📄 ddr2.v
字号:
`else reg [BL_MAX*DQ_BITS-1:0] memory [0:`MEM_SIZE-1]; reg [`MAX_BITS-1:0] address [0:`MEM_SIZE-1]; reg [MEM_BITS:0] memory_index; reg [MEM_BITS:0] memory_used;`endif // receive reg ck_in; reg ck_n_in; reg cke_in; reg cs_n_in; reg ras_n_in; reg cas_n_in; reg we_n_in; reg [15:0] dm_in; reg [2:0] ba_in; reg [15:0] addr_in; reg [63:0] dq_in; reg [31:0] dqs_in; reg odt_in; reg [15:0] dm_in_pos; reg [15:0] dm_in_neg; reg [63:0] dq_in_pos; reg [63:0] dq_in_neg; reg dq_in_valid; reg dqs_in_valid; integer wdqs_cntr; integer wdq_cntr; integer wdqs_pos_cntr [31:0]; reg b2b_write; reg [31:0] prev_dqs_in; reg diff_ck; always @(ck ) ck_in <= #BUS_DELAY ck; always @(ck_n ) ck_n_in <= #BUS_DELAY ck_n; always @(cke ) cke_in <= #BUS_DELAY cke; always @(cs_n ) cs_n_in <= #BUS_DELAY cs_n; always @(ras_n ) ras_n_in <= #BUS_DELAY ras_n; always @(cas_n ) cas_n_in <= #BUS_DELAY cas_n; always @(we_n ) we_n_in <= #BUS_DELAY we_n; always @(dm_rdqs) dm_in <= #BUS_DELAY dm_rdqs; always @(ba ) ba_in <= #BUS_DELAY ba; always @(addr ) addr_in <= #BUS_DELAY addr; always @(dq ) dq_in <= #BUS_DELAY dq; always @(dqs or dqs_n) dqs_in <= #BUS_DELAY (dqs_n<<16) | dqs; always @(odt ) odt_in <= #BUS_DELAY odt; // create internal clock always @(posedge ck_in) diff_ck <= ck_in; always @(posedge ck_n_in) diff_ck <= ~ck_n_in; wire [15:0] dqs_even = dqs_in[15:0]; wire [15:0] dqs_odd = dqs_n_en ? dqs_in[31:16] : ~dqs_in[15:0]; wire [3:0] cmd_n_in = !cs_n_in ? {ras_n_in, cas_n_in, we_n_in} : NOP; //deselect = nop // transmit reg dqs_out_en; reg [DQS_BITS-1:0] dqs_out_en_dly; reg dqs_out; reg [DQS_BITS-1:0] dqs_out_dly; reg dq_out_en; reg [DQ_BITS-1:0] dq_out_en_dly; reg [DQ_BITS-1:0] dq_out; reg [DQ_BITS-1:0] dq_out_dly; integer rdqsen_cntr; integer rdqs_cntr; integer rdqen_cntr; integer rdq_cntr; bufif1 buf_dqs [DQS_BITS-1:0] (dqs, dqs_out_dly, dqs_out_en_dly & {DQS_BITS{out_en}}); bufif1 buf_dm [DM_BITS-1:0] (dm_rdqs, dqs_out_dly, dqs_out_en_dly & {DM_BITS {out_en}} & {DM_BITS{rdqs_en}}); bufif1 buf_dqs_n [DQS_BITS-1:0] (dqs_n, ~dqs_out_dly, dqs_out_en_dly & {DQS_BITS{out_en}} & {DQS_BITS{dqs_n_en}}); bufif1 buf_rdqs_n [DQS_BITS-1:0] (rdqs_n, ~dqs_out_dly, dqs_out_en_dly & {DQS_BITS{out_en}} & {DQS_BITS{dqs_n_en}} & {DQS_BITS{rdqs_en}}); bufif1 buf_dq [DQ_BITS-1:0] (dq, dq_out_dly, dq_out_en_dly & {DQ_BITS {out_en}}); initial begin if (BL_MAX < 2) $display("%m ERROR: BL_MAX parameter must be >= 2. \nBL_MAX = %d", BL_MAX); if ((1<<BO_BITS) > BL_MAX) $display("%m ERROR: 2^BO_BITS cannot be greater than BL_MAX parameter."); $timeformat (-12, 1, " ps", 1); reset_task; seed = RANDOM_SEED; ck_cntr = 0; end // calculate the absolute value of a real number function real abs_value; input arg; real arg; begin if (arg < 0.0) abs_value = -1.0 * arg; else abs_value = arg; end endfunction`ifdef MAX_MEM`else function get_index; input [`MAX_BITS-1:0] addr; begin : index get_index = 0; for (memory_index=0; memory_index<memory_used; memory_index=memory_index+1) begin if (address[memory_index] == addr) begin get_index = 1; disable index; end end end endfunction`endif task memory_write; input [BA_BITS-1:0] bank; input [ROW_BITS-1:0] row; input [COL_BITS-1:0] col; input [BL_MAX*DQ_BITS-1:0] data; reg [`MAX_BITS-1:0] addr; begin // chop off the lowest address bits addr = {bank, row, col}/BL_MAX;`ifdef MAX_MEM memory[addr] = data;`else if (get_index(addr)) begin address[memory_index] = addr; memory[memory_index] = data; end else if (memory_used == `MEM_SIZE) begin $display ("%m: at time %t ERROR: Memory overflow. Write to Address %h with Data %h will be lost.\nYou must increase the MEM_BITS parameter or define MAX_MEM.", $time, addr, data); if (STOP_ON_ERROR) $stop(0); end else begin address[memory_used] = addr; memory[memory_used] = data; memory_used = memory_used + 1; end`endif end endtask task memory_read; input [BA_BITS-1:0] bank; input [ROW_BITS-1:0] row; input [COL_BITS-1:0] col; output [BL_MAX*DQ_BITS-1:0] data; reg [`MAX_BITS-1:0] addr; begin // chop off the lowest address bits addr = {bank, row, col}/BL_MAX;`ifdef MAX_MEM data = memory[addr];`else if (get_index(addr)) begin data = memory[memory_index]; end else begin data = {BL_MAX*DQ_BITS{1'bx}}; end`endif end endtask // Before this task runs, the model must be in a valid state for precharge power down. // After this task runs, NOP commands must be issued until tRFC has been met task initialize; input [ADDR_BITS-1:0] mode_reg0; input [ADDR_BITS-1:0] mode_reg1; input [ADDR_BITS-1:0] mode_reg2; input [ADDR_BITS-1:0] mode_reg3; begin if (DEBUG) $display ("%m: at time %t INFO: Performing Initialization Sequence", $time); cmd_task(1, NOP, 'bx, 'bx); cmd_task(1, PRECHARGE, 'bx, 1<<AP); // Precharege ALL cmd_task(1, LOAD_MODE, 3, mode_reg3); cmd_task(1, LOAD_MODE, 2, mode_reg2); cmd_task(1, LOAD_MODE, 1, mode_reg1); cmd_task(1, LOAD_MODE, 0, mode_reg0 | 'h100); // DLL Reset cmd_task(1, PRECHARGE, 'bx, 1<<AP); // Precharege ALL cmd_task(1, REFRESH, 'bx, 'bx); cmd_task(1, REFRESH, 'bx, 'bx); cmd_task(1, LOAD_MODE, 0, mode_reg0); cmd_task(1, LOAD_MODE, 1, mode_reg1 | 'h380); // OCD Default cmd_task(1, LOAD_MODE, 1, mode_reg1); cmd_task(0, NOP, 'bx, 'bx); end endtask task reset_task; integer i; begin // disable inputs dq_in_valid = 0; dqs_in_valid <= 0; wdqs_cntr = 0; wdq_cntr = 0; for (i=0; i<32; i=i+1) begin wdqs_pos_cntr[i] <= 0; end b2b_write <= 0; // disable outputs out_en = 0; dqs_n_en = 0; rdqs_en = 0; dq_out_en = 0; rdq_cntr = 0; dqs_out_en = 0; rdqs_cntr = 0; // disable ODT odt_en = 0; odt_state = 0; // reset bank state active_bank = {`BANKS{1'b1}};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -