`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