📄 tb.v
字号:
// Decode Command
if (otp) begin
latch_command (8'hA0);
end else begin
if (idm) begin
latch_command (8'h85);
end else begin
if (copyback2) begin
latch_command (8'h8C);
end else begin
latch_command (8'h80);
end
end
end
latch_address (col_addr_1);
latch_address (col_addr_2);
latch_address (row_addr_1);
if (otp) begin
latch_address (8'h00);
latch_address (8'h00);
end else begin
latch_address (row_addr_2);
latch_address (row_addr_3);
end
#tADL_min;
if (~idm && (size != 0)) begin
//only input data if not an internal data move
//random data writes are in a separate task
write_data(data, size, pattern);
end
// Done Program
if (finalCmd) begin
if (tp) begin
latch_command (8'h11);
end else begin
if (cache) begin
latch_command (8'h15);
end else begin
//if (~idm[0]) begin
latch_command (8'h10);
//end
end
end
end
end
endtask
// write data pattern, addresses already input
task write_data;
input [DQ_BITS - 1 : 0] data;
input [COL_BITS - 1 : 0] size;
input [1 : 0] pattern;
integer i;
begin
// Decode Pattern
if (sync_mode) begin
for (i = 0; i <= size - 1; i = i + 2) begin
case (pattern)
2'b00 : latch_data_sync (data,data);
2'b01 : latch_data_sync (data + i, data + (i+1));
2'b10 : latch_data_sync (data - i, data - (i+1));
2'b11 : latch_data_sync ({$random} % {DQ_BITS{1'b1}}, {$random} % {DQ_BITS{1'b1}});
endcase
end
go_idle;
end else begin
for (i = 0; i <= size - 1; i = i + 1) begin
case (pattern)
2'b00 : latch_data_async (data);
2'b01 : latch_data_async (data + i);
2'b10 : latch_data_async (data - i);
2'b11 : latch_data_async ({$random} % {DQ_BITS{1'b1}});
endcase
end
end
end
endtask
//used to write data to a random col address on current page
// tp = address is 1st of two planes
// cache = cache mode program (not last page)
// final = if low, will not finalize write -- indicates that a random data write will follow
task random_data_write;
input [BLCK_BITS - 1 : 0] blck_addr;
input [PAGE_BITS - 1 : 0] page_addr;
input [COL_BITS - 1 : 0] col_addr;
input [DQ_BITS - 1 : 0] data;
input [COL_BITS - 1 : 0] size;
input [1 : 0] pattern;
input tp;
input cache;
input finalCmd;
input column_only; //used to determine whether this is a 5-address row change, or a 2-address column change
reg [DQ_BITS - 1 : 0] col_addr_1;
reg [DQ_BITS - 1 : 0] col_addr_2;
reg [DQ_BITS - 1 : 0] row_addr_1;
reg [DQ_BITS - 1 : 0] row_addr_2;
reg [DQ_BITS - 1 : 0] row_addr_3;
reg [COL_BITS - 1 : 0] i;
reg [23 :00] tsk_row_addr;
begin
col_addr_1 [7 : 0] = col_addr [7 : 0];
col_addr_2 [7 : 0] = {{(16 - COL_BITS){1'b0}}, col_addr [(COL_BITS -1) : 8]};
tsk_row_addr = fn_row_addr(blck_addr, page_addr, 1'b1);
row_addr_1 = tsk_row_addr[07:00];
row_addr_2 = tsk_row_addr[15:08];
row_addr_3 = tsk_row_addr[23:16];
latch_command (8'h85);
latch_address (col_addr_1);
latch_address (col_addr_2);
if (~column_only) begin
latch_address(row_addr_1);
latch_address(row_addr_2);
latch_address(row_addr_3);
end
#tADL_min;
write_data(data, size, pattern);
if (finalCmd) begin
if (tp) begin
latch_command (8'h11);
end else begin
if (cache) begin
latch_command (8'h15);
end else begin
latch_command (8'h10);
end
end
end
end
endtask
task OTP_protect;
begin
// Decode Command
latch_command (8'hA5);
latch_address (8'h00);
latch_address (8'h00);
latch_address (8'h01);
latch_address (8'h00);
latch_address (8'h00);
latch_command (8'h10);
wait_ready;
end
endtask
// reset (FFh) -
task sync_reset;
begin
latch_command (8'hFC);
end
endtask
// reset (FFh) -
task reset;
begin
latch_command (8'hFF);
`ifdef SYNC2ASYNCRESET
We_n <= 1'b1; // switching from sync to async mode after reset // ??? awaiting timing answer
`endif
end
endtask
// Read ID (90h) -
task read_id;
integer i;
begin
latch_command (8'h90);
latch_address (0);
#tWHR_min
for (i = 0; i < NUM_ID_BYTES; i = i + 1)
begin
latch_read; // Byte i
end
end
endtask
//reads static ONFI regs
task read_onfi;
begin
latch_command (8'h90);
latch_address (8'h20);
#tWHR_min;
end
endtask
//command address sequence required to access ONFI parameter data page
//can't really use serial_read here cuz won't know all expected data
task read_onfi_params;
begin
latch_command (8'hEC);
latch_address (8'h00);
end
endtask
// Read speacial
// special = special page read data
// 0 = read ID2
// 1 = read unique
task read_special; // Not inherited from read_id, rather from page_read
input sel;
reg [12:0] i;
begin
latch_command (8'h30);
latch_command (8'h65);
latch_command (8'h00);
latch_address (0);
if (sel) begin
//read_unique
latch_address (0);
end else begin
//read_id2
latch_address (2);
end
latch_address (2);
latch_address (0);
latch_address (0);
latch_command (8'h30);
wait_ready;
#tRR_min;
// Serial Read
for (i = 0; i <= 255; i = i + 1)
begin
latch_read; // Byte 0
end
#tRR_min;
end
endtask
//new ONFI read unique command sequence
//leave it up to use to latch read data
task read_unique;
begin
latch_command (8'hED);
latch_address (0);
#tRR_min;
end
endtask
//pulse Re_n (async) or wait for Dqs (sync) and compares output data to expected value
task serial_read;
input [DQ_BITS -1: 0] data;
input [1:0] pattern;
input [ROW_BITS -1: 0] size;
integer i;
begin
// Serial Read
$display ("%m at time %t: READ DATA : size=%0d,\t data=%0h,\t pattern=%0d", $realtime, size, data, pattern);
//async serial read
for (i = 0; i <= size - 1; i = i + 1) begin
latch_and_check_data(data);
case (pattern)
2'b00 : ;
2'b01 : data = data + 1;
2'b10 : data = data - 1;
2'b11 : data = 0;
endcase
end
#tRR_min;
end
endtask
task serial_read_pio;
input [DQ_BITS -1: 0] data;
begin
latch_and_check_data_pio(data);
#tRR_min;
end
endtask
task latch_and_check_data;
input [DQ_BITS -1: 0] exp_data;
begin
if (sync_mode) begin
end else begin
rd_dq = exp_data;
//enable rd verify tells the latch read task
// whether or not to toggle rd_verify to check data
enable_rd_verify = 1'b1;
latch_read;
enable_rd_verify = 1'b0;
end
end
endtask
task latch_and_check_data_pio;
input [DQ_BITS -1: 0] exp_data;
begin
rd_dq = exp_data;
//rd_verify <= 1;
enable_rd_verify = 1'b1;
latch_read_pio;
enable_rd_verify = 1'b0;
end
endtask
//always @(IO) begin : data_verify
//integer i;
always @ (posedge rd_verify ) begin
// Verify the data word after output delay
//if ((IO ^ rd_dq) !== {DQ_BITS{1'b0}}) begin
if (IO !== rd_dq) begin
$display ("%m at time %t: ERROR: Read data miscompare: Expected = %h, Actual = %h", $realtime, rd_dq, IO);
end
rd_verify <= #1 1'b0;
end
//end
reg test_done;
initial test_done = 0;
// End-of-test triggered in 'subtest.vh'
always @(test_done) begin : all_done
if (test_done == 1) begin
#5000
$display ("%m at time %t: Simulation is Complete", $realtime);
$stop(0);
$finish;
end
end
wire DEADMAN_REQ = 1'b0;
integer DEADMAN_TIMER = 0;
parameter DEADMAN_LIMIT = 10000000 ;
always @ (posedge Clk_int)
begin
if (DEADMAN_REQ == 1'b1)
DEADMAN_TIMER = 0;
else
DEADMAN_TIMER = DEADMAN_TIMER + 1 ;
if (DEADMAN_TIMER == DEADMAN_LIMIT)
begin
$display ("SWM: No Activity in %d Clocks. Deadman Timer at time %t!!", DEADMAN_TIMER, $time);
$stop();
end
end
// task clear_data_regs;
// input [1:0] die_num;
// input [1:0] plane;
// begin
// case (die_num)
// 2'b00 : force uut.uut_0.clear_data_register(plane);
// 2'b01 : force uut.uut_1.clear_data_register(plane);
// 2'b10 : force uut.uut_2.clear_data_register(plane);
// 2'b11 : force uut.uut_3.clear_data_register(plane);
// endcase
// end
// endtask
//
// task clear_cache_regs;
// input [1:0] die_num;
// input [1:0] plane;
// begin
// case (die_num)
// 2'b00 : force uut.uut_0.clear_cache_register(plane);
// 2'b01 : force uut.uut_1.clear_cache_register(plane);
// 2'b10 : force uut.uut_2.clear_cache_register(plane);
// 2'b11 : force uut.uut_3.clear_cache_register(plane);
// endcase
// end
// endtask
`ifdef INIT_MEM
initial begin
#1;
//
//preloading of mem_array can be done here
// This approach is more flexible than readmemh
//
// memory_write(block, page, col, mem_select, data)
// mem_select : 0 = flash memory array
// 1 = OTP array
// 2 = special config data array
//
uut.uut_0.memory_write(0,0,0, 0, 8'h00);
uut.uut_0.memory_write(0,0,1, 0, 8'h01);
uut.uut_0.memory_write(0,0,2, 0, 8'h02);
uut.uut_0.memory_write(0,0,3, 0, 8'h03);
uut.uut_0.memory_write(0,0,4, 0, 8'h04);
uut.uut_0.memory_write(0,0,5, 0, 8'h05);
uut.uut_0.memory_write(0,0,6, 0, 8'h06);
end
`endif
`include "subtest.vh"
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -