`include "../include/tune.v"
module drammem(
input [9:0] ma,
inout [15:0] d,
input ras_n,
input ucas_n,
input lcas_n,
input we_n
);
parameter _verbose_ = 1;
parameter _add_to_addr_ = 0;
parameter _filter_out_ = 32'h91;
parameter _init_ = 1;
reg [15:0] array [0:1048575];
reg [15:0] dout;
reg [19:0] addr;
wire cas_n;
wire idle;
reg was_ras;
reg was_cas;
reg ready;
initial
begin : clear_mem
integer i;
if( _init_ )
begin
for(i=0;i<1048576;i=i+1)
array[i] = 16'hDEAD;
end
end
always @(negedge ras_n)
addr[9:0] <= ma[9:0];
assign cas_n = ucas_n & lcas_n;
always @(negedge cas_n)
begin
addr[19:10] <= ma[9:0];
end
always @(posedge cas_n, negedge cas_n)
ready <= ~cas_n; // to introduce delta-cycle in ready to allow capturing of CAS address before proceeding data
assign idle = ras_n & cas_n;
always @(negedge ras_n, posedge idle)
begin
if( idle )
was_ras <= 1'b0;
else // negedge ras_n
was_ras <= 1'b1;
end
always @(negedge cas_n, posedge idle)
begin
if( idle )
was_cas <= 1'b0;
else
if( was_ras )
was_cas <= 1'b1;
end
assign d = dout;
always @*
begin
if( ready && was_ras && was_cas && we_n && (~idle) ) // idle here is to prevent races at the end of all previous signals, which cause redundant read at the end of write
begin
dout = array[addr];
`ifdef DRAMMEM_VERBOSE
if( _verbose_ == 1 )
begin
if( addr != _filter_out_ )
$display("DRAM read at %t: ($%h)=>$%h",$time,addr*2+_add_to_addr_,dout);
end
`endif
end
else
begin
dout = 16'hZZZZ;
end
end
always @*
if( ready && was_ras && was_cas && (~we_n) && (~idle) )
begin
if( ~ucas_n )
array[addr][15:8] = d[15:8];
if( ~lcas_n )
array[addr][7:0] = d[7:0];
`ifdef DRAMMEM_VERBOSE
if( _verbose_ == 1 )
begin
if( addr != _filter_out_ )
$display("DRAM written at %t: ($%h)<=$%h.$%h",$time,addr*2+_add_to_addr_,ucas_n?8'hXX:d[15:8],lcas_n?8'hXX:d[7:0]);
end
`endif
end
endmodule