mirror of
https://github.com/MPSU/APS.git
synced 2025-09-15 17:20:10 +00:00
292 lines
8.6 KiB
Systemverilog
292 lines
8.6 KiB
Systemverilog
/* -----------------------------------------------------------------------------
|
|
* 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
|