create test 1(sequential access to first,middle,last rows) and test 2(random access)

This commit is contained in:
AngeloJacobo 2023-06-15 17:46:14 +08:00
parent 0923fdc0b6
commit 1937d34565
1 changed files with 274 additions and 57 deletions

View File

@ -38,7 +38,11 @@ module ddr3_dimm_micron_sim;
ERROR: You must specify component density with +define+den____Mb.
`endif
localparam CONTROLLER_CLK_PERIOD = 10, //ns, period of clock input to this DDR3 controller module
DDR3_CLK_PERIOD = 2.5, //ns, period of clock input to DDR3 RAM device
LANES = 8, //8 lanes of DQ
OPT_LOWPOWER = 1, //1 = low power, 0 = low logic
OPT_BUS_ABORT = 1;
reg i_controller_clk, i_ddr3_clk, i_ref_clk;
reg i_rst_n;
@ -69,15 +73,15 @@ module ddr3_dimm_micron_sim;
// DDR3 Controller
ddr3_top #(
.ROW_BITS(14), //width of row address
.COL_BITS(10), //width of column address
.BA_BITS(3), //width of bank address
.DQ_BITS(8), //width of DQ
.CONTROLLER_CLK_PERIOD(10), //ns, period of clock input to this DDR3 controller module
.DDR3_CLK_PERIOD(2.5), //ns, period of clock input to DDR3 RAM device
.LANES(8), //8 lanes of DQ
.OPT_LOWPOWER(1), //1 = low power, 0 = low logic
.OPT_BUS_ABORT(1) //1 = can abort bus, 0 = no absort (i_wb_cyc will be ignored, ideal for an AXI implementation which cannot abort transaction)
.ROW_BITS(ROW_BITS), //width of row address
.COL_BITS(COL_BITS), //width of column address
.BA_BITS(BA_BITS), //width of bank address
.DQ_BITS(DQ_BITS), //width of DQ
.CONTROLLER_CLK_PERIOD(CONTROLLER_CLK_PERIOD), //ns, period of clock input to this DDR3 controller module
.DDR3_CLK_PERIOD(DDR3_CLK_PERIOD), //ns, period of clock input to DDR3 RAM device
.LANES(LANES), //8 lanes of DQ
.OPT_LOWPOWER(OPT_LOWPOWER), //1 = low power, 0 = low logic
.OPT_BUS_ABORT(OPT_BUS_ABORT) //1 = can abort bus, 0 = no absort (i_wb_cyc will be ignored, ideal for an AXI implementation which cannot abort transaction)
) ddr3_top
(
//clock and reset
@ -125,22 +129,7 @@ ddr3_top #(
i_ref_clk = 1;
end
reg[8*3-1:0] command_used; //store command in ASCII
always begin
case({cs_n, ras_n, cas_n, we_n})
4'b0000: command_used = "MRS";
4'b0001: command_used = "REF";
4'b0010: command_used = "PRE";
4'b0011: command_used = "ACT";
4'b0100: command_used = "WR";
4'b0101: command_used = "RD";
4'b0111: command_used = "NOP";
4'b1000: command_used = "DES";
4'b0110: command_used = "ZQC";
default: command_used = "???";
endcase
#1000;
end
/*
// 1 lane DDR3
ddr3 ddr3_0(
@ -179,13 +168,14 @@ ddr3_top #(
.dqs_n(dqs_n),
.dq(dq)
);
integer start_of_test = 0;
reg[511:0] write_data = 0, expected_read_data = 0;
integer address = 0, read_address = 0;
integer start_address = 0, start_read_address;
integer number_of_writes=0, number_of_reads=0, number_of_successful=0, number_of_failed=0;
localparam MAX_READS = 256;
integer random_start = $random; //starting seed for random accesss
localparam MAX_READS = (2**COL_BITS)*(2**BA_BITS + 1)/8; //1 row = 2**(COL_BITS) addresses/8 burst = 128 words per row. Times 8 to pass all 8 banks
initial begin
start_of_test = 0;
//toggle reset for 1 slow clk
@(posedge i_controller_clk)
i_rst_n = 0;
@ -199,9 +189,10 @@ ddr3_top #(
wait(ddr3_top.ddr3_controller_inst.state_calibrate == ddr3_top.ddr3_controller_inst.DONE_CALIBRATE);
// test 1 phase 1: Write random word sequentially
start_of_test = 1;
address = 0;
while(address < MAX_READS*($bits(ddr3_top.i_wb_data)/32)) begin
// write to row 1
start_address = 0;
address = start_address;
while(address < start_address + MAX_READS*($bits(ddr3_top.i_wb_data)/32)) begin
@(posedge i_controller_clk);
if(!o_wb_stall) begin
for (index = 0; index < $bits(ddr3_top.i_wb_data)/32; index = index + 1) begin
@ -212,43 +203,153 @@ ddr3_top #(
i_wb_we = 1;
i_wb_addr = address/ ($bits(ddr3_top.i_wb_data)/32);
i_wb_data = write_data;
$display("Write: Address = %0d, Data = %h", i_wb_addr, i_wb_data);
//$display("Write: Address = %0d, Data = %h", i_wb_addr, i_wb_data);
number_of_writes = number_of_writes + 1;
address = address + ($bits(ddr3_top.i_wb_data)/32);
end
else begin
i_wb_cyc = 1;
i_wb_stb = 0;
i_wb_we = 0;
i_wb_addr = 0;
i_wb_data = 0;
end
end
// test 1 phase 2: Read sequentially
start_of_test = 2;
address = 0;
while(address < MAX_READS*($bits(ddr3_top.i_wb_data)/32)) begin
//Read sequentially
address = start_address;
while(address < start_address + MAX_READS*($bits(ddr3_top.i_wb_data)/32)) begin
@(posedge i_controller_clk);
if(!o_wb_stall) begin
i_wb_cyc = 1;
i_wb_stb = 1;
i_wb_we = 0;
i_wb_addr = address/ ($bits(ddr3_top.i_wb_data)/32);
$display("Read: Address = %0d", i_wb_addr);
//$display("Read: Address = %0d", i_wb_addr);
number_of_reads = number_of_reads + 1;
address = address + ($bits(ddr3_top.i_wb_data)/32);
end
else begin
i_wb_cyc = 1;
i_wb_stb = 0;
i_wb_we = 0;
i_wb_addr = 0;
end
end
@(posedge i_controller_clk);
i_wb_stb = 0;
$display("\nDONE TEST 1: FIRST ROW\n");
#100_000;
@(posedge i_controller_clk);
// write to middle row
start_address = ((2**COL_BITS)*(2**ROW_BITS)*(2**BA_BITS)/2)*($bits(ddr3_top.i_wb_data)/32)/8; //start at the middle row
address = start_address;
while(address < start_address + MAX_READS*($bits(ddr3_top.i_wb_data)/32)) begin
@(posedge i_controller_clk);
if(!o_wb_stall) begin
for (index = 0; index < $bits(ddr3_top.i_wb_data)/32; index = index + 1) begin
write_data[index*32 +: 32] = $random(address + index); //each $random only has 32 bits
end
i_wb_cyc = 1;
i_wb_stb = 1;
i_wb_we = 1;
i_wb_addr = address/ ($bits(ddr3_top.i_wb_data)/32);
i_wb_data = write_data;
//$display("Write: Address = %0d, Data = %h", i_wb_addr, i_wb_data);
number_of_writes = number_of_writes + 1;
address = address + ($bits(ddr3_top.i_wb_data)/32);
end
end
// Read sequentially
address = start_address;
while(address < start_address + MAX_READS*($bits(ddr3_top.i_wb_data)/32)) begin
@(posedge i_controller_clk);
if(!o_wb_stall) begin
i_wb_cyc = 1;
i_wb_stb = 1;
i_wb_we = 0;
i_wb_addr = address/ ($bits(ddr3_top.i_wb_data)/32);
//$display("Read: Address = %0d", i_wb_addr);
number_of_reads = number_of_reads + 1;
address = address + ($bits(ddr3_top.i_wb_data)/32);
end
end
@(posedge i_controller_clk);
i_wb_stb = 0;
$display("\nDONE TEST 1: MIDDLE ROW\n");
#100_000;
// write to last row (then go back to first row)
start_address = ((2**COL_BITS)*(2**ROW_BITS)*(2**BA_BITS) - (2**COL_BITS)*(2**BA_BITS))*($bits(ddr3_top.i_wb_data)/32)/8; //start at the last row
address = start_address;
while(address < start_address + MAX_READS*($bits(ddr3_top.i_wb_data)/32)) begin
@(posedge i_controller_clk);
if(!o_wb_stall) begin
for (index = 0; index < $bits(ddr3_top.i_wb_data)/32; index = index + 1) begin
write_data[index*32 +: 32] = $random(address + index); //each $random only has 32 bits
end
i_wb_cyc = 1;
i_wb_stb = 1;
i_wb_we = 1;
i_wb_addr = address/ ($bits(ddr3_top.i_wb_data)/32);
i_wb_data = write_data;
//$display("Write: Address = %0d, Data = %h", i_wb_addr, i_wb_data);
number_of_writes = number_of_writes + 1;
address = address + ($bits(ddr3_top.i_wb_data)/32);
end
end
// Read sequentially
address = start_address;
while(address < start_address + MAX_READS*($bits(ddr3_top.i_wb_data)/32)) begin
@(posedge i_controller_clk);
if(!o_wb_stall) begin
i_wb_cyc = 1;
i_wb_stb = 1;
i_wb_we = 0;
i_wb_addr = address/ ($bits(ddr3_top.i_wb_data)/32);
//$display("Read: Address = %0d", i_wb_addr);
number_of_reads = number_of_reads + 1;
address = address + ($bits(ddr3_top.i_wb_data)/32);
end
end
@(posedge i_controller_clk);
i_wb_stb = 0;
$display("\nDONE TEST 1: LAST ROW\n");
#100_000;
// Test 2:Random Access
// write randomly
address = random_start; //this will just be used as the seed to generate a random number
while(address < random_start + MAX_READS*($bits(ddr3_top.i_wb_data)/32)) begin
@(posedge i_controller_clk);
if(!o_wb_stall) begin
for (index = 0; index < $bits(ddr3_top.i_wb_data)/32; index = index + 1) begin
write_data[index*32 +: 32] = $random(address + index); //each $random only has 32 bits
end
i_wb_cyc = 1;
i_wb_stb = 1;
i_wb_we = 1;
i_wb_addr = $random(~address); //write at random address
i_wb_data = write_data; //write random data
//$display("Write: Address = %0d, Data = %h", i_wb_addr, i_wb_data);
number_of_writes = number_of_writes + 1;
address = address + ($bits(ddr3_top.i_wb_data)/32);
end
end
// Read sequentially
// Read the random words written at the random addresses
address = random_start;
while(address < random_start + MAX_READS*($bits(ddr3_top.i_wb_data)/32)) begin
@(posedge i_controller_clk);
if(!o_wb_stall) begin
i_wb_cyc = 1;
i_wb_stb = 1;
i_wb_we = 0;
i_wb_addr = $random(~address);
//$display("Read: Address = %0d", i_wb_addr);
number_of_reads = number_of_reads + 1;
address = address + ($bits(ddr3_top.i_wb_data)/32);
end
end
@(posedge i_controller_clk);
i_wb_stb = 0;
$display("\nDONE TEST 1: LAST ROW\n");
#100_000;
/*
// write
@ -288,15 +389,16 @@ ddr3_top #(
//check read data
initial begin
read_address = 0;
while(read_address < MAX_READS*($bits(ddr3_top.i_wb_data)/32)) begin
start_read_address = 0; //start at first row
read_address = start_read_address;
while(read_address < start_read_address + MAX_READS*($bits(ddr3_top.i_wb_data)/32)) begin
@(posedge i_controller_clk);
if(o_wb_ack && start_of_test) begin
if(o_wb_ack && ddr3_top.ddr3_controller_inst.state_calibrate == ddr3_top.ddr3_controller_inst.DONE_CALIBRATE) begin
for (index = 0; index < $bits(ddr3_top.i_wb_data)/32; index = index + 1) begin
expected_read_data[index*32 +: 32] = $random(read_address + index); //each $random only has 32 bits
end
if(expected_read_data == o_wb_data) begin
$display("SUCCESSFUL: Address = %0d, expected data = %h, read data = %h", (read_address/($bits(ddr3_top.i_wb_data)/32)), expected_read_data, o_wb_data);
//$display("SUCCESSFUL: Address = %0d, expected data = %h, read data = %h", (read_address/($bits(ddr3_top.i_wb_data)/32)), expected_read_data, o_wb_data);
number_of_successful = number_of_successful + 1;
end
else begin
@ -306,9 +408,124 @@ ddr3_top #(
read_address = read_address + ($bits(ddr3_top.i_wb_data)/32);
end
end
start_read_address = ((2**COL_BITS)*(2**ROW_BITS)*(2**BA_BITS)/2)*($bits(ddr3_top.i_wb_data)/32)/8; //start at the middle row
read_address = start_read_address;
while(read_address < start_read_address + MAX_READS*($bits(ddr3_top.i_wb_data)/32)) begin
@(posedge i_controller_clk);
if(o_wb_ack && ddr3_top.ddr3_controller_inst.state_calibrate == ddr3_top.ddr3_controller_inst.DONE_CALIBRATE) begin
for (index = 0; index < $bits(ddr3_top.i_wb_data)/32; index = index + 1) begin
expected_read_data[index*32 +: 32] = $random(read_address + index); //each $random only has 32 bits
end
if(expected_read_data == o_wb_data) begin
//$display("SUCCESSFUL: Address = %0d, expected data = %h, read data = %h", (read_address/($bits(ddr3_top.i_wb_data)/32)), expected_read_data, o_wb_data);
number_of_successful = number_of_successful + 1;
end
else begin
$display("FAILED: Address = %0d, expected data = %h, read data = %h", (read_address/($bits(ddr3_top.i_wb_data)/32)), expected_read_data, o_wb_data);
number_of_failed = number_of_failed + 1;
end
read_address = read_address + ($bits(ddr3_top.i_wb_data)/32);
end
end
start_read_address = ((2**COL_BITS)*(2**ROW_BITS)*(2**BA_BITS) - (2**COL_BITS)*(2**BA_BITS))*($bits(ddr3_top.i_wb_data)/32)/8; //start at the last row
read_address = start_read_address;
while(read_address < start_read_address + MAX_READS*($bits(ddr3_top.i_wb_data)/32)) begin
@(posedge i_controller_clk);
if(o_wb_ack && ddr3_top.ddr3_controller_inst.state_calibrate == ddr3_top.ddr3_controller_inst.DONE_CALIBRATE) begin
for (index = 0; index < $bits(ddr3_top.i_wb_data)/32; index = index + 1) begin
expected_read_data[index*32 +: 32] = $random(read_address + index); //each $random only has 32 bits
end
if(expected_read_data == o_wb_data) begin
//$display("SUCCESSFUL: Address = %0d, expected data = %h, read data = %h", (read_address/($bits(ddr3_top.i_wb_data)/32)), expected_read_data, o_wb_data);
number_of_successful = number_of_successful + 1;
end
else begin
$display("FAILED: Address = %0d, expected data = %h, read data = %h", (read_address/($bits(ddr3_top.i_wb_data)/32)), expected_read_data, o_wb_data);
number_of_failed = number_of_failed + 1;
end
read_address = read_address + ($bits(ddr3_top.i_wb_data)/32);
end
end
// Read the random words written at the random addresses//read the random words at random addresses
read_address = random_start;
while(read_address < random_start + MAX_READS*($bits(ddr3_top.i_wb_data)/32)) begin
@(posedge i_controller_clk);
if(o_wb_ack && ddr3_top.ddr3_controller_inst.state_calibrate == ddr3_top.ddr3_controller_inst.DONE_CALIBRATE) begin
for (index = 0; index < $bits(ddr3_top.i_wb_data)/32; index = index + 1) begin
expected_read_data[index*32 +: 32] = $random(read_address + index); //each $random only has 32 bits
end
if(expected_read_data == o_wb_data) begin
//$display("SUCCESSFUL: Address = %0d, expected data = %h, read data = %h", (read_address/($bits(ddr3_top.i_wb_data)/32)), expected_read_data, o_wb_data);
number_of_successful = number_of_successful + 1;
end
else begin
$display("FAILED: Address = %0d, expected data = %h, read data = %h", (read_address/($bits(ddr3_top.i_wb_data)/32)), expected_read_data, o_wb_data);
number_of_failed = number_of_failed + 1;
end
read_address = read_address + ($bits(ddr3_top.i_wb_data)/32);
end
end
end
reg[8*3-1:0] command_used; //store command in ASCII
reg[3*8*2-1:0] prev_cmd; //stores previous 2 commands
reg[32*2-1:0] prev_time;
reg[31:0] time_now;
reg[3:0] repeats = 0;
//display commands issued
always @(posedge o_ddr3_clk_p) begin
if(!cs_n) begin //command is center-aligned to positive edge of clock, a valid command always has low cs_n
case({cs_n, ras_n, cas_n, we_n})
4'b0000: command_used = "MRS";
4'b0001: command_used = "REF";
4'b0010: command_used = "PRE";
4'b0011: command_used = "ACT";
4'b0100: command_used = " WR";
4'b0101: command_used = " RD";
4'b0111: command_used = "NOP";
4'b1000: command_used = "DES";
4'b0110: command_used = "ZQC";
default: command_used = "???";
endcase
time_now = $time;
if(command_used == " WR" || command_used == " RD") begin
$write("[%5d ps] %s @ (%0d, %5d) -> ",(time_now-prev_time[0 +: 32]), command_used, ba_addr, addr); //show bank and column address of being read/write
end
else if(command_used == "ACT")
$write("[%5d ps] %s @ (%0d, %5d) -> ",(time_now-prev_time[0 +: 32]), command_used, ba_addr, addr); //show bank and row address of being activated
else if(command_used == "PRE")
$write("[%5d ps] %s @ (%0d) -> ",(time_now-prev_time[0 +: 32]), command_used, ba_addr); //show bank that is being precharged
else
$write("[%5d ps] %s -> ",(time_now-prev_time[0 +: 32]), command_used); //show bank that is being precharged
prev_cmd <= {prev_cmd[0 +: 3*8], command_used[0 +: 3*8]};
prev_time <= {prev_time[0 +: 32], time_now};
repeats <= repeats + 1;
if(repeats == 4) begin
$write("\n");
repeats <= 0;
end
end
end
/*
// check delays between command if just enough
always @* begin
case({command_used, prev_cmd[0 +: 3*8]})
{"PRE","ACT"};
{"ACT"," RD"};
{"ACT"," WR"};
{" WR"," WR"}:
{" WR"," RD"}:
{" RD"," RD"};
{" RD"," WR"};
endcase
end
*/
endmodule