ЛР6. Добавление тб

Closes #33.
This commit is contained in:
Andrei Solodovnikov
2024-07-15 16:49:01 +03:00
parent 25804e7b81
commit a4294c9b9e

View File

@@ -0,0 +1,291 @@
/* -----------------------------------------------------------------------------
* Project Name : Architectures of Processor Systems (APS) lab work
* Organization : National Research University of Electronic Technology (MIET)
* Department : Institute of Microdevices and Control Systems
* Author(s) : Andrei Solodovnikov
* Email(s) : hepoh@org.miet.ru
See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details.
* ------------------------------------------------------------------------------
*/
module tb_data_mem;
// Входы
import memory_pkg::DATA_MEM_SIZE_WORDS;
import memory_pkg::DATA_MEM_SIZE_BYTES;
logic clk_i;
logic mem_req_i;
logic write_enable_i;
logic [3:0] byte_enable_i;
logic [31:0] addr_i, addr;
logic [31:0] write_data_i;
assign addr = addr_i[2+:$clog2(DATA_MEM_SIZE_WORDS)];
logic [31:0] read_data_o;
logic ready_o;
logic [31:0] last_read_data;
logic [31:0] last_write_data;
int err_cnt = 0;
static bit simulation_finished;
data_mem DUT (.*);
task read_request(input logic [31:0] address, output logic [31:0] data);
addr_i <= address;
mem_req_i <= 1'b1;
write_enable_i <= 1'b0;
@(posedge clk_i);
data = read_data_o;
mem_req_i <= 1'b0;
endtask
task write_request( input logic [31:0] address, data, input [3:0] be);
addr_i <= address;
mem_req_i <= 1'b1;
write_enable_i <= 1'b1;
byte_enable_i <= be;
write_data_i <= data;
@(posedge clk_i);
mem_req_i <= 1'b0;
endtask
task direct_read_test();
logic [31:0] data;
for(int i = 0; i < 128; i++) begin
read_request(i, data);
end
if(DATA_MEM_SIZE_BYTES > 128) begin
for(int i = 1; i <= 128; i++) begin
read_request(DATA_MEM_SIZE_BYTES / 128 * i + i%4, data);
end
end
endtask
task direct_write_test();
for(int i = 0; i < 128; i++) begin
write_request(i, $urandom(), '1);
end
if(DATA_MEM_SIZE_BYTES > 128) begin
for(int i = 1; i <= 128; i++) begin
write_request(DATA_MEM_SIZE_BYTES / 128 * i + i%4, $urandom(), i%16);
end
end
endtask
task random_write_test();
repeat(1000) begin
write_request($urandom_range(0, DATA_MEM_SIZE_BYTES-1), $urandom(), $urandom_range(0, 15));
end
repeat(1000) begin
write_request($urandom(), $urandom(), $urandom_range(0, 15));
end
endtask
task random_read_test();
logic [31:0] data;
repeat(1000) begin
read_request($urandom_range(0, DATA_MEM_SIZE_BYTES-1), data);
end
repeat(1000) begin
read_request($urandom(), data);
end
endtask
task incorrect_read_test();
mem_req_i <= '0;
write_enable_i <= '1;
addr_i <= '0;
@(posedge clk_i);
write_enable_i <= '0;
@(posedge clk_i);
mem_req_i <= '1;
@(posedge clk_i);
endtask
task incorrect_write_test();
mem_req_i <= '0;
write_enable_i <= '0;
byte_enable_i <= '0;
write_data_i <= '1;
addr_i <= '0;
@(posedge clk_i);
mem_req_i <= '1;
@(posedge clk_i);
write_enable_i <= '1;
@(posedge clk_i);
byte_enable_i <= 4'b0010;
@(posedge clk_i);
endtask
task random_test();
repeat(1000) begin
mem_req_i <= $urandom_range(1);
write_enable_i <= $urandom_range(1);
byte_enable_i <= $urandom_range(15);
addr_i <= $urandom();
write_data_i <= $urandom();
@(posedge clk_i);
end
endtask
initial begin
$timeformat(-9, 3, "ns", 8);
$display("Test has been started");
DUT.ram[0] = '0;
DUT.ram[DATA_MEM_SIZE_WORDS-1] = '0;
DUT.ram[DATA_MEM_SIZE_WORDS] = '0;
assert( DUT.ram[0] == 0) else begin
$display("RAM has no element with index 0");
$fatal;
end
assert( DUT.ram[DATA_MEM_SIZE_WORDS-1] == 0) else begin
$display("RAM has no element with index %d", DATA_MEM_SIZE_WORDS-1);
$fatal;
end
assert( DUT.ram[DATA_MEM_SIZE_WORDS] === 'x) else begin
$display("RAM has element with index %d", DATA_MEM_SIZE_WORDS);
$fatal;
end
assert( DUT.ram[0][0] == 0) else begin
$display("RAM bit indexes started not from 0");
$fatal;
end
assert( DUT.ram[0][31] == 0) else begin
$display("RAM bit indexes ended not at 31");
$fatal;
end
assert( DUT.ram[0][32] === 'x) else begin
$display("RAM bit indexes ended not at 31");
$fatal;
end
direct_write_test();
direct_read_test();
random_write_test();
random_read_test();
incorrect_read_test();
incorrect_write_test();
random_test();
$display("\nTest has been finished\nNumber of errors: %d\n", err_cnt);
simulation_finished = 1;
$finish;
end
logic [31:0] ram_data;
logic [31:0] addr_reg;
always @(posedge clk_i) begin
addr_reg <= addr;
end
assign ram_data = DUT.ram[addr_reg];
initial begin
clk_i = 0;
forever #5 clk_i = ~clk_i;
end
ready_check: assert property (@(posedge clk_i) ready_o) else begin
err_cnt++;
$display("Error at %t. Value of ready is not equal 1.", $time);
end
correct_read_check: assert property (
@(posedge clk_i)
mem_req_i & !write_enable_i |=> read_data_o === ram_data
) else begin
err_cnt++;
$display("Error at %t. Incorrect read_data_o: %08h instead of %08h", $time(), $sampled(read_data_o), $sampled(ram_data));
end
logic [31:0] write_data;
always @(posedge clk_i) begin
write_data <= write_data_i;
end
correct_write_check_0: assert property (
@(posedge clk_i)
mem_req_i & write_enable_i & byte_enable_i[0]|=> $past(write_data_i[7:0]) === ram_data[7:0]
) else begin
err_cnt++;
$display("Error at %t. Incorrect value of ram[%01d][7:0]: %02h instead of %02h", $time(), $sampled(addr_reg), $sampled(ram_data[7:0]), $sampled(write_data_i[7:0]));
end
correct_write_check_1: assert property (
@(posedge clk_i)
mem_req_i & write_enable_i & byte_enable_i[1]|=> $past(write_data_i[15:8]) == ram_data[15:8]
) else begin
err_cnt++;
$display("Error at %t. Incorrect value of ram[%01d][15:8]: %02h instead of %02h", $time(), $sampled(addr_reg), $sampled(ram_data[15:8]), $sampled(write_data_i[15:8]));
end
correct_write_check_2: assert property (
@(posedge clk_i)
mem_req_i & write_enable_i & byte_enable_i[2]|=> $past(write_data_i[23:16]) == ram_data[23:16]
) else begin
err_cnt++;
$display("Error at %t. Incorrect value of ram[%d][23:16]: %02h instead of %02h", $time(), $sampled(addr_reg), $sampled(ram_data[23:16]), $sampled(write_data_i[23:16]));
end
correct_write_check_3: assert property (
@(posedge clk_i)
mem_req_i & write_enable_i & byte_enable_i[3]|=> $past(write_data_i[31:24]) == ram_data[31:24]
) else begin
err_cnt++;
$display("Error at %t. Incorrect value of ram[%d][31:24]: %02h instead of %02h", $time(), $sampled(addr), $sampled(ram_data[31:24]), $sampled(write_data_i[31:24]));
end
incorrect_read_check: assert property (
@(posedge clk_i)
!mem_req_i | write_enable_i |=> $stable(read_data_o)
) else begin
err_cnt++;
$display("Error at %t. read_data_o is unstable without read request", $time());
end
incorrect_write_check_0: assert property (
@(posedge clk_i)
(!mem_req_i | !write_enable_i | !byte_enable_i[0]) & $stable(addr) |=> $stable(ram_data[7:0])
) else begin
err_cnt++;
$display("Error at %t. ram[%d][7:0] is unstable without write request", $time(), $sampled(addr_reg));
end
icorrect_write_check_1: assert property (
@(posedge clk_i)
(!mem_req_i | !write_enable_i | !byte_enable_i[1]) & $stable(addr) |=> $stable(ram_data[15:8])
) else begin
err_cnt++;
$display("Error at %t. ram[%d][15:8] is unstable without write request", $time(), $sampled(addr_reg));
end
incorrect_write_check_2: assert property (
@(posedge clk_i)
(!mem_req_i | !write_enable_i | !byte_enable_i[2]) & $stable(addr) |=> $stable(ram_data[23:16])
) else begin
err_cnt++;
$display("Error at %t. ram[%d][23:16] is unstable without write request", $time(), $sampled(addr_reg));
end
incorrect_write_check_3: assert property (
@(posedge clk_i)
(!mem_req_i | !write_enable_i | !byte_enable_i[3]) & $stable(addr) |=> $stable(ram_data[31:24])
) else begin
err_cnt++;
$display("Error at %t. ram[%d][31:24] is unstable without write request", $time(), $sampled(addr_reg));
end
always @(posedge clk_i) begin
if(simulation_finished) begin
$finish;
end
end
always @(posedge clk_i) begin
if (err_cnt >= 10) begin
$display("\nTest has been stopped after 10 errors"); $stop();
end
end
endmodule