📄 ddr2.v
字号:
end
always @(cas_latency_clocks or add_latency_clocks) begin read_latency = cas_latency_clocks + add_latency_clocks; write_latency = read_latency - 1; if ((read_latency*2 > MAX_CMD_QUEUE) || (write_latency*2 > MAX_CMD_QUEUE)) begin $display("%m at time %t ERROR: Command Queue Overflow. You must increase the MAX_CMD_QUEUE parameter.", $time); if (!no_halt) $stop(0); end end // Check the initialization sequence
always @ (posedge cke_in_one_clk_back) begin
if (!power_up_done) begin`ifdef FULL_MEM for (i=0; i<=((1<<BA_BITS+ROW_BITS+COL_BITS-3)-1); i=i+1) begin //erase memory ... one address at a time MEM[i] <= 'bx; end`else mem_used <= 0; //erase memory`endif if (200000000 > $time) $display ("%m at time %t WARNING: A 200 us delay is required before CKE can transition HIGH.", $time); if ((cmd_chk + 200000000 > $time) || (cmd !== `NOP)) $display("%m: at time %t WARNING: NOP or DESELECT should be maintained for 200 us before CKE transitions HIGH", $time); wait (clk_in && cke_in && (cmd == `PRE)) if (tcke_chk + 400000 > $time) $display ("%m at time %t WARNING: A 400 ns delay is required before Precharge All can be issued after CKE transitions HIGH.", $time); @ (posedge dll_enabled) begin //Enable the DLL @ (posedge dll_reset) begin //Reset the DLL wait (ext_mode_reg_2_set && ext_mode_reg_3_set) begin aref_count <= 0; precharged_banks = 0; activated_banks = {1<<BA_BITS{1'b1}}; //require PRECHARGE commands or PRECHARGE ALL wait (aref_count >= 2) begin //2 or more AUTO REFRESH commands wait (ext_mode_reg_1[9:7] == 3'b111) begin //OCD Default wait (ext_mode_reg_1[9:7] == 3'b000) begin //OCD Exit wait(!dll_reset) begin //clear DLL reset in MR if (debug) $display ("%m: at time %t MEMORY: Power Up and Initialization Sequence is complete", $time); power_up_done <= 1; end end end end end end end end end
// Main always loop
always @(clk_in) begin data_task; if (clk_in) begin cmd_task; // clk and odt pins are disabled during self refresh if (!self_refresh_enter) begin // ODT if (odt_enabled) begin if (odt_event + tis > $time) $display ("%m: at time %t ERROR: tIS violation on ODT by %t", $time, odt_event + tis - $time); odt_in_pipe[0] = odt_in; if (odt_in_pipe[1] ^ odt_in) begin if (txp_chk + taxpd*tck > $time) $display ("%m: at time %t ERROR: tAXPD violation during ODT transition", $time); tanpd_chk = $time; if (tmrd_chk > 0) if (tmrd_chk + 8*tck > $time) $display ("%m: at time %t ERROR: tMRD violation during ODT transition. 8 clocks are required.", $time); end end end // check setup of command signals if ($time > tis) begin if (cke_event + tis > $time) $display ("%m: at time %t ERROR: tIS violation on CKE by %t", $time, cke_event + tis - $time); if (cke_in) begin if (cs_n_event + tis > $time) $display ("%m: at time %t ERROR: tIS violation on CS_N by %t", $time, cs_n_event + tis - $time); if (ras_n_event + tis > $time) $display ("%m: at time %t ERROR: tIS violation on RAS_N by %t", $time, ras_n_event + tis - $time); if (cas_n_event + tis > $time) $display ("%m: at time %t ERROR: tIS violation on CAS_N by %t", $time, cas_n_event + tis - $time); if (we_n_event + tis > $time) $display ("%m: at time %t ERROR: tIS violation on WE_N by %t", $time, we_n_event + tis - $time); for (i=0; i< 3; i=i+1) begin if (ba_event[i] + tis > $time) $display ("%m: at time %t ERROR: tIS violation on BA bit %d by %t", $time, i, ba_event[i] + tis - $time); end for (i=0; i<16; i=i+1) begin if (addr_event[i] + tis > $time) $display ("%m: at time %t ERROR: tIS violation on ADDR bit %d by %t", $time, i, addr_event[i] + tis - $time); end end end clk_rise_event <= $time; end else begin odt_in_pipe[0] = odt_in_pipe[1]; clk_fall_event = $time; end // ODT if (~self_refresh_enter & odt_enabled) begin // async ODT mode applies: // 1.) during slow exit power down // 2.) during precharge power down // 3.) until tAXPD has been satisfied if ((power_down_enter && (low_power || &precharged_banks)) || (txp_chk + taxpd*tck > $time)) begin if (odt_in_pipe[0]) begin odt_data = #(taonpd) 1'b1; end else begin odt_data = #(taofpd) 1'b0; end // sync ODT mode applies: // 1.) during normal operation // 2.) during fast exit power down end else begin if (odt_in_pipe[$rtoi(taond*2.0)]) begin odt_data = 1'b1; end else if (~odt_in_pipe[$rtoi(taofd*2.0)]) begin odt_data = 1'b0; end end end end
always @(dqs_in[0]) dqs_receiver(0); always @(dqs_in[1]) dqs_receiver(1); always @(dqs_in[2]) dqs_receiver(2); always @(dqs_in[3]) dqs_receiver(3); task dqs_receiver; input i; integer i; begin if (dqs_in[i]) begin case (i) 0: dq_in_pos[i] <= dq_in[ 7: 0]; 1: dq_in_pos[i] <= dq_in[15: 8]; 2: dq_in_pos[i] <= dq_in[23:16]; 3: dq_in_pos[i] <= dq_in[31:24]; endcase dm_in_pos[i] <= dm_in[i]; end else if (!dqs_in[i]) begin case (i) 0: dq_in_neg[i] <= dq_in[ 7: 0]; 1: dq_in_neg[i] <= dq_in[15: 8]; 2: dq_in_neg[i] <= dq_in[23:16]; 3: dq_in_neg[i] <= dq_in[31:24]; endcase dm_in_neg[i] <= dm_in[i]; end end endtask task reset_task; begin // disable inputs data_in_enable = 0; data_dqs_in_enable = 0; data_in_valid = 0; // disable outputs outputs_enabled = 0; dqs_n_enabled = 0; rdqs_enabled = 0; // disable ODT odt_enabled = 0; odt_data = 0; // reset bank state precharged_banks = 0; activated_banks = {1<<BA_BITS{1'b1}}; auto_precharge = 0; // require initialization sequence power_up_done <= 0; ext_mode_reg_2_set = 0; ext_mode_reg_3_set = 0; // reset DLL dll_reset = 0; dll_enabled = 0; dll_locked = 0; // exit power down and self refresh power_down_enter = 0; self_refresh_enter = 0; end endtask task get_mem_index;
input [BA_BITS+ROW_BITS+COL_BITS-3-1 : 0] add;
begin
`ifdef FULL_MEM
mem_index = add;
found = 1;
`else
mem_index = 0;
found = 0;
while ((mem_index < mem_used) && !found) begin
if (ADD[mem_index] === add)
found = 1;
else
mem_index = mem_index + 1;
end
`endif
end
endtask
task write_mem;
input [BA_BITS+ROW_BITS+COL_BITS-3-1 : 0] add;
input [8*DQ_BITS - 1 : 0] data;
begin
get_mem_index(add);
`ifdef FULL_MEM
`else
if (!found) begin
if (mem_used === (1<<MEM_BITS)) begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -