SPI_Test/rtl/qubitmcu/qbmcu_decode.v

481 lines
20 KiB
Coq
Raw Normal View History

2024-06-25 16:41:01 +08:00
//+FHDR--------------------------------------------------------------------------------------------------------
// Company:
//-----------------------------------------------------------------------------------------------------------------
// File Name : qbmcu_decode.v
// Department :
// Author : PWY
// Author's Tel :
//-----------------------------------------------------------------------------------------------------------------
// Relese History
// Version Date Author Description
// 0.1 2024-03-13 PWY The decode module to decode the instruction details
//-----------------------------------------------------------------------------------------------------------------
// Keywords :
//
//-----------------------------------------------------------------------------------------------------------------
// Parameter
//
//-----------------------------------------------------------------------------------------------------------------
// Purpose :
//
//-----------------------------------------------------------------------------------------------------------------
// Target Device:
// Tool versions:
//-----------------------------------------------------------------------------------------------------------------
// Reuse Issues
// Reset Strategy:
// Clock Domains:
// Critical Timing:
// Asynchronous I/F:
// Synthesizable (y/n):
// Other:
//-FHDR--------------------------------------------------------------------------------------------------------
`include "qbmcu_defines.v"
module qbmcu_decode(
input clk // System Clock
,input rst_n // System reset,active low
,input dec_i_active // DEC module Active from MCU FSM
//////////////////////////////////////////////////////////////
// The IR stage to Decoder
,input [`QBMCU_INSTR_SIZE-1 :0] dec_i_instr
,input [`QBMCU_PC_SIZE-1 :0] dec_i_pc
//////////////////////////////////////////////////////////////
// The Decoded Info-Bus
//,output dec_o_rs1en
//,output dec_o_rs2en
,output dec_o_rdwen
,output [`QBMCU_RFIDX_WIDTH-1 :0] dec_o_rs1idx
,output [`QBMCU_RFIDX_WIDTH-1 :0] dec_o_rs2idx
,output [`QBMCU_RFIDX_WIDTH-1 :0] dec_o_rdidx
,output [`QBMCU_DECINFO_WIDTH-1:0] dec_o_info
,output [`QBMCU_XLEN-1 :0] dec_o_imm
,output [`QBMCU_PC_SIZE-1 :0] dec_o_pc
,output dec_o_ilegl
);
wire dec_i_active_r;
wire [`QBMCU_DECINFO_WIDTH-1:0] dec_info_w;
//dec_i_active_r
//sirv_gnrl_dffr #(1) dec_i_active_r_dffr (dec_i_active, dec_i_active_r, clk, rst_n);
assign dec_i_active_r = dec_i_active;
///////////////////////////////////////////////////////////////
//Instruction decoding
///////////////////////////////////////////////////////////////
wire [32-1:0] rv32_instr = dec_i_instr;
wire [6:0] opcode = rv32_instr[6:0];
//wire opcode_1_0_00 = (opcode[1:0] == 2'b00);
//wire opcode_1_0_01 = (opcode[1:0] == 2'b01);
//wire opcode_1_0_10 = (opcode[1:0] == 2'b10);
wire opcode_1_0_11 = (opcode[1:0] == 2'b11);
wire rv32 = (~(dec_i_instr[4:2] == 3'b111)) & opcode_1_0_11;
wire [4:0] rv32_rd = rv32_instr[11:7];
wire [2:0] rv32_func3 = rv32_instr[14:12];
wire [4:0] rv32_rs1 = rv32_instr[19:15];
wire [4:0] rv32_rs2 = rv32_instr[24:20];
wire [6:0] rv32_func7 = rv32_instr[31:25];
// We generate the signals and reused them as much as possible to save gatecounts
wire opcode_4_2_000 = (opcode[4:2] == 3'b000);
wire opcode_4_2_001 = (opcode[4:2] == 3'b001);
wire opcode_4_2_010 = (opcode[4:2] == 3'b010);
wire opcode_4_2_011 = (opcode[4:2] == 3'b011);
wire opcode_4_2_100 = (opcode[4:2] == 3'b100);
wire opcode_4_2_101 = (opcode[4:2] == 3'b101);
//wire opcode_4_2_110 = (opcode[4:2] == 3'b110);
wire opcode_4_2_111 = (opcode[4:2] == 3'b111);
wire opcode_6_5_00 = (opcode[6:5] == 2'b00);
wire opcode_6_5_01 = (opcode[6:5] == 2'b01);
//wire opcode_6_5_10 = (opcode[6:5] == 2'b10);
wire opcode_6_5_11 = (opcode[6:5] == 2'b11);
wire rv32_func3_000 = (rv32_func3 == 3'b000);
wire rv32_func3_001 = (rv32_func3 == 3'b001);
wire rv32_func3_010 = (rv32_func3 == 3'b010);
wire rv32_func3_011 = (rv32_func3 == 3'b011);
wire rv32_func3_100 = (rv32_func3 == 3'b100);
wire rv32_func3_101 = (rv32_func3 == 3'b101);
wire rv32_func3_110 = (rv32_func3 == 3'b110);
wire rv32_func3_111 = (rv32_func3 == 3'b111);
wire rv32_func7_0000000 = (rv32_func7 == 7'b0000000);
wire rv32_func7_0100000 = (rv32_func7 == 7'b0100000);
wire rv32_func7_1111111 = (rv32_func7 == 7'b1111111);
wire rv32_rs1_x0 = (rv32_rs1 == 5'b00000);
wire rv32_rs2_x0 = (rv32_rs2 == 5'b00000);
//wire rv32_rs2_x1 = (rv32_rs2 == 5'b00001);
wire rv32_rd_x0 = (rv32_rd == 5'b00000);
//wire rv32_rd_x2 = (rv32_rd == 5'b00010);
wire rv32_rs1_x31 = (rv32_rs1 == 5'b11111);
wire rv32_rs2_x31 = (rv32_rs2 == 5'b11111);
wire rv32_rd_x31 = (rv32_rd == 5'b11111);
wire rv32_load = opcode_6_5_00 & opcode_4_2_000 & opcode_1_0_11; //LB
wire rv32_store = opcode_6_5_01 & opcode_4_2_000 & opcode_1_0_11; //SB
wire rv32_branch = opcode_6_5_11 & opcode_4_2_000 & opcode_1_0_11; //B
wire rv32_jalr = opcode_6_5_11 & opcode_4_2_001 & opcode_1_0_11; //JALR
wire rv32_custom0 = opcode_6_5_00 & opcode_4_2_010 & opcode_1_0_11; //WAIT SENDC SEND
wire rv32_custom1 = opcode_6_5_01 & opcode_4_2_010 & opcode_1_0_11; //EXIT EXIT_IRQ
wire rv32_jal = opcode_6_5_11 & opcode_4_2_011 & opcode_1_0_11; //JAL
wire rv32_op_imm = opcode_6_5_00 & opcode_4_2_100 & opcode_1_0_11; //ADDI
wire rv32_op = opcode_6_5_01 & opcode_4_2_100 & opcode_1_0_11; //ADD
wire rv32_auipc = opcode_6_5_00 & opcode_4_2_101 & opcode_1_0_11; //AUIPC
wire rv32_lui = opcode_6_5_01 & opcode_4_2_101 & opcode_1_0_11; //LUI
// ===========================================================================
// Branch Instructions
wire rv32_beq = rv32_branch & rv32_func3_000; //B beq
wire rv32_bne = rv32_branch & rv32_func3_001; //B bne
wire rv32_blt = rv32_branch & rv32_func3_100; //B blt
wire rv32_bgt = rv32_branch & rv32_func3_101; //B bge
wire rv32_bltu = rv32_branch & rv32_func3_110; //B bltu
wire rv32_bgtu = rv32_branch & rv32_func3_111; //B bgeu
// ===========================================================================
// The Branch and system group of instructions will be handled by BJP
wire dec_jal = rv32_jal ;
wire dec_jalr = rv32_jalr;
wire dec_bxx = rv32_branch;
wire dec_bjp = dec_jal | dec_jalr | dec_bxx;
wire bjp_op = dec_bjp ;
wire [`QBMCU_DECINFO_BJP_WIDTH-1:0] bjp_info_bus;
assign bjp_info_bus[`QBMCU_DECINFO_GRP ] = `QBMCU_DECINFO_GRP_BJP;
assign bjp_info_bus[`QBMCU_DECINFO_RV32 ] = rv32;
assign bjp_info_bus[`QBMCU_DECINFO_BJP_JUMP ] = dec_jal | dec_jalr;
assign bjp_info_bus[`QBMCU_DECINFO_BJP_JALR ] = dec_jalr;
assign bjp_info_bus[`QBMCU_DECINFO_BJP_BEQ ] = rv32_beq ;
assign bjp_info_bus[`QBMCU_DECINFO_BJP_BNE ] = rv32_bne ;
assign bjp_info_bus[`QBMCU_DECINFO_BJP_BLT ] = rv32_blt;
assign bjp_info_bus[`QBMCU_DECINFO_BJP_BGT ] = rv32_bgt ;
assign bjp_info_bus[`QBMCU_DECINFO_BJP_BLTU ] = rv32_bltu;
assign bjp_info_bus[`QBMCU_DECINFO_BJP_BGTU ] = rv32_bgtu;
assign bjp_info_bus[`QBMCU_DECINFO_BJP_BXX ] = dec_bxx;
// ===========================================================================
// ALU Instructions
wire rv32_addi = rv32_op_imm & rv32_func3_000; // I addi
wire rv32_slti = rv32_op_imm & rv32_func3_010; // I slti
wire rv32_sltiu = rv32_op_imm & rv32_func3_011; // I sltiu
wire rv32_xori = rv32_op_imm & rv32_func3_100; // I xori
wire rv32_ori = rv32_op_imm & rv32_func3_110; // I ori
wire rv32_andi = rv32_op_imm & rv32_func3_111; // I andi
wire rv32_slli = rv32_op_imm & rv32_func3_001 & (rv32_instr[31:26] == 6'b000000); // I slli
wire rv32_srli = rv32_op_imm & rv32_func3_101 & (rv32_instr[31:26] == 6'b000000); // I srli
wire rv32_srai = rv32_op_imm & rv32_func3_101 & (rv32_instr[31:26] == 6'b010000); // I srai
wire rv32_sxxi_shamt_legl = (rv32_instr[25] == 1'b0); //shamt[5] must be zero for RV32I
wire rv32_sxxi_shamt_ilgl = (rv32_slli | rv32_srli | rv32_srai) & (~rv32_sxxi_shamt_legl);
wire rv32_add = rv32_op & rv32_func3_000 & rv32_func7_0000000; // R add
wire rv32_sub = rv32_op & rv32_func3_000 & rv32_func7_0100000; // R sub
wire rv32_sll = rv32_op & rv32_func3_001 & rv32_func7_0000000; // R sll
wire rv32_slt = rv32_op & rv32_func3_010 & rv32_func7_0000000; // R slt
wire rv32_sltu = rv32_op & rv32_func3_011 & rv32_func7_0000000; // R sltu
wire rv32_xor = rv32_op & rv32_func3_100 & rv32_func7_0000000; // R xor
wire rv32_srl = rv32_op & rv32_func3_101 & rv32_func7_0000000; // R srl
wire rv32_sra = rv32_op & rv32_func3_101 & rv32_func7_0100000; // R sra
wire rv32_or = rv32_op & rv32_func3_110 & rv32_func7_0000000; // R or
wire rv32_and = rv32_op & rv32_func3_111 & rv32_func7_0000000; // R and
wire rv32_nop = rv32_addi & rv32_rs1_x0 & rv32_rd_x0 & (~(|rv32_instr[31:20]));
wire alu_op = (~rv32_sxxi_shamt_ilgl) &
( rv32_op_imm
| rv32_op
| rv32_auipc
| rv32_lui
| rv32_nop)
;
wire need_imm;
wire [`QBMCU_DECINFO_ALU_WIDTH-1:0] alu_info_bus;
assign alu_info_bus[`QBMCU_DECINFO_GRP ] = `QBMCU_DECINFO_GRP_ALU;
assign alu_info_bus[`QBMCU_DECINFO_RV32 ] = rv32;
assign alu_info_bus[`QBMCU_DECINFO_ALU_ADD ] = rv32_add | rv32_addi | rv32_auipc ;
assign alu_info_bus[`QBMCU_DECINFO_ALU_SUB ] = rv32_sub ;
assign alu_info_bus[`QBMCU_DECINFO_ALU_SLT ] = rv32_slt | rv32_slti;
assign alu_info_bus[`QBMCU_DECINFO_ALU_SLTU ] = rv32_sltu | rv32_sltiu;
assign alu_info_bus[`QBMCU_DECINFO_ALU_XOR ] = rv32_xor | rv32_xori ;
assign alu_info_bus[`QBMCU_DECINFO_ALU_SLL ] = rv32_sll | rv32_slli ;
assign alu_info_bus[`QBMCU_DECINFO_ALU_SRL ] = rv32_srl | rv32_srli ;
assign alu_info_bus[`QBMCU_DECINFO_ALU_SRA ] = rv32_sra | rv32_srai ;
assign alu_info_bus[`QBMCU_DECINFO_ALU_OR ] = rv32_or | rv32_ori ;
assign alu_info_bus[`QBMCU_DECINFO_ALU_AND ] = rv32_and | rv32_andi ;
assign alu_info_bus[`QBMCU_DECINFO_ALU_LUI ] = rv32_lui ;
assign alu_info_bus[`QBMCU_DECINFO_ALU_OP2IMM] = need_imm;
assign alu_info_bus[`QBMCU_DECINFO_ALU_OP1PC ] = rv32_auipc;
assign alu_info_bus[`QBMCU_DECINFO_ALU_NOP ] = rv32_nop;
// ===========================================================================
// Load/Store Instructions
//wire rv32_lb = rv32_load & rv32_func3_000; // I lb
//wire rv32_lh = rv32_load & rv32_func3_001; // I lh
//wire rv32_lw = rv32_load & rv32_func3_010; // I lw
//wire rv32_lbu = rv32_load & rv32_func3_100; // I lbu
//wire rv32_lhu = rv32_load & rv32_func3_101; // I lhu
//wire rv32_sb = rv32_store & rv32_func3_000; // S sb
//wire rv32_sh = rv32_store & rv32_func3_001; // S sh
//wire rv32_sw = rv32_store & rv32_func3_010; // S sw
// Load/Store Data Size
wire [1:0] lsu_info_size = rv32_func3[1:0] ;
// Load/Store Data Sign
wire lsu_info_usign = rv32_func3[2];
wire ldst_op = rv32_load | rv32_store;
wire [`QBMCU_DECINFO_AGU_WIDTH-1:0] agu_info_bus;
assign agu_info_bus[`QBMCU_DECINFO_GRP ] = `QBMCU_DECINFO_GRP_AGU;
assign agu_info_bus[`QBMCU_DECINFO_RV32 ] = rv32;
assign agu_info_bus[`QBMCU_DECINFO_AGU_LOAD ] = rv32_load ;
assign agu_info_bus[`QBMCU_DECINFO_AGU_STORE ] = rv32_store ;
assign agu_info_bus[`QBMCU_DECINFO_AGU_SIZE ] = lsu_info_size;
assign agu_info_bus[`QBMCU_DECINFO_AGU_USIGN ] = lsu_info_usign;
assign agu_info_bus[`QBMCU_DECINFO_AGU_OP2IMM ] = need_imm;
// ===========================================================================
// Expand instructions : WAIT SEND SENC EXIT EiXT_IRQ
wire rv32_wait = rv32_custom0 & rv32_func3_000; //WAIT
wire rv32_send = rv32_custom0 & rv32_func3_010; //SEND
wire rv32_sendc = rv32_custom0 & rv32_func3_011; //WAIT
wire rv32_exit = rv32_custom1 & rv32_func3_000; //EXIT
wire rv32_exiti = rv32_custom1 & rv32_func3_001; //EXIT_IRQ
wire ext_op = (~rv32_sxxi_shamt_ilgl) &
( rv32_wait
| rv32_send
| rv32_sendc
| rv32_exit
| rv32_exiti)
;
wire [`QBMCU_DECINFO_EXT_WIDTH-1:0] ext_info_bus;
assign ext_info_bus[`QBMCU_DECINFO_GRP ] = `QBMCU_DECINFO_GRP_EXT;
assign ext_info_bus[`QBMCU_DECINFO_RV32 ] = rv32;
assign ext_info_bus[`QBMCU_DECINFO_EXT_WAIT ] = rv32_wait;
assign ext_info_bus[`QBMCU_DECINFO_EXT_SEND ] = rv32_send;
assign ext_info_bus[`QBMCU_DECINFO_EXT_SENDC ] = rv32_sendc;
assign ext_info_bus[`QBMCU_DECINFO_EXT_EXIT ] = rv32_exit;
assign ext_info_bus[`QBMCU_DECINFO_EXT_EXITI ] = rv32_exiti ;
assign ext_info_bus[`QBMCU_DECINFO_EXT_OP2IMM] = need_imm;
// Reuse the common signals as much as possible to save gatecounts
wire rv32_all0s_ilgl = rv32_func7_0000000
& rv32_rs2_x0
& rv32_rs1_x0
& rv32_func3_000
& rv32_rd_x0
& opcode_6_5_00
& opcode_4_2_000
& (opcode[1:0] == 2'b00);
wire rv32_all1s_ilgl = rv32_func7_1111111
& rv32_rs2_x31
& rv32_rs1_x31
& rv32_func3_111
& rv32_rd_x31
& opcode_6_5_11
& opcode_4_2_111
& (opcode[1:0] == 2'b11);
wire rv_all0s1s_ilgl = (rv32_all0s_ilgl | rv32_all1s_ilgl);
//
// All the RV32I need RD register except the
// * Branch, Store,
wire rv32_need_rd = (~rv32_rd_x0 )
& (~rv32_branch )
& (~rv32_store )
& (~rv32_custom1);
// All the RV32I need RS1 register except the
// * lui
// * auipc
// * jal
//wire rv32_need_rs1 = (~rv32_rs1_x0)
// & (~rv32_lui )
// & (~rv32_auipc )
// & (~rv32_jal );
// Following RV32IMA instructions need RS2 register
// * branch
// * store
// * rv32_op
//wire rv32_need_rs2 = (~rv32_rs2_x0)
// & ((rv32_branch)
// | (rv32_store )
// | (rv32_op ));
wire [31:0] rv32_i_imm = {
{20{rv32_instr[31]}}
, rv32_instr[31:20]
};
wire [31:0] rv32_s_imm = {
{20{rv32_instr[31]}}
, rv32_instr[31:25]
, rv32_instr[11:7]
};
wire [31:0] rv32_b_imm = {
{19{rv32_instr[31]}}
, rv32_instr[31]
, rv32_instr[7]
, rv32_instr[30:25]
, rv32_instr[11:8]
, 1'b0
};
wire [31:0] rv32_u_imm = {rv32_instr[31:12],12'b0};
wire [31:0] rv32_j_imm = {
{11{rv32_instr[31]}}
, rv32_instr[31]
, rv32_instr[19:12]
, rv32_instr[20]
, rv32_instr[30:21]
, 1'b0
};
//expand immediate operands
wire [31:0] rv32_e_imm = rv32_i_imm;
// It will select i-type immediate when
// * rv32_op_imm
// * rv32_jalr
// * rv32_load
wire rv32_imm_sel_i = rv32_op_imm | rv32_jalr | rv32_load;
//wire rv32_imm_sel_jalr = rv32_jalr;
//wire [31:0] rv32_jalr_imm = rv32_i_imm;
// It will select u-type immediate when
// * rv32_lui, rv32_auipc
wire rv32_imm_sel_u = rv32_lui | rv32_auipc;
// It will select j-type immediate when
// * rv32_jal
wire rv32_imm_sel_j = rv32_jal;
//wire rv32_imm_sel_jal = rv32_jal;
//wire [31:0] rv32_jal_imm = rv32_j_imm;
// It will select b-type immediate when
// * rv32_branch
wire rv32_imm_sel_b = rv32_branch;
//wire rv32_imm_sel_bxx = rv32_branch;
//wire [31:0] rv32_bxx_imm = rv32_b_imm;
// It will select s-type immediate when
// * rv32_store
wire rv32_imm_sel_s = rv32_store;
// It will select e-type immediate when
// * rv32_custom0
// * rv32_custom1
wire rv32_imm_sel_e = rv32_custom0 | rv32_custom1;
wire [31:0] rv32_imm =
({32{rv32_imm_sel_i}} & rv32_i_imm)
| ({32{rv32_imm_sel_s}} & rv32_s_imm)
| ({32{rv32_imm_sel_b}} & rv32_b_imm)
| ({32{rv32_imm_sel_u}} & rv32_u_imm)
| ({32{rv32_imm_sel_j}} & rv32_j_imm)
| ({32{rv32_imm_sel_e}} & rv32_e_imm)
;
wire rv32_need_imm =
rv32_imm_sel_i
| rv32_imm_sel_s
| rv32_imm_sel_b
| rv32_imm_sel_u
| rv32_imm_sel_j
| rv32_imm_sel_e
;
assign need_imm = rv32_need_imm ;
//dec_o_imm
sirv_gnrl_dfflr #(`QBMCU_XLEN) dec_o_imm_dfflr (dec_i_active_r, rv32_imm, dec_o_imm, clk, rst_n);
//dec_o_pc
sirv_gnrl_dfflr #(`QBMCU_PC_SIZE) dec_o_pc_dfflr (dec_i_active_r, dec_i_pc, dec_o_pc, clk, rst_n);
assign dec_info_w =
({`QBMCU_DECINFO_WIDTH{alu_op}} & {{`QBMCU_DECINFO_WIDTH-`QBMCU_DECINFO_ALU_WIDTH{1'b0}},alu_info_bus})
| ({`QBMCU_DECINFO_WIDTH{ldst_op}} & {{`QBMCU_DECINFO_WIDTH-`QBMCU_DECINFO_AGU_WIDTH{1'b0}},agu_info_bus})
| ({`QBMCU_DECINFO_WIDTH{bjp_op}} & {{`QBMCU_DECINFO_WIDTH-`QBMCU_DECINFO_BJP_WIDTH{1'b0}},bjp_info_bus})
| ({`QBMCU_DECINFO_WIDTH{ext_op}} & {{`QBMCU_DECINFO_WIDTH-`QBMCU_DECINFO_EXT_WIDTH{1'b0}},ext_info_bus})
;
//dec_o_info
sirv_gnrl_dfflr #(`QBMCU_DECINFO_WIDTH) dec_o_info_dfflr (dec_i_active_r, dec_info_w, dec_o_info, clk, rst_n);
//dec_o_rs1idx
sirv_gnrl_dfflr #(`QBMCU_RFIDX_WIDTH) dec_o_rs1idx_dfflr (dec_i_active_r, rv32_rs1[`QBMCU_RFIDX_WIDTH-1:0], dec_o_rs1idx, clk, rst_n);
//dec_o_rs2idx
sirv_gnrl_dfflr #(`QBMCU_RFIDX_WIDTH) dec_o_rs2idx_dfflr (dec_i_active_r, rv32_rs2[`QBMCU_RFIDX_WIDTH-1:0], dec_o_rs2idx, clk, rst_n);
//dec_o_rdidx
sirv_gnrl_dfflr #(`QBMCU_RFIDX_WIDTH) dec_o_rdidx_dfflr (dec_i_active_r, rv32_rd[`QBMCU_RFIDX_WIDTH-1:0], dec_o_rdidx, clk, rst_n);
//dec_o_rs1en
//sirv_gnrl_dfflr #(1) dec_o_rs1en_dfflr (dec_i_active_r, rv32_need_rs1, dec_o_rs1en, clk, rst_n);
//dec_o_rs2en
//sirv_gnrl_dfflr #(1) dec_o_rs2en_dfflr (dec_i_active_r, rv32_need_rs2, dec_o_rs2en, clk, rst_n);
//dec_o_rdwen
sirv_gnrl_dfflr #(1) dec_o_rdwen_dfflr (dec_i_active_r, rv32_need_rd, dec_o_rdwen, clk, rst_n);
wire legl_ops =
alu_op
| ldst_op
| bjp_op
| ext_op
;
wire rv_index_ilgl = 1'b0;
wire dec_ilegl_w =
(rv_all0s1s_ilgl)
| (rv_index_ilgl)
| (rv32_sxxi_shamt_ilgl)
| (~legl_ops);
//dec_o_ilegl
sirv_gnrl_dfflr #(1) dec_o_ilegl_dfflr (dec_i_active_r, dec_ilegl_w, dec_o_ilegl, clk, rst_n);
endmodule
`include "qbmcu_undefines.v"