📄 tb.v
字号:
Ale = 0;
//Determine how long to wait after the last command latch before toggling Re_n
// tCCS is required during a column address change
// not all designs have tCCS defined, so tWHR would be the default in that case
tCCS_cache = (tCCS_cache_min > tWHR_cache_min) ? tCCS_cache_min : tWHR_cache_min;
tCCS = (tCCS_min > tWHR_min) ? tCCS_min : tWHR_min;
//if last We_n posedge is recent, need to wait to avoid timing violation
if (cache_mode) begin
if (($realtime - tm_wen_pos) < tCCS_cache) begin
#(tCCS_cache - ($realtime - tm_wen_pos));
end
end else begin
if (($realtime - tm_wen_pos) < tCCS) begin
#(tCCS - ($realtime - tm_wen_pos));
end
end
if (($realtime - tm_rbn_pos) < tRR_min) begin
#(tRR_min - ($realtime - tm_rbn_pos));
end
if (($realtime - tm_cen_neg) < tCLR_min) begin
#(tCLR_min - ($realtime - tm_cen_neg));
end
Re_n <= 0;
if (enable_rd_verify) begin //if using this testbench to check the data, enable_rd_verify will be active
if (cache_mode) begin
if (tm_cen_neg + tCEA_cache_max > $realtime) begin
rd_verify <= #(tCEA_cache_max +1) 1'b1;
end else begin
rd_verify <= #(tREA_cache_max +1) 1'b1;
end
end else begin
if (tm_cen_neg + tCEA_max > $realtime) begin
rd_verify <= #(tCEA_max +1) 1'b1;
end else begin
rd_verify <= #(tREA_max +1) 1'b1;
end
end
end
#(tRP);
Re_n <= 1;
#(tRC-tRP);
end
endtask
//pulse Re_n to latch read data
//special timing for Programmable DriveStrength
task latch_read_pio;
parameter trl=tRPIO_min;
parameter trh=tRPIO_min;
begin
Cle = 0;
Ale = 0;
Re_n <= 0;
if (enable_rd_verify) begin //if using this testbench to check the data, enable_rd_verify will be active
rd_verify <= #(tREAIO_max +1) 1'b1;
end
#(trl);
Re_n <= 1;
#(trh);
end
endtask
task latch_address;
input [7 : 0] addr_in;
reg we_setup;
reg ale_setup;
reg cle_setup;
reg ce_setup;
reg io_setup;
reg ale_hold;
reg we_hold;
reg io_hold;
begin
if (sync_mode) begin
end else begin
//these allow us to keep track of how far from the previous
// signal edge we are in real time. No need to delay the
// We_n transitions of timing checks are already met
we_setup = 0;
ale_setup = 0;
cle_setup = 0;
ce_setup = 0;
io_setup = 0;
ale_hold = 0;
we_hold = 0;
io_hold = 0;
Ale = 1'b1;
Io[7:0] = addr_in;
`ifdef x16
Io[15:8] = 8'b0;
`endif
if (($realtime - tm_wen_pos) < tWH) begin
#($realtime - tm_wen_pos);
end
We_n = 1'b0;
//Check Cle
if (cache_mode) begin
if (($realtime - tm_cle_pos) < tCLS_cache_min) begin
cle_setup <= #(tCLS_cache_min - ($realtime - tm_cle_neg)) 1'b1;
end else begin
cle_setup = 1'b1;
end
end else begin
if (($realtime - tm_cle_pos) < tCLS_min) begin
cle_setup <= #(tCLS_min - ($realtime - tm_cle_neg)) 1'b1;
end else begin
cle_setup = 1'b1;
end
end
//Check Ce_n
if (cache_mode) begin
if (($realtime - tm_cen_neg) < tCS_cache_min) begin
ce_setup <= #(tCS_cache_min - ($realtime - tm_cen_neg)) 1'b1;
end else begin
ce_setup = 1'b1;
end
end else begin
if (($realtime - tm_cen_neg) < tCS_min) begin
ce_setup <= #(tCS_min - ($realtime - tm_cen_neg)) 1'b1;
end else begin
ce_setup = 1'b1;
end
end
//Check Cle setup
if (cache_mode) begin
ale_setup <= #tALS_cache_min 1'b1;
io_setup <= #tDS_cache_min 1'b1;
end else begin
ale_setup <= #tALS_min 1'b1;
io_setup <= #tDS_min 1'b1;
end
we_setup <= #tWP 1'b1;
//wait for all setup times to be met
wait (we_setup && ale_setup && cle_setup && ce_setup && io_setup);
We_n = 1;
if (cache_mode) begin
ale_hold <= #tALH_cache_min 1'b1;
io_hold <= #tDH_cache_min 1'b1;
end else begin
ale_hold <= #tALH_min 1'b1;
io_hold <= #tDH_min 1'b1;
end
//user defined or default value
we_hold <= #tWH 1'b1;
//wait for hold times to be met
wait (we_hold && io_hold && ale_hold);
Ale = 0;
Io = {DQ_BITS{1'bz}};
end
end
endtask
//latches the command on IO on posedge We_n
task latch_command;
input [DQ_BITS - 1 : 0] data_in;
reg we_setup;
reg ale_setup;
reg cle_setup;
reg ce_setup;
reg io_setup;
reg trhw_setup;
reg cle_hold;
reg ce_hold;
reg ale_hold;
reg we_hold;
reg io_hold;
real delay;
begin
if (sync_mode) begin
end else begin
//these allow us to keep track of how far from the previous
// signal edge we are in real time. No need to delay the
// We_n transitions of timing checks are already met
we_setup = 0;
ale_setup = 0;
cle_setup = 0;
ce_setup = 0;
io_setup = 0;
trhw_setup = 0;
cle_hold = 0;
ce_hold = 0;
ale_hold = 0;
we_hold = 0;
io_hold = 0;
//If pulsing Re_n to read data was the
//last op, wait for the x's to clear as
//the device may or may not still be driving
//data during the 'x' time. Need to wait for
//the Io bus to be high impedance.
wait (IO !== {DQ_BITS{1'bx}});
Cle = 1'b1;
Io = data_in;
//if we just finished a read, wait for tRHW to be met
if (($realtime - tm_ren_pos) < tRHW_min) begin
trhw_setup <= #(tRHW_min - ($realtime - tm_ren_pos)) 1'b1;
We_n <= #(tRHW_min - ($realtime - tm_ren_pos)) 1'b0;
we_setup <= #(tRHW_min - ($realtime-tm_ren_pos) + tWP) 1'b1;
end else begin
trhw_setup = 1'b1;
We_n = 1'b0;
we_setup <= #tWP 1'b1;
end
//Check Ale
if (cache_mode) begin
if (($realtime - tm_ale_neg) < tALS_cache_min) begin
ale_setup <= #(tALS_cache_min - ($realtime - tm_ale_neg)) 1'b1;
end else begin
ale_setup = 1'b1;
end
end else begin
if (($realtime - tm_ale_neg) < tALS_min) begin
ale_setup <= #(tALS_min - ($realtime - tm_ale_neg)) 1'b1;
end else begin
ale_setup = 1'b1;
end
end
//Check Cle setup
if (cache_mode) begin
cle_setup <= #tCLS_cache_min 1'b1;
io_setup <= #tDS_cache_min 1'b1;
end else begin
cle_setup <= #tCLS_min 1'b1;
io_setup <= #tDS_min 1'b1;
end
//Check Ce_n
#1;
if (cache_mode) begin
if ((Ce_n === 1'b0) && (($realtime - tm_cen_neg) < tCS_cache_min)) begin
ce_setup <= #(tCS_cache_min - ($realtime - tm_cen_neg)) 1'b1;
end else if ((Ce2_n === 1'b0) && (($realtime - tm_ce2n_neg) < tCS_cache_min)) begin
ce_setup <= #(tCS_cache_min - ($realtime - tm_ce2n_neg)) 1'b1;
end else begin
ce_setup = 1'b1;
end
end else begin
if ((Ce_n === 1'b0) && (($realtime - tm_cen_neg) < tCS_min)) begin
ce_setup <= #(tCS_min - ($realtime - tm_cen_neg)) 1'b1;
end else if ((Ce2_n === 1'b0) && (($realtime - tm_ce2n_neg) < tCS_min)) begin
ce_setup <= #(tCS_min - ($realtime - tm_ce2n_neg)) 1'b1;
end else begin
ce_setup = 1'b1;
end
end
//wait for all setup times to be met
wait (we_setup && ale_setup && cle_setup && ce_setup && io_setup && trhw_setup);
We_n = 1;
if (cache_mode) begin
cle_hold <= #tCLH_cache_min 1'b1;
ale_hold <= #tALH_cache_min 1'b1;
io_hold <= #tDH_cache_min 1'b1;
end else begin
cle_hold <= #tCLH_min 1'b1;
ale_hold <= #tALH_min 1'b1;
io_hold <= #tDH_min 1'b1;
end
//user defined or default value
we_hold <= #tWH 1'b1;
//wait for hold times to be met
wait (we_hold && io_hold && ale_hold && cle_hold);
Cle = 0;
if ((Io[7:0] !== 8'h70) && (Io[7:0] !== 8'h78)) lastCmd = Io;
Io = {DQ_BITS{1'bz}};
end
end
endtask
task latch_command_pio;
input [DQ_BITS - 1 : 0] data_in;
begin
#(tRHW_min + tCLSIO_min);
We_n = 0;
Ale = 0;
Cle = 1;
Io = data_in;
#tWPIO_min;
We_n = 1;
#(tWHIO_min + tCLHIO_min);
Cle = 0;
Io = {DQ_BITS{1'bz}};
end
endtask
task latch_data_sync;
input [DQ_BITS -1: 0] data0_in;
input [DQ_BITS -1: 0] data1_in;
begin
end
endtask
//pulse we to latch write data
task latch_data_async;
input [DQ_BITS - 1 : 0] data_in;
begin
We_n = 0;
Io = data_in;
//tWP is almost always > tDS_min
//tWH is almost always > tDH_min
if (tWP > tDS_min) begin
#tWP;
end else begin
#tDS_min;
end
//wait for tCCS if this was a column change
if ((($realtime - tm_wen_pos) < tCCS_min) && ((lastCmd === 8'h85) || (lastCmd === 8'hE0))) begin
#(tCCS_min - ($realtime - tm_wen_pos));
end
We_n = 1;
if (tWH > tDH_min) begin
#tWH;
end else begin
#tDH_min;
end
Io = {DQ_BITS{1'bz}};
end
endtask
task latch_data_pio;
input [DQ_BITS - 1 : 0] data_in;
begin
#(tWPIO_min - (tWHIO_min - tDHIO_min));
We_n = 0;
Ale = 0;
#(tWPIO_min-tDSIO_min);
Ale = 0;
Io = data_in;
#tWPIO_min; // 10 ns
We_n = 1;
#(tWCIO_min - tWPIO_min);
//#tDH_min;
Io = {DQ_BITS{1'bz}};
#(tWHIO_min-tDHIO_min);
end
endtask
// Status Read (70h)
task status_read;
begin
$display ("%m at time %t", $realtime);
latch_command (8'h70);
#tWHR_min;
end
endtask
//No Op
task nop;
input trc;
real trc;
begin
#trc;
end
endtask
task go_idle;
begin
end
endtask
// 0 = regular lock, 1 = locktight
task lock_block;
input locktight;
begin
if (locktight === 1'b1) begin
latch_command(8'h2C);
end else begin
latch_command(8'h2A);
end
end
endtask
task get_drivestrength;
begin
// Decode Command
latch_command_pio (8'hB8);
#tWHRIO_min;
end
endtask
task set_drivestrength;
input [7 : 0] drivestrength;
begin
// Decode Command
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -