diff --git a/Labs/05. Main decoder/tb_decoder_riscv.sv b/Labs/05. Main decoder/tb_decoder_riscv.sv index a8492bb0..12b80ece 100644 --- a/Labs/05. Main decoder/tb_decoder_riscv.sv +++ b/Labs/05. Main decoder/tb_decoder_riscv.sv @@ -2,460 +2,816 @@ * 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) : Nikita Bulavin -* Email(s) : nekkit6@edu.miet.ru +* 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_decoder_riscv(); import riscv_pkg::*; - parameter delay = 4; - parameter cycle = 200; // per one opcode - - reg [31:0] instr; - wire [1:0] a_sel; - wire [2:0] b_sel; - wire [ALU_OP_WIDTH-1:0] alu_op; - wire [2:0] csr_op; - wire csr_we; - wire mem_req; - wire mem_we; - wire [2:0] mem_size; - wire gpr_we; - wire [1:0] wb_sel; - wire illegal_instr; - wire branch; - wire jal; - wire jalr; - wire mret; - - reg a_sel_miss; - reg b_sel_miss; - reg alu_op_miss; - reg csr_op_miss; - reg csr_we_miss; - reg mem_req_miss; - reg mem_we_miss; - reg mem_size_miss; - reg gpr_we_miss; - reg wb_sel_miss; - reg illegal_miss; - reg branch_miss; - reg jal_miss; - reg jalr_miss; - reg mret_miss; - - string opcode_type; - string instr_type; - - decoder_riscv dut ( - .fetched_instr_i (instr), - .a_sel_o (a_sel), - .b_sel_o (b_sel), - .alu_op_o (alu_op), - .csr_op_o (csr_op), - .csr_we_o (csr_we), - .mem_req_o (mem_req), - .mem_we_o (mem_we), - .mem_size_o (mem_size), - .gpr_we_o (gpr_we), - .wb_sel_o (wb_sel), - .illegal_instr_o (illegal_instr), - .branch_o (branch), - .jal_o (jal), - .jalr_o (jalr), - .mret_o (mret) - ); - - decoder_riscv_ref grm(.fetched_instr_i (instr)); + typedef class riscv_instr; + riscv_instr instr = new(); - wire [4:0] opcode; - assign opcode = instr[6:2]; + logic [4:0] opcode_array[11] = { + LOAD_OPCODE, + MISC_MEM_OPCODE, + OP_IMM_OPCODE, + AUIPC_OPCODE, + STORE_OPCODE, + OP_OPCODE, + LUI_OPCODE, + BRANCH_OPCODE, + JALR_OPCODE, + JAL_OPCODE, + SYSTEM_OPCODE + }; + /* + Since randomize with overconstraining slows down simulation, it has been + decided to make a list of all codes instead of looping over every possible + combination func3 and func7. + */ + logic [14:0] valid_codes[44] = { + {LOAD_OPCODE , 3'h0, 7'h00}, + {LOAD_OPCODE , 3'h1, 7'h00}, + {LOAD_OPCODE , 3'h2, 7'h00}, + {LOAD_OPCODE , 3'h4, 7'h00}, + {LOAD_OPCODE , 3'h5, 7'h00}, + {MISC_MEM_OPCODE, 3'h0, 7'h00}, + {OP_IMM_OPCODE , 3'h0, 7'h00}, + {OP_IMM_OPCODE , 3'h1, 7'h00}, + {OP_IMM_OPCODE , 3'h2, 7'h00}, + {OP_IMM_OPCODE , 3'h3, 7'h00}, + {OP_IMM_OPCODE , 3'h4, 7'h00}, + {OP_IMM_OPCODE , 3'h5, 7'h00}, + {OP_IMM_OPCODE , 3'h5, 7'h20}, + {OP_IMM_OPCODE , 3'h6, 7'h00}, + {OP_IMM_OPCODE , 3'h7, 7'h00}, + {AUIPC_OPCODE , 3'h0, 7'h00}, + {STORE_OPCODE , 3'h0, 7'h00}, + {STORE_OPCODE , 3'h1, 7'h00}, + {STORE_OPCODE , 3'h2, 7'h00}, + {OP_OPCODE , 3'h0, 7'h00}, + {OP_OPCODE , 3'h0, 7'h20}, + {OP_OPCODE , 3'h1, 7'h00}, + {OP_OPCODE , 3'h2, 7'h00}, + {OP_OPCODE , 3'h3, 7'h00}, + {OP_OPCODE , 3'h4, 7'h00}, + {OP_OPCODE , 3'h5, 7'h00}, + {OP_OPCODE , 3'h5, 7'h20}, + {OP_OPCODE , 3'h6, 7'h00}, + {OP_OPCODE , 3'h7, 7'h00}, + {LUI_OPCODE , 3'h0, 7'h00}, + {BRANCH_OPCODE , 3'h0, 7'h00}, + {BRANCH_OPCODE , 3'h1, 7'h00}, + {BRANCH_OPCODE , 3'h4, 7'h00}, + {BRANCH_OPCODE , 3'h5, 7'h00}, + {BRANCH_OPCODE , 3'h6, 7'h00}, + {BRANCH_OPCODE , 3'h7, 7'h00}, + {JALR_OPCODE , 3'h0, 7'h00}, + {JAL_OPCODE , 3'h0, 7'h00}, + {SYSTEM_OPCODE , 3'h1, 7'h00}, + {SYSTEM_OPCODE , 3'h2, 7'h00}, + {SYSTEM_OPCODE , 3'h3, 7'h00}, + {SYSTEM_OPCODE , 3'h5, 7'h00}, + {SYSTEM_OPCODE , 3'h6, 7'h00}, + {SYSTEM_OPCODE , 3'h7, 7'h00} + }; - always @(*) begin - case (opcode) - LUI_OPCODE, AUIPC_OPCODE, JAL_OPCODE: - instr_type = $sformatf("%020b %05b %07b ", instr[31:12], instr[11:7], instr[6:0]); - JALR_OPCODE, LOAD_OPCODE, OP_IMM_OPCODE, SYSTEM_OPCODE: - instr_type = $sformatf("%012b %05b %03b %05b %07b ", instr[31:20], instr[19:15], instr[14:12], instr[11:7], instr[6:0]); - BRANCH_OPCODE, STORE_OPCODE, OP_OPCODE: - instr_type = $sformatf("%07b %05b %05b %03b %05b %07b", instr[31:25], instr[24:20], instr[19:15], instr[14:12], instr[11:7], instr[6:0]); - MISC_MEM_OPCODE: - instr_type = $sformatf("%017b %03b %05b %07b ", instr[31:15], instr[14:12], instr[11:7], instr[6:0]); - default: - instr_type = $sformatf("%032b ", instr); - endcase - end + logic [14:0] invalid_codes[38] = { + {LOAD_OPCODE , 3'h3, 7'h00}, + {LOAD_OPCODE , 3'h6, 7'h00}, + {LOAD_OPCODE , 3'h7, 7'h00}, + {MISC_MEM_OPCODE, 3'h1, 7'h00}, + {MISC_MEM_OPCODE, 3'h2, 7'h00}, + {MISC_MEM_OPCODE, 3'h3, 7'h00}, + {MISC_MEM_OPCODE, 3'h4, 7'h00}, + {MISC_MEM_OPCODE, 3'h5, 7'h00}, + {MISC_MEM_OPCODE, 3'h6, 7'h00}, + {MISC_MEM_OPCODE, 3'h7, 7'h00}, + {OP_IMM_OPCODE , 3'h0, 7'h20}, + {OP_IMM_OPCODE , 3'h1, 7'h20}, + {OP_IMM_OPCODE , 3'h2, 7'h20}, + {OP_IMM_OPCODE , 3'h3, 7'h20}, + {OP_IMM_OPCODE , 3'h4, 7'h20}, + {OP_IMM_OPCODE , 3'h6, 7'h20}, + {OP_IMM_OPCODE , 3'h7, 7'h20}, + {STORE_OPCODE , 3'h3, 7'h00}, + {STORE_OPCODE , 3'h4, 7'h00}, + {STORE_OPCODE , 3'h5, 7'h00}, + {STORE_OPCODE , 3'h6, 7'h00}, + {STORE_OPCODE , 3'h7, 7'h00}, + {OP_OPCODE , 3'h1, 7'h20}, + {OP_OPCODE , 3'h2, 7'h20}, + {OP_OPCODE , 3'h3, 7'h20}, + {OP_OPCODE , 3'h4, 7'h20}, + {OP_OPCODE , 3'h6, 7'h20}, + {OP_OPCODE , 3'h7, 7'h20}, + {BRANCH_OPCODE , 3'h2, 7'h00}, + {BRANCH_OPCODE , 3'h3, 7'h00}, + {JALR_OPCODE , 3'h1, 7'h00}, + {JALR_OPCODE , 3'h2, 7'h00}, + {JALR_OPCODE , 3'h3, 7'h00}, + {JALR_OPCODE , 3'h4, 7'h00}, + {JALR_OPCODE , 3'h5, 7'h00}, + {JALR_OPCODE , 3'h6, 7'h00}, + {JALR_OPCODE , 3'h7, 7'h00}, + {SYSTEM_OPCODE , 3'h4, 7'h00} + }; - always @(*) begin - a_sel_miss = 'b0; - b_sel_miss = 'b0; - alu_op_miss = 'b0; - csr_op_miss = 'b0; - csr_we_miss = 'b0; - mem_req_miss = 'b0; - mem_we_miss = 'b0; - mem_size_miss = 'b0; - gpr_we_miss = 'b0; - wb_sel_miss = 'b0; - illegal_miss = 'b0; - branch_miss = 'b0; - jal_miss = 'b0; - jalr_miss = 'b0; - mret_miss = 'b0; - illegal_miss = grm.illegal_instr_o !== illegal_instr; - case (opcode) - LOAD_OPCODE, STORE_OPCODE: - begin - a_sel_miss = (grm.a_sel_o !== a_sel) & !illegal_instr; - b_sel_miss = (grm.b_sel_o !== b_sel) & !illegal_instr; - alu_op_miss = (grm.alu_op_o !== alu_op) & !illegal_instr; - csr_we_miss = (grm.csr_we_o !== csr_we); - mem_req_miss = grm.mem_req_o !== mem_req; - mem_we_miss = grm.mem_we_o !== mem_we; - mem_size_miss = (grm.mem_size_o !== mem_size) & !illegal_instr; - gpr_we_miss = grm.gpr_we_o !== gpr_we; - wb_sel_miss = (grm.wb_sel_o !== wb_sel) & !illegal_instr; - branch_miss = grm.branch_o !== branch; - jal_miss = grm.jal_o !== jal; - jalr_miss = grm.jalr_o !== jalr; - mret_miss = grm.mret_o !== mret; - end + bit clk, test_has_been_finished, test_paused_by_errs; + int err_count; + initial begin + clk = '0; + test_has_been_finished = '0; + err_count = '0; + test_paused_by_errs = '0; + end - JAL_OPCODE, JALR_OPCODE, - AUIPC_OPCODE, - OP_IMM_OPCODE, OP_OPCODE: - begin - a_sel_miss = (grm.a_sel_o !== a_sel) & !illegal_instr; - b_sel_miss = (grm.b_sel_o !== b_sel) & !illegal_instr; - alu_op_miss = (grm.alu_op_o !== alu_op) & !illegal_instr; - csr_we_miss = (grm.csr_we_o !== csr_we); - mem_req_miss = grm.mem_req_o !== mem_req; - mem_we_miss = grm.mem_we_o !== mem_we; - //mem_size_miss = (grm.mem_size_o !== mem_size) & !illegal_instr; - gpr_we_miss = grm.gpr_we_o !== gpr_we; - wb_sel_miss = (grm.wb_sel_o !== wb_sel) & !illegal_instr; - branch_miss = grm.branch_o !== branch; - jal_miss = grm.jal_o !== jal; - jalr_miss = grm.jalr_o !== jalr; - mret_miss = grm.mret_o !== mret; - end - - BRANCH_OPCODE: - begin - a_sel_miss = (grm.a_sel_o !== a_sel) & !illegal_instr; - b_sel_miss = (grm.b_sel_o !== b_sel) & !illegal_instr; - alu_op_miss = (grm.alu_op_o !== alu_op) & !illegal_instr; - csr_we_miss = (grm.csr_we_o !== csr_we); - mem_req_miss = grm.mem_req_o !== mem_req; - mem_we_miss = grm.mem_we_o !== mem_we; - //mem_size_miss = (grm.mem_size_o !== mem_size) & !illegal_instr; - gpr_we_miss = grm.gpr_we_o !== gpr_we; - //wb_sel_miss = (grm.wb_sel_o !== wb_sel) & !illegal_instr; - branch_miss = grm.branch_o !== branch; - jal_miss = grm.jal_o !== jal; - jalr_miss = grm.jalr_o !== jalr; - mret_miss = grm.mret_o !== mret; - end + always #5 clk = ~clk; + always @(posedge clk) begin + if(test_has_been_finished) begin + $finish(); + end + end - LUI_OPCODE: begin - a_sel_miss = (grm.a_sel_o !== a_sel) & !illegal_instr; - b_sel_miss = (grm.b_sel_o !== b_sel) & !illegal_instr; - alu_op_miss = ((alu_op !== ALU_ADD)&(alu_op !== ALU_XOR)&(alu_op !== ALU_OR)) & !illegal_instr; - csr_we_miss = (grm.csr_we_o !== csr_we); - mem_req_miss = grm.mem_req_o !== mem_req; - mem_we_miss = grm.mem_we_o !== mem_we; - //mem_size_miss = (grm.mem_size_o !== mem_size) & !illegal_instr; - gpr_we_miss = grm.gpr_we_o !== gpr_we; - wb_sel_miss = (grm.wb_sel_o !== wb_sel) & !illegal_instr; - branch_miss = grm.branch_o !== branch; - jal_miss = grm.jal_o !== jal; - jalr_miss = grm.jalr_o !== jalr; - mret_miss = grm.mret_o !== mret; - end - - SYSTEM_OPCODE: begin - //a_sel_miss = (grm.a_sel_o !== a_sel) & !illegal_instr; - //b_sel_miss = (grm.b_sel_o !== b_sel) & !illegal_instr; - //alu_op_miss = ((alu_op !== ALU_ADD)&(alu_op !== ALU_XOR)&(alu_op !== ALU_OR)) & !illegal_instr; - csr_we_miss = (grm.csr_we_o !== csr_we); - mem_req_miss = grm.mem_req_o !== mem_req; - mem_we_miss = grm.mem_we_o !== mem_we; - //mem_size_miss = (grm.mem_size_o !== mem_size) & !illegal_instr; - gpr_we_miss = grm.gpr_we_o !== gpr_we; - wb_sel_miss = (grm.wb_sel_o !== wb_sel) & !illegal_instr & !mret; - branch_miss = grm.branch_o !== branch; - jal_miss = grm.jal_o !== jal; - jalr_miss = grm.jalr_o !== jalr; - mret_miss = grm.mret_o !== mret; - end - default: //MISC_MEM_OPCODE and other - begin - //a_sel_miss = grm.a_sel_o !== a_sel; - //b_sel_miss = grm.b_sel_o !== b_sel; - //alu_op_miss = grm.alu_op_o !== alu_op; - csr_we_miss = (grm.csr_we_o !== csr_we); - mem_req_miss = grm.mem_req_o !== mem_req; - mem_we_miss = grm.mem_we_o !== mem_we; - //mem_size_miss = grm.mem_size_o !== mem_size; - gpr_we_miss = grm.gpr_we_o !== gpr_we; - //wb_sel_miss = grm.wb_sel_o !== wb_sel; - branch_miss = grm.branch_o !== branch; - jal_miss = grm.jal_o !== jal; - jalr_miss = grm.jalr_o !== jalr; - mret_miss = grm.mret_o !== mret; - end - endcase + always @(posedge clk) begin + if((err_count >= 10) & !test_paused_by_errs) begin + test_paused_by_errs = '1; + $display("\nTest has been stopped after 10 errors"); + $stop(); + end end - integer X; - reg [$clog2(cycle+1)-1:0] V; - integer error; + logic [31:0] fetched_instr_i; + logic [1:0] a_sel_o; + logic [2:0] b_sel_o; + logic [4:0] alu_op_o; + logic [2:0] csr_op_o; + logic csr_we_o; + logic mem_req_o; + logic mem_we_o; + logic [2:0] mem_size_o; + logic gpr_we_o; + logic [1:0] wb_sel_o; + logic illegal_instr_o; + logic branch_o; + logic jal_o; + logic jalr_o; + logic mret_o; + + logic [1:0] grm_a_sel_o; + logic [2:0] grm_b_sel_o; + logic [4:0] grm_alu_op_o; + logic [2:0] grm_csr_op_o; + logic grm_csr_we_o; + logic grm_mem_req_o; + logic grm_mem_we_o; + logic [2:0] grm_mem_size_o; + logic grm_gpr_we_o; + logic [1:0] grm_wb_sel_o; + logic grm_illegal_instr_o; + logic grm_branch_o; + logic grm_jal_o; + logic grm_jalr_o; + logic grm_mret_o; + + + decoder_riscv DUT(.*); + + decoder_riscv_ref GRM( + .fetched_instr_i (fetched_instr_i ), + .a_sel_o (grm_a_sel_o ), + .b_sel_o (grm_b_sel_o ), + .alu_op_o (grm_alu_op_o ), + .csr_op_o (grm_csr_op_o ), + .csr_we_o (grm_csr_we_o ), + .mem_req_o (grm_mem_req_o ), + .mem_we_o (grm_mem_we_o ), + .mem_size_o (grm_mem_size_o ), + .gpr_we_o (grm_gpr_we_o ), + .wb_sel_o (grm_wb_sel_o ), + .illegal_instr_o (grm_illegal_instr_o), + .branch_o (grm_branch_o ), + .jal_o (grm_jal_o ), + .jalr_o (grm_jalr_o ), + .mret_o (grm_mret_o ) + ); initial begin - $timeformat(-9, 2, " ns", 3); - error = 0; + $display("Test has been started"); + $display( "\n\n==========================\nCLICK THE BUTTON 'Run All'\n==========================\n"); $stop(); + + valid_instrs_direct_test(); + valid_instrs_random_test(); + illegal_instr_direct_test(); + illegal_instrs_random_test(); + + $display("\nTest has been finished\nNumber of errors: %d\n", err_count); + test_has_been_finished = 1'b1; + $finish(); end - initial begin - $display( "\nStart test: \n\n==========================\nCLICK THE BUTTON 'Run All'\n==========================\n"); $stop(); - - for (V=0; V (grm_a_sel_o === a_sel_o ) + ) + else begin + $error("\na_sel_o value is incorrect ( %02b instead of %02b), instruction: %s %s", a_sel_o , grm_a_sel_o , raw_instr, instr_str ); + err_count++; + end + + b_sel_prop : assert property ( + @(posedge clk) disable iff(grm_illegal_instr_o) + b_sel_check |-> (grm_b_sel_o === b_sel_o ) + ) + else begin + $error("\nb_sel_o value is incorrect ( %03b instead of %03b), instruction: %s %s", b_sel_o , grm_b_sel_o , raw_instr, instr_str ); + err_count++; + end + + alu_op_prop : assert property ( + @(posedge clk) disable iff(grm_illegal_instr_o) + alu_op_check |-> (grm_alu_op_o === alu_op_o ) + ) + else begin + $error("\nalu_op_o value is incorrect (%05b instead of %05b), instruction: %s %s", alu_op_o , grm_alu_op_o, raw_instr, instr_str ); + err_count++; + end + + csr_op_prop : assert property ( + @(posedge clk) disable iff(grm_illegal_instr_o) + csr_op_check |-> (grm_csr_op_o === csr_op_o ) + ) + else begin + $error("\ncsr_op_o value is incorrect ( %03b instead of %03b), instruction: %s %s", csr_op_o , grm_csr_op_o, raw_instr, instr_str ); + err_count++; + end + + csr_we_prop : assert property ( + @(posedge clk) disable iff(grm_illegal_instr_o) + csr_we_check |-> (grm_csr_we_o === csr_we_o ) + ) + else begin + $error("\ncsr_we_o value is incorrect ( %b instead of %b), instruction: %s %s", csr_we_o , grm_csr_we_o, raw_instr, instr_str ); + err_count++; + end + + mem_req_prop : assert property ( + @(posedge clk) disable iff(grm_illegal_instr_o) + mem_req_check |-> (grm_mem_req_o === mem_req_o ) + ) + else begin + $error("\nmem_req_o value is incorrect ( %b instead of %b), instruction: %s %s", mem_req_o , grm_mem_req_o, raw_instr, instr_str ); + err_count++; + end + + mem_we_prop : assert property ( + @(posedge clk) disable iff(grm_illegal_instr_o) + mem_we_check |-> (grm_mem_we_o === mem_we_o ) + ) + else begin + $error("\nmem_we_o value is incorrect ( %b instead of %b), instruction: %s %s", mem_we_o , grm_mem_we_o, raw_instr, instr_str ); + err_count++; + end + + mem_size_prop: assert property ( + @(posedge clk) disable iff(grm_illegal_instr_o) + mem_size_check |-> (grm_mem_size_o === mem_size_o) + ) + else begin + $error("\nmem_size_o value is incorrect ( %03b instead of %03b), instruction: %s %s", mem_size_o, grm_mem_size_o, raw_instr, instr_str); + err_count++; + end + + gpr_we_prop : assert property ( + @(posedge clk) disable iff(grm_illegal_instr_o) + gpr_we_check |-> (grm_gpr_we_o === gpr_we_o ) + ) + else begin + $error("\ngpr_we_o value is incorrect ( %b instead of %b), instruction: %s %s", gpr_we_o , grm_gpr_we_o, raw_instr, instr_str ); + err_count++; + end + + wb_sel_prop : assert property ( + @(posedge clk) disable iff(grm_illegal_instr_o) + wb_sel_check |-> (grm_wb_sel_o === wb_sel_o ) + ) + else begin + $error("\nwb_sel_o value is incorrect ( %b instead of %b), instruction: %s %s", wb_sel_o , grm_wb_sel_o, raw_instr, instr_str ); + err_count++; + end + + branch_prop : assert property ( + @(posedge clk) disable iff(grm_illegal_instr_o) + branch_check |-> (grm_branch_o === branch_o ) + ) + else begin + $error("\nbranch_o value is incorrect ( %b instead of %b), instruction: %s %s", branch_o , grm_branch_o, raw_instr, instr_str ); + err_count++; + end + + jal_prop : assert property ( + @(posedge clk) disable iff(grm_illegal_instr_o) + jal_check |-> (grm_jal_o === jal_o ) + ) + else begin + $error("\njal_o value is incorrect ( %b instead of %b), instruction: %s %s", jal_o , grm_jal_o , raw_instr, instr_str ); + err_count++; + end + + jalr_prop : assert property ( + @(posedge clk) disable iff(grm_illegal_instr_o) + jalr_check |-> (grm_jalr_o === jalr_o ) + ) + else begin + $error("\njalr_o value is incorrect ( %b instead of %b), instruction: %s %s", jalr_o , grm_jalr_o , raw_instr, instr_str ); + err_count++; + end + + mret_prop : assert property ( + @(posedge clk) disable iff(grm_illegal_instr_o) + mret_check |-> (grm_mret_o === mret_o ) + ) + else begin + $error("\nmret_o value is incorrect ( %b instead of %b), instruction: %s %s", mret_o , grm_mret_o , raw_instr, instr_str ); + err_count++; + end + + always_comb begin + case (opcode) + LUI_OPCODE, AUIPC_OPCODE, JAL_OPCODE: + raw_instr = $sformatf("%020b %05b %07b " , fetched_instr_i[31:12], fetched_instr_i[11:7], fetched_instr_i[6:0]); + JALR_OPCODE, LOAD_OPCODE, OP_IMM_OPCODE, SYSTEM_OPCODE: + raw_instr = $sformatf("%012b %05b %03b %05b %07b " , fetched_instr_i[31:20], fetched_instr_i[19:15], fetched_instr_i[14:12], fetched_instr_i[11:7], fetched_instr_i[6:0]); + BRANCH_OPCODE, STORE_OPCODE, OP_OPCODE: + raw_instr = $sformatf("%07b %05b %05b %03b %05b %07b", fetched_instr_i[31:25], fetched_instr_i[24:20], fetched_instr_i[19:15], fetched_instr_i[14:12], fetched_instr_i[11:7], fetched_instr_i[6:0]); + MISC_MEM_OPCODE: + raw_instr = $sformatf("%017b %03b %05b %07b " , fetched_instr_i[31:15], fetched_instr_i[14:12], fetched_instr_i[11:7], fetched_instr_i[6:0]); + default: + raw_instr = $sformatf("%032b " , fetched_instr_i); + endcase + end + + always_comb begin + if(&fetched_instr_i[1:0]) + case(opcode) LUI_OPCODE: begin - opcode_type = "( LUI )"; + instr_str = "( LUI )"; end AUIPC_OPCODE: begin - opcode_type = "( AUIPC )"; + instr_str = "( AUIPC )"; end JAL_OPCODE: begin - opcode_type = "( JAL )"; + instr_str = "( JAL )"; end JALR_OPCODE: begin - opcode_type = instr[14:12]? "( illegal_JALR )": "( JALR )"; + instr_str = func3? "( illegal_JALR )": "( JALR )"; end BRANCH_OPCODE: begin - case(instr[14:12]) - 3'b000: opcode_type = "( BEQ )"; - 3'b001: opcode_type = "( BNE )"; - 3'b100: opcode_type = "( BLT )"; - 3'b101: opcode_type = "( BGE )"; - 3'b110: opcode_type = "( BLTU )"; - 3'b111: opcode_type = "( BGEU )"; - default: opcode_type= "(illegal_BRANCH)"; - endcase + case(func3) + 3'b000: instr_str = "( BEQ )"; + 3'b001: instr_str = "( BNE )"; + 3'b100: instr_str = "( BLT )"; + 3'b101: instr_str = "( BGE )"; + 3'b110: instr_str = "( BLTU )"; + 3'b111: instr_str = "( BGEU )"; + default: instr_str= "(illegal_BRANCH)"; + endcase end LOAD_OPCODE: begin - case(instr[14:12]) - 3'b000: opcode_type = "( LB )"; - 3'b001: opcode_type = "( LH )"; - 3'b010: opcode_type = "( LW )"; - 3'b100: opcode_type = "( LBU )"; - 3'b101: opcode_type = "( LHU )"; - default: opcode_type= "( illegal_LOAD )"; - endcase + case(func3) + 3'b000: instr_str = "( LB )"; + 3'b001: instr_str = "( LH )"; + 3'b010: instr_str = "( LW )"; + 3'b100: instr_str = "( LBU )"; + 3'b101: instr_str = "( LHU )"; + default: instr_str= "( illegal_LOAD )"; + endcase end STORE_OPCODE: begin - case(instr[14:12]) - 3'b000: opcode_type = "( SB )"; - 3'b001: opcode_type = "( SH )"; - 3'b010: opcode_type = "( SW )"; - default: opcode_type = "(illegal_STORE)"; - endcase + case(func3) + 3'b000: instr_str = "( SB )"; + 3'b001: instr_str = "( SH )"; + 3'b010: instr_str = "( SW )"; + default: instr_str = "(illegal_STORE)"; + endcase end OP_IMM_OPCODE: begin - case({2'b0,instr[14:12]}) - ALU_ADD : opcode_type = "( ADDI )"; - ALU_XOR : opcode_type = "( XORI )"; - ALU_OR : opcode_type = "( ORI )"; - ALU_AND : opcode_type = "( ANDI )"; - ALU_SRL : opcode_type = {instr[31],instr[29:25]}? "(illegal_OP_IMM)": instr[30]? "( SRAI )": "( SRLI )"; - ALU_SLL : opcode_type = instr[31:25]? "(illegal_OP_IMM)": "( SLLI )"; - ALU_SLTS : opcode_type = "( SLTI )"; - ALU_SLTU : opcode_type = "( SLTIU )"; - default : opcode_type = "(illegal_OP_IMM)"; - endcase + case({2'b0,func3}) + ALU_ADD : instr_str = "( ADDI )"; + ALU_XOR : instr_str = "( XORI )"; + ALU_OR : instr_str = "( ORI )"; + ALU_AND : instr_str = "( ANDI )"; + ALU_SRL : instr_str = {fetched_instr_i[31],fetched_instr_i[29:25]}? "(illegal_OP_IMM)": fetched_instr_i[30]? "( SRAI )": "( SRLI )"; + ALU_SLL : instr_str = fetched_instr_i[31:25]? "(illegal_OP_IMM)": "( SLLI )"; + ALU_SLTS : instr_str = "( SLTI )"; + ALU_SLTU : instr_str = "( SLTIU )"; + default : instr_str = "(illegal_OP_IMM)"; + endcase end OP_OPCODE: begin - if(!instr[29:25]) - case({instr[31:30],instr[14:12]}) - ALU_ADD : opcode_type = "( ADD )"; - ALU_SUB : opcode_type = "( SUB )"; - ALU_XOR : opcode_type = "( XOR )"; - ALU_OR : opcode_type = "( OR )"; - ALU_AND : opcode_type = "( AND )"; - ALU_SRA : opcode_type = "( SRA )"; - ALU_SRL : opcode_type = "( SRL )"; - ALU_SLL : opcode_type = "( SLL )"; - ALU_SLTU : opcode_type = "( SLTU )"; - default : opcode_type = "( illegal_OP )"; + if(!fetched_instr_i[29:25]) + case({fetched_instr_i[31:30], func3}) + ALU_ADD : instr_str = "( ADD )"; + ALU_SUB : instr_str = "( SUB )"; + ALU_XOR : instr_str = "( XOR )"; + ALU_OR : instr_str = "( OR )"; + ALU_AND : instr_str = "( AND )"; + ALU_SRA : instr_str = "( SRA )"; + ALU_SRL : instr_str = "( SRL )"; + ALU_SLL : instr_str = "( SLL )"; + ALU_SLTU : instr_str = "( SLTU )"; + default : instr_str = "( illegal_OP )"; endcase - else opcode_type = "( illegal_OP )"; + else instr_str = "( illegal_OP )"; end MISC_MEM_OPCODE: begin - opcode_type = instr[14:12]? "(illegal_FENCE )": "( FENCE )"; + instr_str = func3 ? "(illegal_FENCE )": "( FENCE )"; end SYSTEM_OPCODE: begin - opcode_type = {instr[31:21], instr[19:7]}? "(illegal_SYSTEM)": instr[20]? "( EBREAK )": "( ECALL )"; + instr_str = "(illegal_SYSTEM)"; + case(func3) + 3'd0: begin + case(fetched_instr_i) + 32'h000_0_0_0_73: instr_str = "( ECALL )"; + 32'h001_0_0_0_73: instr_str = "( EBREAK )"; + 32'h302_0_0_0_73: instr_str = "( MRET )"; + endcase + end + 3'd1: instr_str = "( CSRRW )"; + 3'd2: instr_str = "( CSRRS )"; + 3'd3: instr_str = "( CSRRC )"; + 3'd5: instr_str = "( CSRRWI )"; + 3'd6: instr_str = "( CSRRSI )"; + 3'd7: instr_str = "( CSRRCI )"; + endcase end - default: opcode_type = "(illegal_opcode)"; - endcase - else opcode_type = "(illegal_opcode)"; + default: instr_str = "(illegal_opcode)"; + endcase + else instr_str = "(illegal_opcode)"; end + class riscv_instr; + rand bit [20:0] imm; + rand bit [ 6:0] func7; + rand bit [ 4:0] shamt; + rand bit [ 4:0] rs2; + rand bit [ 4:0] rs1; + rand bit [ 2:0] func3; + rand bit [ 4:0] rd; + rand bit [ 4:0] opcode; + + bit [31:0] bits; + + bit [31:0] system_instrs[3] = { + 32'h000_0_0_0_73, //ecall + 32'h001_0_0_0_73, //ebreak + 32'h302_0_0_0_73 //mret + }; + + constraint valid_opcode {opcode inside { LOAD_OPCODE, + MISC_MEM_OPCODE, + OP_IMM_OPCODE, + AUIPC_OPCODE, + STORE_OPCODE, + OP_OPCODE, + LUI_OPCODE, + BRANCH_OPCODE, + JALR_OPCODE, + JAL_OPCODE, + SYSTEM_OPCODE + };} + + constraint load_opcode { (opcode == LOAD_OPCODE ) -> !(func3 inside {3'h3, 3'h6, 3'h7});} + + constraint misc_mem_opcode { (opcode == MISC_MEM_OPCODE) -> (func3 == 3'b000);} + + constraint op_imm_opcode1 {((opcode == OP_IMM_OPCODE ) && (func3 == 3'h1)) -> (func7 == 7'h00);} + constraint op_imm_opcode2 {((opcode == OP_IMM_OPCODE ) && (func3 == 3'h5)) -> (func7 inside {7'h00, 7'h20});} + + constraint store_opcode { (opcode == STORE_OPCODE ) -> (func3 inside {3'h0, 3'h1, 3'h2});} + + constraint op_opcode1 {((opcode == OP_OPCODE ) && (func3 inside {3'b000, 3'b101})) -> (func7 inside {7'h00, 7'h20});} + constraint op_opcode2 {((opcode == OP_OPCODE ) && !(func3 inside {3'b000, 3'b101})) -> (func7 == 7'h00);} + + constraint branch_opcode { (opcode == BRANCH_OPCODE ) -> !(func3 inside {3'h2, 3'h3});} + + constraint jalr_opcode { (opcode == JALR_OPCODE ) -> (func3 == 3'h0);} + + constraint system_opcode { (opcode == SYSTEM_OPCODE ) -> !(func3 == 3'h4);} + + function void post_randomize(); + case(opcode) + LOAD_OPCODE, MISC_MEM_OPCODE, JALR_OPCODE: begin + bits = {imm[11:0], rs1, func3, rd, opcode, 2'b11}; + end + OP_IMM_OPCODE: begin + if(func3 inside {3'h1, 3'h5}) begin + bits = {func7, shamt, rs1, func3, rd, opcode, 2'b11}; + end + else begin + bits = {imm[11:0], rs1, func3, rd, opcode, 2'b11}; + end + end + AUIPC_OPCODE, LUI_OPCODE: begin + bits = {imm, opcode, 2'b11}; + end + STORE_OPCODE: begin + bits = {imm[11:5], rs2, rs1, func3, imm[4:0], opcode, 2'b11}; + end + OP_OPCODE: begin + bits = {func7, rs2, rs1, func3, rd, opcode, 2'b11}; + end + BRANCH_OPCODE: begin + bits = {imm[12], imm[10:5], rs2, rs1, func3, imm[4:1], imm[11], opcode, 2'b11}; + end + JAL_OPCODE: begin + bits = {imm[20], imm[10:1], imm[11], imm[19:12], rd, opcode, 2'b11}; + end + SYSTEM_OPCODE: begin + if(func3 == 3'h0) begin + bits = system_instrs[$urandom_range(3)]; + end + else begin + bits = {imm[11:0], rs1, func3, rd, opcode, 2'b11}; + end + end + default: begin + $fatal(1, "Missing opcode %0h in post_randomize", opcode); + end + endcase + endfunction + + endclass + endmodule -////////////////////////////////////////////////////////////////////////////////// -// Company: MIET -// Engineer: Alexey Kozin -// -// Create Date: 10/08/2023 07:39:15 AM -// Design Name: -// Module Name: decoder_riscv -// Project Name: RISCV_practicum -// Target Devices: Nexys A7-100T -// Tool Versions: -// Description: main decoder for risc-v processor -// -// Dependencies: -// -// Revision: -// Revision 0.01 - File Created -// Additional Comments: -// -////////////////////////////////////////////////////////////////////////////////// +/* ----------------------------------------------------------------------------- +* 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) : Alexey Kozin +* Email(s) : @edu.miet.ru +See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details. +* ------------------------------------------------------------------------------ +*/ module gpr_we_table (gis_ew_rpg, edocpo_6, edocpo_5, edocpo_4, edocpo_3, edocpo_2); output logic gis_ew_rpg; input edocpo_6, edocpo_5, edocpo_4, edocpo_3, edocpo_2; @@ -536,8 +892,6 @@ module csr_we_table (gis_ew_rsc, edocpo_6, edocpo_5, edocpo_4, edocpo_3, edocpo_ endcase endmodule - - module mem_req_table (gis_qer_mem, edocpo_6, edocpo_5, edocpo_4, edocpo_3, edocpo_2); output logic gis_qer_mem; input edocpo_6, edocpo_5, edocpo_4, edocpo_3, edocpo_2;