From e30ca87534cf40410f740ae4b2b1816784364622 Mon Sep 17 00:00:00 2001 From: Andrei Solodovnikov Date: Thu, 23 Nov 2023 23:48:40 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9B=D0=A010.=20=D0=94=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=82=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D0=BE=D0=B2=D1=8B=D1=85=20=D1=81=D1=86=D0=B5=D0=BD=D0=B0=D1=80?= =?UTF-8?q?=D0=B8=D0=B5=D0=B2=20=D0=B2=20tb=5Fcsr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Labs/10. Interrupt subsystem/tb_csr.sv | 413 +++++-------------------- 1 file changed, 80 insertions(+), 333 deletions(-) diff --git a/Labs/10. Interrupt subsystem/tb_csr.sv b/Labs/10. Interrupt subsystem/tb_csr.sv index 09d06e53..2802c3f4 100644 --- a/Labs/10. Interrupt subsystem/tb_csr.sv +++ b/Labs/10. Interrupt subsystem/tb_csr.sv @@ -1,363 +1,110 @@ -////////////////////////////////////////////////////////////////////////////////// -// Company: MIET -// Engineer: Daniil Strelkov +module csr_controller( -// Module Name: tb_csr -// Project Name: RISCV_practicum -// Target Devices: Nexys A7-100T -// Description: tb for CSR controller -// -////////////////////////////////////////////////////////////////////////////////// + input logic clk_i, + input logic rst_i, + input logic trap_i, -module tb_csr(); - logic clk_i; - logic rst_i; - logic trap_i; + input logic [ 2:0] opcode_i, - logic [ 2:0] opcode_i; + input logic [11:0] addr_i, + input logic [31:0] pc_i, + input logic [31:0] mcause_i, + input logic [31:0] rs1_data_i, + input logic [31:0] imm_data_i, + input logic write_enable_i, - logic [11:0] addr_i; - logic [31:0] pc_i; - logic [31:0] mcause_i; - logic [31:0] rs1_data_i; - logic [31:0] imm_data_i; - logic write_enable_i; - - logic [31:0] read_data_o; - logic [31:0] mie_o; - logic [31:0] mepc_o; - logic [31:0] mtvec_o; + output logic [31:0] read_data_o, + output logic [31:0] mie_o, + output logic [31:0] mepc_o, + output logic [31:0] mtvec_o +); import csr_pkg::*; -csr_controller dut(.*); - -always #5 clk_i <= ~clk_i; +logic [31:0] data; +logic [31:0] read_data; -int err_count; - -initial begin - $display("\n\n===========================\n\nPress button 'Run All' (F3)\n\n===========================\n\n"); - $stop(); - err_count = 0; - clk_i <= 0; - rst_i <= 1'b1; - repeat(2)@(posedge clk_i); - rst_i <= 1'b0; -end +logic [31:0] mie_ff; +logic [31:0] mtvec_ff; +logic [31:0] mscratch_ff; +logic [31:0] mepc_ff; +logic [31:0] mcause_ff; -initial begin - opcode_i = '0; - addr_i = '0; - pc_i = '0; - mcause_i = '0; - rs1_data_i = '0; - imm_data_i = '0; - trap_i = '0; - repeat(4)@(posedge clk_i); - csrrw(); - csrrs(); - csrrc(); - csrrwi(); - csrrsi(); - csrrci(); - csrr(); - csrw(); - trap(); - - $display("Simulation finished. Number of errors: %d", err_count); - if( !err_count ) $display("\n csr_controller SUCCESS!!!\n"); - $finish; -end - -initial begin - int not_stopped = 1; - forever begin - @(posedge clk_i); - if((err_count >= 10) && not_stopped) begin - $display("Simulation stopped after ten errors."); - $stop(); - not_stopped = 0; - end - end -end - -logic [31:0] data_ref; -logic [31:0] pc_ref; -logic [31:0] mcause_ref; -logic [11:0] addr [0:4] = { MIE_ADDR, -MTVEC_ADDR, -MSCRATCH_ADDR, -MEPC_ADDR, -MCAUSE_ADDR}; - -assign pc_ref = write_enable_i ? pc_i : pc_ref; -assign mcause_ref = write_enable_i ? mcause_i : mcause_ref; +logic en_mie; +logic en_mtvec; +logic en_mscratch; +logic en_mepc; +logic en_mcause; always_comb begin - if (rst_i) data_ref <= 0; - if (write_enable_i) - case(opcode_i) - CSR_RW: data_ref <= #1 rs1_data_i; - CSR_RS: data_ref <= #1 rs1_data_i | read_data_o; - CSR_RC: data_ref <= #1 ~rs1_data_i & read_data_o; - CSR_RWI: data_ref <= #1 imm_data_i; - CSR_RSI: data_ref <= #1 imm_data_i | read_data_o; - CSR_RCI: data_ref <= #1 ~imm_data_i & read_data_o; - default: data_ref <= #1 data_ref; + case ( opcode_i ) + CSR_RW: data <= rs1_data_i; + CSR_RS: data <= rs1_data_i | read_data; + CSR_RC: data <= ~rs1_data_i & read_data; + CSR_RWI: data <= imm_data_i; + CSR_RSI: data <= imm_data_i | read_data; + CSR_RCI: data <= ~imm_data_i & read_data; endcase end -task clear(); - rst_i <= 1'b1; - repeat(2)@(posedge clk_i); - rst_i <= 1'b0; -endtask - -//csrrw -task csrrw(); - trap_i <= 0; -for (int i = 0; i<5; i = i+1) begin - repeat(20) begin - opcode_i <= CSR_RW; - addr_i <= addr[i]; - rs1_data_i <= $random; - imm_data_i <= $random; - write_enable_i <= 1; - @(posedge clk_i); - write_enable_i <= 0; - @(posedge clk_i); - check_reg(); - end - clear(); - @(posedge clk_i); -end -endtask -//csrrs -task csrrs(); - trap_i <= 0; -for (int i = 0; i<5; i = i+1) begin - repeat(20) begin - opcode_i <= CSR_RS; - addr_i <= addr[i]; - rs1_data_i <= $random; - imm_data_i <= $random; - write_enable_i <= 1; - @(posedge clk_i); - write_enable_i <= 0; - @(posedge clk_i); - check_reg(); - end - clear(); - @(posedge clk_i); -end -endtask -//csrrc -task csrrc(); - trap_i <= 0; -for (int i = 0; i<5; i = i+1) begin - repeat(20) begin - addr_i <= addr[i]; - opcode_i <= CSR_RC; - rs1_data_i <= $random; - imm_data_i <= $random; - write_enable_i <= 1; - @(posedge clk_i); - write_enable_i <= 0; - @(posedge clk_i); - check_reg(); - end - clear(); - @(posedge clk_i); -end -endtask - -//csrrwi -task csrrwi(); - trap_i <= 0; -for (int i = 0; i<5; i = i+1) begin - repeat(20) begin - addr_i <= addr[i]; - opcode_i <= CSR_RWI; - rs1_data_i <= $random; - imm_data_i <= $random; - write_enable_i <= 1; - @(posedge clk_i); - write_enable_i <= 0; - @(posedge clk_i); - check_reg(); - end - clear(); - @(posedge clk_i); +always_comb begin + case ( addr_i ) + MIE_ADDR: en_mie <= write_enable_i; + MTVEC_ADDR: en_mtvec <= write_enable_i; + MSCRATCH_ADDR: en_mscratch <= write_enable_i; + MEPC_ADDR: en_mepc <= write_enable_i; + MCAUSE_ADDR: en_mcause <= write_enable_i; + endcase end -endtask -//csrrsi -task csrrsi(); - trap_i <= 0; -for (int i = 0; i<5; i = i+1) begin - repeat(20) begin - addr_i <= addr[i]; - opcode_i <= CSR_RSI; - rs1_data_i <= $random; - imm_data_i <= $random; - write_enable_i <= 1; - @(posedge clk_i); - write_enable_i <= 0; - @(posedge clk_i); - check_reg(); - end - clear(); - @(posedge clk_i); +always_ff @( posedge clk_i ) begin + if( rst_i ) + mie_ff <= '0; + else if( en_mie ) + mie_ff <= data; end -endtask -//csrrci -task csrrci(); - trap_i <= 0; -for (int i = 0; i<5; i = i+1) begin - repeat(20) begin - addr_i <= addr[i]; - opcode_i <= CSR_RCI; - rs1_data_i <= $random; - imm_data_i <= $random; - write_enable_i <= 1; - @(posedge clk_i); - write_enable_i <= 0; - @(posedge clk_i); - check_reg(); - end - clear(); - @(posedge clk_i); +always_ff @( posedge clk_i ) begin + if( rst_i ) + mtvec_ff <= '0; + else if( en_mtvec ) + mtvec_ff <= data; end -endtask -//csrr -task csrr(); - trap_i <= 0; -for (int i = 0; i<5; i = i+1) begin - repeat(20) begin - addr_i <= addr[i]; - opcode_i <= CSR_RS; - rs1_data_i <= 0; - imm_data_i <= $random; - write_enable_i <= 1; - @(posedge clk_i); - write_enable_i <= 0; - @(posedge clk_i); - check_reg(); - end - clear(); - @(posedge clk_i); +always_ff @( posedge clk_i ) begin + if( rst_i ) + mscratch_ff <= '0; + else if( en_mscratch ) + mscratch_ff <= data; end -endtask -//csrw -task csrw(); - trap_i <= 0; -for (int i = 0; i<5; i = i+1) begin - repeat(20) begin - addr_i <= addr[i]; - opcode_i <= CSR_RW; - rs1_data_i <= $random; - imm_data_i <= $random; - write_enable_i <= 1; - @(posedge clk_i); - write_enable_i <= 0; - @(posedge clk_i); - check_reg(); - end - clear(); - @(posedge clk_i); +always_ff @( posedge clk_i ) begin + if( rst_i ) + mepc_ff <= '0; + else if( en_mepc | trap_i ) + mepc_ff <= ( trap_i ) ? pc_i : addr_i; end -endtask -//trap -task trap(); -repeat(100) begin - opcode_i <= $random; - addr_i <= MCAUSE_ADDR; - pc_i <= $random; - mcause_i <= $random; - write_enable_i <= 0; - trap_i <= 1; - @(posedge clk_i); - trap_i <= 0; - @(posedge clk_i); - check_reg(); +always_ff @( posedge clk_i ) begin + if( rst_i ) + mcause_ff <= '0; + else if( en_mcause | trap_i ) + mcause_ff <= ( trap_i ) ? mcause_i : addr_i; end -endtask -task check_reg(); - trap_i <= 0; - opcode_i <= 0; - rs1_data_i <= 0; - imm_data_i <= 0; - write_enable_i <= 0; - for (int i = 0; i<5; i = i+1) begin - addr_i <= addr[i]; - @(posedge clk_i); +always_comb begin + case ( addr_i ) + MIE_ADDR: read_data_o <= mie_ff; + MTVEC_ADDR: read_data_o <= mtvec_ff; + MSCRATCH_ADDR: read_data_o <= mscratch_ff; + MEPC_ADDR: read_data_o <= mepc_ff; + MCAUSE_ADDR: read_data_o <= mcause_ff; + endcase end -endtask - -trap_mepc_a: assert property ( - @(posedge clk_i) disable iff ( rst_i ) - $rose(trap_i) |-> ##1 (mepc_o === pc_i) -)else begin - err_count++; - $display("Incorrect mepc on trap : mepc_o = %08h while it should be %08h.\n", mepc_o, pc_i); - end - - -trap_mcause_a: assert property ( - @(posedge clk_i) disable iff ( rst_i ) - ($rose(trap_i) && (addr_i == MCAUSE_ADDR)) |-> ##1 (read_data_o === mcause_i) -)else begin - err_count++; - $display("Incorrect mcause on trap : read_data_o = %08h while it should be %08h.\n", read_data_o, mcause_i); - end - -string reg_name; -string padding; -csr_read_a: assert property ( - @(posedge clk_i) disable iff ( rst_i || trap_i ) - ( (opcode_i inside {CSR_RW, CSR_RS, CSR_RC, CSR_RWI, CSR_RSI, CSR_RCI} ) && $rose(write_enable_i)) |=> (read_data_o === data_ref) -)else begin - err_count++; - case(addr_i) - MIE_ADDR : reg_name = "mie "; - MTVEC_ADDR : reg_name = "mtvec "; - MSCRATCH_ADDR : reg_name = "mscratch"; - MEPC_ADDR : reg_name = "mepc "; - MCAUSE_ADDR : reg_name = "mcause "; - default : reg_name = "ill_addr"; - endcase - $display("Incorrect read from %s: read_data_o = %08h while it should be %08h.\n", reg_name, read_data_o, data_ref); - end - -mie_a: assert property ( - @(posedge clk_i) disable iff ( rst_i || trap_i ) - ((addr_i === MIE_ADDR) && $rose(write_enable_i)) |=> (mie_o === data_ref) -)else begin - err_count++; - $display("Incorrect value of mie_o : mie_o = %08h while if should be %08h.\n", mie_o, data_ref); - end - -mepc_a: assert property ( - @(posedge clk_i) disable iff ( rst_i || trap_i ) - ((addr_i === MEPC_ADDR) && $rose(write_enable_i)) |=> (mepc_o === data_ref) -)else begin - err_count++; - $display("Incorrect value of mepc_o : mepc_o = %08h while if should be %08h.\n", mepc_o, data_ref); - end - -mtvec_a: assert property ( - @(posedge clk_i) disable iff ( rst_i || trap_i ) - ((addr_i === MTVEC_ADDR) && $rose(write_enable_i)) |=> (mtvec_o === data_ref) -)else begin - err_count++; - $display("Incorrect value of mtvec_o : mtvec_o = %08h while if should be %08h.\n", mtvec_o, data_ref); - end +assign mie_o = mie_ff; +assign mtvec_o = mtvec_ff; +assign mepc_o = mepc_ff; +assign read_data_o = read_data; endmodule