📄 tb.v
字号:
latch_command_pio (8'hB8);
latch_data_pio (drivestrength);
#tWHRIO_min;
end
endtask
task get_features;
input [7 : 0] feature_address;
begin
latch_command (8'hEE);
latch_address (feature_address);
//use wait_ready task to wait for busy to return inactive
//then use serial_read task to output data
end
endtask
task set_features;
input [7 : 0] feature_address;
//these are defined as only 8 bit features regardless of DQ_BITS width
input [7:0] p1;
input [7:0] p2;
input [7:0] p3;
input [7:0] p4;
begin
Ce_n <=0;
if (feature_address == 8'h01) begin
Ce2_n <= 0;
end
if (sync_mode == 0) begin
#tCS_min; //avoid CE setup time violation if we're in async mode
end
latch_command (8'hEF);
latch_address (feature_address);
#tADL_min;
if (sync_mode) begin
latch_data_sync (p1,p1);
latch_data_sync (p2,p2);
latch_data_sync (p3,p3);
latch_data_sync (p4,p4);
go_idle;
end else begin
latch_data_async (p1);
latch_data_async (p2);
latch_data_async (p3);
latch_data_async (p4);
end
end
endtask
// multi die status read
task multi_die_status_read;
input [BLCK_BITS - 1 : 0] blck_addr;
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 [23 :00] tsk_row_addr;
begin
// Decode Address
tsk_row_addr = fn_row_addr(blck_addr, 0, 1'b0);
row_addr_1 = tsk_row_addr[07:00];
row_addr_2 = tsk_row_addr[15:08];
row_addr_3 = tsk_row_addr[23:16];
// Decode Command
latch_command (8'h78);
latch_address (row_addr_1);
latch_address (row_addr_2);
latch_address (row_addr_3);
#(tWHR_min);
end
endtask
// locked block status read
task block_lock_status_read;
input [BLCK_BITS - 1 : 0] blck_addr;
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 [23 : 0] tsk_row_addr;
begin
// Decode Address
tsk_row_addr = fn_row_addr(blck_addr, 0, 1'b0);
row_addr_1 = tsk_row_addr[07:00];
row_addr_2 = tsk_row_addr[15:08];
row_addr_3 = tsk_row_addr[23:16];
// Decode Command
latch_command (8'h7A);
latch_address (row_addr_1);
latch_address (row_addr_2);
latch_address (row_addr_3);
#tWHR_min;
end
endtask
task unlock_block;
input [BLCK_BITS - 1 : 0] blck_addr_one;
input [BLCK_BITS - 1 : 0] blck_addr_two;
input invert;
reg [DQ_BITS - 1 : 0] row_addr_1_one;
reg [DQ_BITS - 1 : 0] row_addr_2_one;
reg [DQ_BITS - 1 : 0] row_addr_3_one;
reg [DQ_BITS - 1 : 0] row_addr_1_two;
reg [DQ_BITS - 1 : 0] row_addr_2_two;
reg [DQ_BITS - 1 : 0] row_addr_3_two;
reg [23 : 0] tsk_row_addr;
reg [23 : 0] tsk_row_addr2;
begin
tsk_row_addr = fn_row_addr(blck_addr_one, 0, 1'b0);
row_addr_1_one = {tsk_row_addr[07:01], (tsk_row_addr[00] | invert)};
row_addr_2_one = tsk_row_addr[15:08];
tsk_row_addr2 = fn_row_addr(blck_addr_two, 0, 1'b0);
row_addr_1_two = {tsk_row_addr2[07:01], (tsk_row_addr2[00] | invert)};
row_addr_2_two = tsk_row_addr2[15:08];
row_addr_3_one = tsk_row_addr[23:16];
row_addr_3_two = tsk_row_addr2[23:16];
// Decode Command
latch_command (8'h23);
latch_address (row_addr_1_one);
latch_address (row_addr_2_one);
latch_address (row_addr_3_one);
latch_command (8'h24);
latch_address (row_addr_1_two);
latch_address (row_addr_2_two);
latch_address (row_addr_3_two);
#tWHR_min;
end
endtask
// Erase Block (60h -> D0h)
// tp = address is 1st of two planes
task erase_block;
input [BLCK_BITS - 1 : 0] blck_addr;
input tp;
input onfi;
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 [23 : 0] tsk_row_addr;
begin
// Decode Address
tsk_row_addr = fn_row_addr(blck_addr, 0, 1'b0);
row_addr_1 = tsk_row_addr[07:00];
row_addr_2 = tsk_row_addr[15:08];
row_addr_3 = tsk_row_addr[23:16];
// Decode Command
latch_command (8'h60);
latch_address (row_addr_1);
latch_address (row_addr_2);
latch_address (row_addr_3);
if (~tp) begin
latch_command (8'hD0);
end else if (onfi) begin
latch_command (8'hD1);
end
#tRR_min;
end
endtask
// Multi-Plane Page Read (00h -> 32h)
// blck_addr = block address
// page_addr = page address
// col_addr = column address
//
// This is an ONFI 2.0 command : queues a plane to be read during a multi-plane page read
//
task multiplane_read_page;
input [BLCK_BITS - 1 : 0] blck_addr;
input [PAGE_BITS - 1 : 0] page_addr;
input [COL_BITS - 1 : 0] col_addr;
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 [23 :00] tsk_row_addr;
begin
// Decode Address
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 and address sequence
latch_command (8'h00);
latch_address (col_addr_1);
latch_address (col_addr_2);
latch_address (row_addr_1);
latch_address (row_addr_2);
latch_address (row_addr_3);
latch_command (8'h32);
end
endtask //multiplane_read_page
// Page Read (00h -> [30h])
// blck_addr = block address
// page_addr = page address
// col_addr = column address
// tp = address is 1st of two planes
// idm = read for internal data move
// otp = OTP page read
//
// For twoplane, first issue read_page with tp=1, output == 00h with address
// followed by read_page with tp=0, output == 00h with address and 30h
//
task read_page;
input [BLCK_BITS - 1 : 0] blck_addr;
input [PAGE_BITS - 1 : 0] page_addr;
input [COL_BITS - 1 : 0] col_addr;
input tp;
input idm;
input otp;
input copyback2;
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 [23 :00] tsk_row_addr;
begin
//once another page read starts, we're not in cache page read anymore
if (otp && (tp || idm)) $display("%m at time %t: ERROR: Illegal task option. Can't read OTP page with twoplane or internal data move", $realtime);
// Decode Address
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];
// Decode Command
if (otp) begin
latch_command (8'hAF);
end else begin
latch_command (8'h00);
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
if (~tp) begin
if (idm) begin
latch_command (8'h35);
end else begin
if (copyback2) begin
latch_command (8'h3A);
end else begin
latch_command (8'h30);
end
end
end
//$display("%m at time %t: INFO: Read Page block addr=%s, page addr=%s, column addr=%s", $realtime,blck_addr, page_addr, col_addr);
end
endtask
task cache_read;
input last;
begin
if (last) begin
latch_command(8'h3F);
end else begin
latch_command(8'h31);
end
end
endtask
task cache_read_random;
input [BLCK_BITS - 1 : 0] blck_addr;
input [PAGE_BITS - 1 : 0] page_addr;
input [COL_BITS - 1 : 0] col_addr;
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 [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'h00);
latch_address (col_addr_1);
latch_address (col_addr_2);
latch_address (row_addr_1);
latch_address (row_addr_2);
latch_address (row_addr_3);
latch_command (8'h31);
end
endtask
//tp = 0 = page random data (2 address cycles)
// 1 = two-plane random data (5 address cycles)
task random_data_read;
input [BLCK_BITS - 1 : 0] blck_addr;
input [PAGE_BITS - 1 : 0] page_addr;
input [COL_BITS - 1 : 0] col_addr;
input tp;
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 [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];
if (tp) begin
latch_command (8'h06);
latch_address (col_addr_1);
latch_address (col_addr_2);
latch_address (row_addr_1);
latch_address (row_addr_2);
latch_address (row_addr_3);
end else begin
latch_command (8'h05);
latch_address (col_addr_1);
latch_address (col_addr_2);
end
latch_command (8'hE0);
#tWHR_min;
end
endtask
// Program Page (80h -> 10h)
// blck_addr = block address
// page_addr = page address
// col_addr = column address
// data = your first data value
// size = number of serial data to be written
// pattern = modify data pattern
// 00 = no change
// 01 = inc
// 10 = dec
// 11 = random
// tp = address is 1st of two planes
// idm = program for internal data move
// 0 = no idm
// 1 = program for internal data move (for 2plane, 1st half of idm program)
// otp = OTP page read
// cache = cache mode program (not last page)
// final = if low, will not finalize write -- indicates that a random data write will follow
task program_page;
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 idm;
input otp;
input cache;
input copyback2;
input finalCmd;
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 [23 :00] tsk_row_addr;
reg [COL_BITS - 1 : 0] i;
begin
if (otp && (tp || idm || cache)) $display("%m at time %t: ERROR: Illegal task option. Can't write OTP page with cache, twoplane, or internal data move commands", $realtime);
// Decode Address
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];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -