E203是两级流水线结构,第一级是IFU进行取指操作,第二级包括译码、执行、交付和写回等功能。架构图如下:

https://www.cnblogs.com/images/cnblogs_com/mikewolf2002/1519640/o_pipeline.jpg

译码模块就是把机器码翻译成对应的输出功能。E203支持RV32IMAC,它的译码器模块是纯的组合电路实现,相对比较简单。只要熟悉了RiscV的指令规范,很容易看懂。

译码模块的输入信号来自于IFU模块,包括以下信号:

input  [`E203_INSTR_SIZE-1:0] i_instr, //来自IFU的32位指令
input [`E203_PC_SIZE-1:0] i_pc, //来自IFU的当前指令PC
input i_prdt_taken, //预测需要跳转,来自IFU模块的分支预测单元,对分支跳转指令有用,如果当前指令为分支跳转指令,该信号会被传递到相应的info_bus
input i_misalgn, // 表示当前指令遇到了分支跳转异常
input i_buserr, // 表面当前指令遭遇了取指存储器访问错误
input i_muldiv_b2b, // 前后临接的mul和div指令时置1,如果当前指令为乘法除法指令,该信号传递到相应的info_bus input dbg_mode, //debug模式下,忽视dret指令异常的情况

译码模块的输出包括以下信号:

output dec_rs1x0, // 该指令源操作数1为x0
output dec_rs2x0, // 该指令源操作数2为x0
output dec_rs1en, //该指令需要读取源操作数1
output dec_rs2en, //该指令需要读取源操作数2
output dec_rdwen, //该指令需要写结果操作数到目的寄存器
output [`E203_RFIDX_WIDTH-1:0] dec_rs1idx, //源操作数1的寄存器索引
output [`E203_RFIDX_WIDTH-1:0] dec_rs2idx, //源操作数2的寄存器索引
output [`E203_RFIDX_WIDTH-1:0] dec_rdidx, //目的寄存器索引
output [`E203_DECINFO_WIDTH-1:0] dec_info, //该指令的其它信息,被打包成一组宽信号,称之为信息总线(info bus).
output [`E203_XLEN-1:0] dec_imm, //该指令使用的立即数值。
output [`E203_PC_SIZE-1:0] dec_pc, // 该指令的pc值,等于输入的i_pc
output dec_misalgn, //指令遇到了分支跳转异常,等于输入的misalgn
output dec_buserr, //指令遭遇了取指存储器访问错误,等于输入的i_buserr
output dec_ilegl, //解码后,发现该指令是非法指令 output dec_mulhsu, //指令为 mulh或mulhsu或mulhu,这些乘法指令都把结果的高32位放到目的寄存器
output dec_mul , //指令为乘法指令
output dec_div , //指令为除法指令
output dec_rem ,//指数为取余数指令
output dec_divu ,//指令为无符号数除法指令
output dec_remu ,//指令为无符号数取余数指令 output dec_rv32, //该指令为32位指令,为0的话则是16位的压缩指令
output dec_bjp, //该指令为跳转指令,jal 或者jalr或者bxx指令
output dec_jal, //该指令为jal指令
output dec_jalr, //该指令为jalr指令
output dec_bxx, //该指令为bxx output [`E203_RFIDX_WIDTH-1:0] dec_jalr_rs1idx, //jalr指令中rs1寄存器索引
output [`E203_XLEN-1:0] dec_bjp_imm //bjp指令中的立即数

下面代码判断指令是32位指令还是16位指令的代码。操作码的低2位11,且3到5位不为111,则为rv32指令,否则为16位指令,因为E203不支持rv64,所以用一位信号就可以表示rv32和rvc了。

wire [32-1:0] rv32_instr = i_instr;
wire [16-1:0] rv16_instr = i_instr[15:0];
//指令的低7位为操作码
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);
//为32位指令或者16位指令
wire rv32 = (~(i_instr[4:2] == 3'b111)) & opcode_1_0_11;

下面代码为取出32位指令和16位指令的关键编码段。RVC的编码比较复杂,有些指令寄存器为3位表示,有些为5位表示,立即数通常都有旋转,旋转格式还很多。具体参见https://www.cnblogs.com/mikewolf2002/p/9884789.html

wire [4:0]  rv32_rd     = rv32_instr[11:7]; // 目的寄存器索引
wire [2:0] rv32_func3 = rv32_instr[14:12];//func3段
wire [4:0] rv32_rs1 = rv32_instr[19:15];//源操作数1寄存器索引
wire [4:0] rv32_rs2 = rv32_instr[24:20];//源操作数2寄存器索引
wire [6:0] rv32_func7 = rv32_instr[31:25];//func7段
//CR 15-12 func4, 11-7 rd/rs1, 6-2 rs2, 0-1 opcode
//CI 15-13 func3, 12 imm,11-7 rd/rs1,6-2 imm, 0-1 opcode
wire [4:0] rv16_rd = rv32_rd;
wire [4:0] rv16_rs1 = rv16_rd;
wire [4:0] rv16_rs2 = rv32_instr[6:2];
//CIW,CL,CS,CA,CB,CJ
//rdd=rd', rss1=rs1', rss2=rs2' short register, x8-x15, f8-f15
wire [4:0] rv16_rdd = {2'b01,rv32_instr[4:2]};
wire [4:0] rv16_rss1 = {2'b01,rv32_instr[9:7]};
wire [4:0] rv16_rss2 = rv16_rdd; wire [2:0] rv16_func3 = rv32_instr[15:13]

下面的代码产生指令中的关键信息判断,用于后面的代码复用。

// 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 rv16_func3_000 = (rv16_func3 == 3'b000);
wire rv16_func3_001 = (rv16_func3 == 3'b001);
wire rv16_func3_010 = (rv16_func3 == 3'b010);
wire rv16_func3_011 = (rv16_func3 == 3'b011);
wire rv16_func3_100 = (rv16_func3 == 3'b100);
wire rv16_func3_101 = (rv16_func3 == 3'b101);
wire rv16_func3_110 = (rv16_func3 == 3'b110);
wire rv16_func3_111 = (rv16_func3 == 3'b111); wire rv32_func7_0000000 = (rv32_func7 == 7'b0000000);
wire rv32_func7_0100000 = (rv32_func7 == 7'b0100000);
wire rv32_func7_0000001 = (rv32_func7 == 7'b0000001);
wire rv32_func7_0000101 = (rv32_func7 == 7'b0000101);
wire rv32_func7_0001001 = (rv32_func7 == 7'b0001001);
wire rv32_func7_0001101 = (rv32_func7 == 7'b0001101);
wire rv32_func7_0010101 = (rv32_func7 == 7'b0010101);
wire rv32_func7_0100001 = (rv32_func7 == 7'b0100001);
wire rv32_func7_0010001 = (rv32_func7 == 7'b0010001);
wire rv32_func7_0101101 = (rv32_func7 == 7'b0101101);
wire rv32_func7_1111111 = (rv32_func7 == 7'b1111111);
wire rv32_func7_0000100 = (rv32_func7 == 7'b0000100);
wire rv32_func7_0001000 = (rv32_func7 == 7'b0001000);
wire rv32_func7_0001100 = (rv32_func7 == 7'b0001100);
wire rv32_func7_0101100 = (rv32_func7 == 7'b0101100);
wire rv32_func7_0010000 = (rv32_func7 == 7'b0010000);
wire rv32_func7_0010100 = (rv32_func7 == 7'b0010100);
wire rv32_func7_1100000 = (rv32_func7 == 7'b1100000);
wire rv32_func7_1110000 = (rv32_func7 == 7'b1110000);
wire rv32_func7_1010000 = (rv32_func7 == 7'b1010000);
wire rv32_func7_1101000 = (rv32_func7 == 7'b1101000);
wire rv32_func7_1111000 = (rv32_func7 == 7'b1111000);
wire rv32_func7_1010001 = (rv32_func7 == 7'b1010001);
wire rv32_func7_1110001 = (rv32_func7 == 7'b1110001);
wire rv32_func7_1100001 = (rv32_func7 == 7'b1100001);
wire rv32_func7_1101001 = (rv32_func7 == 7'b1101001); 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 rv16_rs1_x0 = (rv16_rs1 == 5'b00000);
wire rv16_rs2_x0 = (rv16_rs2 == 5'b00000);
wire rv16_rd_x0 = (rv16_rd == 5'b00000);
wire rv16_rd_x2 = (rv16_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);

对32位指令和16位指令进行译码

//rv32 load指令,opcode是0000011,不同load指令通过func3区分
wire rv32_load = opcode_6_5_00 & opcode_4_2_000 & opcode_1_0_11; //rv32 store指令,opcode是0100011,不同store指令通过func3区分
wire rv32_store = opcode_6_5_01 & opcode_4_2_000 & opcode_1_0_11; //madd指令 opcode=1000011,乘加指令 //madd指令是浮点指令的一部分,fmadd.s, fmadd.d, fmadd.q,e203 不支持
// wire rv32_madd = opcode_6_5_10 & opcode_4_2_000 & opcode_1_0_11; //branch指令opcode=1100011, bxx指令jalr,jal操作码不同,单独判断
wire rv32_branch = opcode_6_5_11 & opcode_4_2_000 & opcode_1_0_11; //浮点数load指令,opcode=0000111,包括fsw,fsd,fsq
//wire rv32_load_fp = opcode_6_5_00 & opcode_4_2_001 & opcode_1_0_11; //浮点数store指令,opcode=0100111,包括flw,fld,flq
// wire rv32_store_fp = opcode_6_5_01 & opcode_4_2_001 & opcode_1_0_11; //msub指令 opcode=1000111,乘减指令
//msub指令是浮点指令的一部分,fmsub.s, fmsub.d, fmsub.q wire rv32_msub = opcode_6_5_10 & opcode_4_2_001 & opcode_1_0_11; //jalr指令的opcode=1100111
wire rv32_jalr = opcode_6_5_11 & opcode_4_2_001 & opcode_1_0_11; //opcode为0001011为第一类的定制指令,架构设计者可以实现自己定义的指令
//opcode为0101011为第二类的定制指令,还有第三和第四类的定制指令。 //wire rv32_custom0 = opcode_6_5_00 & opcode_4_2_010 & opcode_1_0_11;
//wire rv32_custom1 = opcode_6_5_01 & opcode_4_2_010 & opcode_1_0_11; //nmsub指令opcode=1001011, 负乘减操作x[rd]=-rs1*rs2+rs3
//wire rv32_nmsub = opcode_6_5_10 & opcode_4_2_010 & opcode_1_0_11; //保留的指令,为了将来扩展用 opcode=1101011
//wire rv32_resved0 = opcode_6_5_11 & opcode_4_2_010 & opcode_1_0_11; //存储器屏障指令, fence,fence.i, opcode=0001111 wire rv32_miscmem = opcode_6_5_00 & opcode_4_2_011 & opcode_1_0_11; //原子指令, opcode=0101111,不同的原子指令,通过func3和func7区分
`ifdef E203_SUPPORT_AMO//{
wire rv32_amo = opcode_6_5_01 & opcode_4_2_011 & opcode_1_0_11;
`endif//E203_SUPPORT_AMO}
`ifndef E203_SUPPORT_AMO//{
wire rv32_amo = 1'b0;
`endif//} //nmadd指令是浮点指令的一部分,fnmadd.s, fnmadd.d, fnmadd.q
wire rv32_nmadd = opcode_6_5_10 & opcode_4_2_011 & opcode_1_0_11; //jal指令的opcode=1101111
wire rv32_jal = opcode_6_5_11 & opcode_4_2_011 & opcode_1_0_11; //i型的运算指令,opcode=0010011,比如addi wire rv32_op_imm = opcode_6_5_00 & opcode_4_2_100 & opcode_1_0_11; //浮点R型的运算指令, opcode=1010011, 比如add
wire rv32_op = opcode_6_5_01 & opcode_4_2_100 & opcode_1_0_11; //R型的运算指令, opcode=0110011, 比如fadd.s
wire rv32_op_fp = opcode_6_5_10 & opcode_4_2_100 & opcode_1_0_11; //一些csr指令, opcode=1110011,比如csrrw
wire rv32_system = opcode_6_5_11 & opcode_4_2_100 & opcode_1_0_11; //auipc指令,opcode=0010111 wire rv32_auipc = opcode_6_5_00 & opcode_4_2_101 & opcode_1_0_11; //lui指令,opcode=0110111
wire rv32_lui = opcode_6_5_01 & opcode_4_2_101 & opcode_1_0_11; //第二、三类保留指令
// wire rv32_resved1 = opcode_6_5_10 & opcode_4_2_101 & opcode_1_0_11;
// wire rv32_resved2 = opcode_6_5_11 & opcode_4_2_101 & opcode_1_0_11; //slliw,srliw,addiw, sraiw等指令的操作码,opcode=0011011,这些都是64位指令 //wire rv32_op_imm_32= opcode_6_5_00 & opcode_4_2_110 & opcode_1_0_11; //addw,subw,…等64位算术运算指令
// wire rv32_op_32 = opcode_6_5_01 & opcode_4_2_110 & opcode_1_0_11; //第三,四类定制指令
// wire rv32_custom2 = opcode_6_5_10 & opcode_4_2_110 & opcode_1_0_11;
// wire rv32_custom3 = opcode_6_5_11 & opcode_4_2_110 & opcode_1_0_11;

//c.addispn, opcode=00, func3=000

wire rv16_addi4spn     = opcode_1_0_00 & rv16_func3_000;

//c.lw, opcode=00, func3=010
wire rv16_lw = opcode_1_0_00 & rv16_func3_010; //c.sw, opcode=00, func3=110
wire rv16_sw = opcode_1_0_00 & rv16_func3_110; //c.addi, opcode=01, func3=000
wire rv16_addi = opcode_1_0_01 & rv16_func3_000; //c.jal, opcode=01, func3=001
wire rv16_jal = opcode_1_0_01 & rv16_func3_001; //c.li, opcode=01, func3=010
wire rv16_li = opcode_1_0_01 & rv16_func3_010; //c.lui是对的,addi16sp还要判断11-7位是否是00010
wire rv16_lui_addi16sp = opcode_1_0_01 & rv16_func3_011; //一些c.alu指令,比如c.sub等等,opcode=01, func3=100,不同的c.alu指令之间,通过[12-10][6-6]来区分
wire rv16_miscalu = opcode_1_0_01 & rv16_func3_100; //c.j指令,opcode=01, func3=101
wire rv16_j = opcode_1_0_01 & rv16_func3_101 //c.beqz指令,opcode=01, func3=110
wire rv16_beqz = opcode_1_0_01 & rv16_func3_110; //c.bnez指令,opcode=01, func3=111
wire rv16_bnez = opcode_1_0_01 & rv16_func3_111; //c.slli指令,opcode=10, func3=000
wire rv16_slli = opcode_1_0_10 & rv16_func3_000; //c.lwsp指令,opcode=10, func3=010
wire rv16_lwsp = opcode_1_0_10 & rv16_func3_010; //c.jalr, c.add,c,mv opcode=10, func3=100
wire rv16_jalr_mv_add = opcode_1_0_10 & rv16_func3_100; //c.swsp指令,opcode=01, func3=101
wire rv16_swsp = opcode_1_0_10 & rv16_func3_110; `ifndef E203_HAS_FPU//{
wire rv16_flw = 1'b0;
wire rv16_fld = 1'b0;
wire rv16_fsw = 1'b0;
wire rv16_fsd = 1'b0;
wire rv16_fldsp = 1'b0;
wire rv16_flwsp = 1'b0;
wire rv16_fsdsp = 1'b0;
wire rv16_fswsp = 1'b0;
`endif//} //对c.lwsp, rd不能为x0 wire rv16_lwsp_ilgl = rv16_lwsp & rv16_rd_x0;//(RES, rd=0) //c.nop指令 wire rv16_nop = rv16_addi
& (~rv16_instr[12]) & (rv16_rd_x0) & (rv16_rs2_x0); //一些c.alu指令 wire rv16_srli = rv16_miscalu & (rv16_instr[11:10] == 2'b00);
wire rv16_srai = rv16_miscalu & (rv16_instr[11:10] == 2'b01);
wire rv16_andi = rv16_miscalu & (rv16_instr[11:10] == 2'b10); wire rv16_instr_12_is0 = (rv16_instr[12] == 1'b0);
wire rv16_instr_6_2_is0s = (rv16_instr[6:2] == 5'b0); //对压缩移位指令的合法性判断 wire rv16_sxxi_shamt_legl =
rv16_instr_12_is0 //shamt[5] must be zero for RV32C
& (~(rv16_instr_6_2_is0s)) //shamt[4:0] must be non-zero for RV32C
;
wire rv16_sxxi_shamt_ilgl = (rv16_slli | rv16_srli | rv16_srai) & (~rv16_sxxi_shamt_legl); wire rv16_addi16sp = rv16_lui_addi16sp & rv32_rd_x2;
wire rv16_lui = rv16_lui_addi16sp & (~rv32_rd_x0) & (~rv32_rd_x2); //C.LI is only valid when rd!=x0.
wire rv16_li_ilgl = rv16_li & (rv16_rd_x0);
//C.LUI is only valid when rd!=x0 or x2, and when the immediate is not equal to zero.
wire rv16_lui_ilgl = rv16_lui & (rv16_rd_x0 | rv16_rd_x2 | (rv16_instr_6_2_is0s & rv16_instr_12_is0)); wire rv16_li_lui_ilgl = rv16_li_ilgl | rv16_lui_ilgl; wire rv16_addi4spn_ilgl = rv16_addi4spn & (rv16_instr_12_is0 & rv16_rd_x0 & opcode_6_5_00);//(RES, nzimm=0, bits[12:5])
wire rv16_addi16sp_ilgl = rv16_addi16sp & rv16_instr_12_is0 & rv16_instr_6_2_is0s; //(RES, nzimm=0, bits 12,6:2) wire rv16_subxororand = rv16_miscalu & (rv16_instr[12:10] == 3'b011);//
wire rv16_sub = rv16_subxororand & (rv16_instr[6:5] == 2'b00);//
wire rv16_xor = rv16_subxororand & (rv16_instr[6:5] == 2'b01);//
wire rv16_or = rv16_subxororand & (rv16_instr[6:5] == 2'b10);//
wire rv16_and = rv16_subxororand & (rv16_instr[6:5] == 2'b11);// wire rv16_jr = rv16_jalr_mv_add //
& (~rv16_instr[12]) & (~rv16_rs1_x0) & (rv16_rs2_x0);// The RES rs1=0 illegal is already covered here
wire rv16_mv = rv16_jalr_mv_add //
& (~rv16_instr[12]) & (~rv16_rd_x0) & (~rv16_rs2_x0);
wire rv16_ebreak = rv16_jalr_mv_add //
& (rv16_instr[12]) & (rv16_rd_x0) & (rv16_rs2_x0);
wire rv16_jalr = rv16_jalr_mv_add //
& (rv16_instr[12]) & (~rv16_rs1_x0) & (rv16_rs2_x0);
wire rv16_add = rv16_jalr_mv_add //
& (rv16_instr[12]) & (~rv16_rd_x0) & (~rv16_rs2_x0); // ===========================================================================
// Branch Instructions
wire rv32_beq = rv32_branch & rv32_func3_000;
wire rv32_bne = rv32_branch & rv32_func3_001;
wire rv32_blt = rv32_branch & rv32_func3_100;
wire rv32_bgt = rv32_branch & rv32_func3_101;
wire rv32_bltu = rv32_branch & rv32_func3_110;
wire rv32_bgtu = rv32_branch & rv32_func3_111; // ===========================================================================
// System Instructions
wire rv32_ecall = rv32_system & rv32_func3_000 & (rv32_instr[31:20] == 12'b0000_0000_0000);
wire rv32_ebreak = rv32_system & rv32_func3_000 & (rv32_instr[31:20] == 12'b0000_0000_0001);
wire rv32_mret = rv32_system & rv32_func3_000 & (rv32_instr[31:20] == 12'b0011_0000_0010);
wire rv32_dret = rv32_system & rv32_func3_000 & (rv32_instr[31:20] == 12'b0111_1011_0010);
wire rv32_wfi = rv32_system & rv32_func3_000 & (rv32_instr[31:20] == 12'b0001_0000_0101);
// We dont implement the WFI and MRET illegal exception when the rs and rd is not zeros wire rv32_csrrw = rv32_system & rv32_func3_001;
wire rv32_csrrs = rv32_system & rv32_func3_010;
wire rv32_csrrc = rv32_system & rv32_func3_011;
wire rv32_csrrwi = rv32_system & rv32_func3_101;
wire rv32_csrrsi = rv32_system & rv32_func3_110;
wire rv32_csrrci = rv32_system & rv32_func3_111; wire rv32_dret_ilgl = rv32_dret & (~dbg_mode); wire rv32_ecall_ebreak_ret_wfi = rv32_system & rv32_func3_000;
wire rv32_csr = rv32_system & (~rv32_func3_000); // ============================================================
//c.addispn, opcode=00, func3=000
wire rv16_addi4spn = opcode_1_0_00 & rv16_func3_000; //c.lw, opcode=00, func3=010
wire rv16_lw = opcode_1_0_00 & rv16_func3_010; //c.sw, opcode=00, func3=110
wire rv16_sw = opcode_1_0_00 & rv16_func3_110; //c.addi, opcode=01, func3=000
wire rv16_addi = opcode_1_0_01 & rv16_func3_000; //c.jal, opcode=01, func3=001
wire rv16_jal = opcode_1_0_01 & rv16_func3_001; //c.li, opcode=01, func3=010
wire rv16_li = opcode_1_0_01 & rv16_func3_010; //addi16sp还要判断11-7位是否是00010
wire rv16_lui_addi16sp = opcode_1_0_01 & rv16_func3_011; //一些c.alu指令,比如c.sub等等,opcode=01, func3=100,不同的c.alu指令之间,通过[12-10][6-6]来区分
wire rv16_miscalu = opcode_1_0_01 & rv16_func3_100; //c.j指令,opcode=01, func3=101
wire rv16_j = opcode_1_0_01 & rv16_func3_101 //c.beqz指令,opcode=01, func3=110
wire rv16_beqz = opcode_1_0_01 & rv16_func3_110; //c.bnez指令,opcode=01, func3=111
wire rv16_bnez = opcode_1_0_01 & rv16_func3_111; //c.slli指令,opcode=10, func3=000
wire rv16_slli = opcode_1_0_10 & rv16_func3_000; //c.lwsp指令,opcode=10, func3=010
wire rv16_lwsp = opcode_1_0_10 & rv16_func3_010; //c.jalr, c.add,c,mv opcode=10, func3=100
wire rv16_jalr_mv_add = opcode_1_0_10 & rv16_func3_100; //c.swsp指令,opcode=01, func3=101
wire rv16_swsp = opcode_1_0_10 & rv16_func3_110; `ifndef E203_HAS_FPU//{
wire rv16_flw = 1'b0;
wire rv16_fld = 1'b0;
wire rv16_fsw = 1'b0;
wire rv16_fsd = 1'b0;
wire rv16_fldsp = 1'b0;
wire rv16_flwsp = 1'b0;
wire rv16_fsdsp = 1'b0;
wire rv16_fswsp = 1'b0;
`endif//} //对c.lwsp, rd不能为x0 wire rv16_lwsp_ilgl = rv16_lwsp & rv16_rd_x0;//(RES, rd=0) //c.nop指令,imm[6:2]位用rs2来代替,他们位置是相同的 wire rv16_nop = rv16_addi
& (~rv16_instr[12]) & (rv16_rd_x0) & (rv16_rs2_x0); //一些c.alu指令 wire rv16_srli = rv16_miscalu & (rv16_instr[11:10] == 2'b00);
wire rv16_srai = rv16_miscalu & (rv16_instr[11:10] == 2'b01);
wire rv16_andi = rv16_miscalu & (rv16_instr[11:10] == 2'b10); wire rv16_instr_12_is0 = (rv16_instr[12] == 1'b0);
wire rv16_instr_6_2_is0s = (rv16_instr[6:2] == 5'b0); //对压缩移位指令的合法性判断 wire rv16_sxxi_shamt_legl =
rv16_instr_12_is0 //shamt[5] must be zero for RV32C
& (~(rv16_instr_6_2_is0s)) //shamt[4:0] must be non-zero for RV32C
;
wire rv16_sxxi_shamt_ilgl = (rv16_slli | rv16_srli | rv16_srai) & (~rv16_sxxi_shamt_legl); wire rv16_addi16sp = rv16_lui_addi16sp & rv32_rd_x2;
wire rv16_lui = rv16_lui_addi16sp & (~rv32_rd_x0) & (~rv32_rd_x2); //C.LI is only valid when rd!=x0.
wire rv16_li_ilgl = rv16_li & (rv16_rd_x0);
//C.LUI is only valid when rd!=x0 or x2, and when the immediate is not equal to zero.
wire rv16_lui_ilgl = rv16_lui & (rv16_rd_x0 | rv16_rd_x2 | (rv16_instr_6_2_is0s & rv16_instr_12_is0)); wire rv16_li_lui_ilgl = rv16_li_ilgl | rv16_lui_ilgl; wire rv16_addi4spn_ilgl = rv16_addi4spn & (rv16_instr_12_is0 & rv16_rd_x0 & opcode_6_5_00);//(RES, nzimm=0, bits[12:5])
wire rv16_addi16sp_ilgl = rv16_addi16sp & rv16_instr_12_is0 & rv16_instr_6_2_is0s; //(RES, nzimm=0, bits 12,6:2) wire rv16_subxororand = rv16_miscalu & (rv16_instr[12:10] == 3'b011);//
wire rv16_sub = rv16_subxororand & (rv16_instr[6:5] == 2'b00);//
wire rv16_xor = rv16_subxororand & (rv16_instr[6:5] == 2'b01);//
wire rv16_or = rv16_subxororand & (rv16_instr[6:5] == 2'b10);//
wire rv16_and = rv16_subxororand & (rv16_instr[6:5] == 2'b11);// wire rv16_jr = rv16_jalr_mv_add //
& (~rv16_instr[12]) & (~rv16_rs1_x0) & (rv16_rs2_x0);// The RES rs1=0 illegal is already covered here
wire rv16_mv = rv16_jalr_mv_add //
& (~rv16_instr[12]) & (~rv16_rd_x0) & (~rv16_rs2_x0);
wire rv16_ebreak = rv16_jalr_mv_add //
& (rv16_instr[12]) & (rv16_rd_x0) & (rv16_rs2_x0);
wire rv16_jalr = rv16_jalr_mv_add //
& (rv16_instr[12]) & (~rv16_rs1_x0) & (rv16_rs2_x0);
wire rv16_add = rv16_jalr_mv_add //
& (rv16_instr[12]) & (~rv16_rd_x0) & (~rv16_rs2_x0);

32位系统指令,csr指令以及分支指令判断。

 // ===========================================================================
// Branch Instructions
wire rv32_beq = rv32_branch & rv32_func3_000;
wire rv32_bne = rv32_branch & rv32_func3_001;
wire rv32_blt = rv32_branch & rv32_func3_100;
wire rv32_bgt = rv32_branch & rv32_func3_101;
wire rv32_bltu = rv32_branch & rv32_func3_110;
wire rv32_bgtu = rv32_branch & rv32_func3_111; // ===========================================================================
// System Instructions
wire rv32_ecall = rv32_system & rv32_func3_000 & (rv32_instr[31:20] == 12'b0000_0000_0000);
wire rv32_ebreak = rv32_system & rv32_func3_000 & (rv32_instr[31:20] == 12'b0000_0000_0001);
wire rv32_mret = rv32_system & rv32_func3_000 & (rv32_instr[31:20] == 12'b0011_0000_0010);
wire rv32_dret = rv32_system & rv32_func3_000 & (rv32_instr[31:20] == 12'b0111_1011_0010);
wire rv32_wfi = rv32_system & rv32_func3_000 & (rv32_instr[31:20] == 12'b0001_0000_0101);
// We dont implement the WFI and MRET illegal exception when the rs and rd is not zeros wire rv32_csrrw = rv32_system & rv32_func3_001;
wire rv32_csrrs = rv32_system & rv32_func3_010;
wire rv32_csrrc = rv32_system & rv32_func3_011;
wire rv32_csrrwi = rv32_system & rv32_func3_101;
wire rv32_csrrsi = rv32_system & rv32_func3_110;
wire rv32_csrrci = rv32_system & rv32_func3_111; //如果为debug模式,则忽视dret不合法的判断
wire rv32_dret_ilgl = rv32_dret & (~dbg_mode); wire rv32_ecall_ebreak_ret_wfi = rv32_system & rv32_func3_000;
wire rv32_csr = rv32_system & (~rv32_func3_000); // ============================================================

译码模块输入包括信息总线,信息总线中包含一个3位的grp信息,EXU单元会根据这个grp把解码后的信号派遣 (dispatch)到该单元进行后续的的处理。E203并不包括EAI和FPU单元,其它5个单元是ALU单元的子单元。不同的指令会在这些子单元中进行后续的执行操作。

跳转和系统指令被BJP单元处理,

下面代码生成BJP单元所需的信息总线(Info Bus),BJP单元信息总线总共17位。每位表示的意思如下,其中,grp为010:

// The Branch and system group of instructions will be handled by BJP

assign dec_jal     = rv32_jal    | rv16_jal  | rv16_j;
assign dec_jalr = rv32_jalr | rv16_jalr | rv16_jr;
assign dec_bxx = rv32_branch | rv16_beqz | rv16_bnez;
assign dec_bjp = dec_jal | dec_jalr | dec_bxx; wire rv32_fence ;
wire rv32_fence_i;
wire rv32_fence_fencei; //判定当前指令是否是bjp指令
wire bjp_op = dec_bjp | rv32_mret | (rv32_dret & (~rv32_dret_ilgl)) | rv32_fence_fencei; //生成bjp信息总线信号 wire [`E203_DECINFO_BJP_WIDTH-1:0] bjp_info_bus;
assign bjp_info_bus[`E203_DECINFO_GRP ] = `E203_DECINFO_GRP_BJP;
assign bjp_info_bus[`E203_DECINFO_RV32 ] = rv32;
assign bjp_info_bus[`E203_DECINFO_BJP_JUMP ] = dec_jal | dec_jalr;
assign bjp_info_bus[`E203_DECINFO_BJP_BPRDT] = i_prdt_taken;
assign bjp_info_bus[`E203_DECINFO_BJP_BEQ ] = rv32_beq | rv16_beqz;
assign bjp_info_bus[`E203_DECINFO_BJP_BNE ] = rv32_bne | rv16_bnez;
assign bjp_info_bus[`E203_DECINFO_BJP_BLT ] = rv32_blt;
assign bjp_info_bus[`E203_DECINFO_BJP_BGT ] = rv32_bgt ;
assign bjp_info_bus[`E203_DECINFO_BJP_BLTU ] = rv32_bltu;
assign bjp_info_bus[`E203_DECINFO_BJP_BGTU ] = rv32_bgtu;
assign bjp_info_bus[`E203_DECINFO_BJP_BXX ] = dec_bxx;
assign bjp_info_bus[`E203_DECINFO_BJP_MRET ] = rv32_mret;
assign bjp_info_bus[`E203_DECINFO_BJP_DRET ] = rv32_dret;
assign bjp_info_bus[`E203_DECINFO_BJP_FENCE ] = rv32_fence;
assign bjp_info_bus[`E203_DECINFO_BJP_FENCEI] = rv32_fence_i;

E203 译码模块(1)的更多相关文章

  1. E203译码模块(3)

    下面的代码译码出指令的立即数,不同的指令有不同的立即数编码形式. //I类型指令的imm,[31:20],符号位扩展成32位. wire [31:0] rv32_i_imm = { {20{rv32_ ...

  2. E203 译码模块(2)

    常用的alu算术运算指令(包括ecall和 ebreak)在regular alu单元处理.regular alu单元为alu单元的一个子单元.regular单元的信息总线共21位,格式如下图所示,其 ...

  3. 蜂鸟E203 IFU模块

    E203的IFU(instruction fetch unit)模块主要功能和接口如下: IFU的PC生成单元产生下一条指令的PC. 该PC传输到地址判断和ICB生成单元,就是根据PC值产生相应读指请 ...

  4. what is the purpose of channel coding?(信道编码的作用?)

    信道.信道编码及其作用 1.信道(channel) 信道和通信电路并不等同,用来表示向某一个方向传送信息的媒体.因此一条通信线路往往包含一条发送信道和一条接收信道. 从通信的双方信息交互方式看有三个基 ...

  5. 串行CPU设计

    一.概述 串行CPU工作流程 串行CPU的时序流程如下图所示:取指.译码.执行.回写. 其中,取指.回写是与存储器打交道:而译码与执行则是CPU内部自个儿的操作. 我们究竟想要CPU干什么?     ...

  6. FPGA实现“打字机”(VGA & UART)

    看到标题中的"打字机"三个字,你是不是脑补了下面这幅图像.这是二战电影中常出现的道具,现在恐怕都见不到了. ●电影道具"打字机" 我要实现的当然不是这个样子,只 ...

  7. FPGA学习笔记(五)—— 组合逻辑电路功能的描述

    设计方法:    分析真值表规律        两种描述方式: 方式1:用assign描述,用阻塞赋值= 方式2:用always@(*)描述,用非阻塞赋值<=      选择功能的三种描述方式: ...

  8. 从Learning to Segment Every Thing说起

    原文地址:https://arxiv.org/pdf/1711.10370.pdf 这是何恺明老师发表于CVPR2018的一篇优秀paper. 先简单回顾一下语义分割领域之前的工作 那么什么是语义分割 ...

  9. Verilog HDL语言实现的单周期CPU设计(全部代码及其注释)

    写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文! 本博客全网唯一合法URL:ht ...

随机推荐

  1. Linux中raid磁盘阵列

    一.磁盘阵列(Redundant Arrays of Independent Disks,RAID) 有“独立磁盘构成的具有冗余能力的阵列”之意. 磁盘阵列是由很多价格较便宜的磁盘,以硬件(RAID卡 ...

  2. mysql操作数据表

    目录 创建数据表 列约束 查看数据表结构 列类型(字段类型) 整型 浮点型 字符串 时间日期类型 Date Time Datetime Timestamp Year 枚举enum 修改表名 增加字段 ...

  3. Python—闭包和装饰器

    闭包 定义:内部函数对外部函数变量的引用,则将该函数与用到的变量称为闭包. 闭包必须满足以下三个条件: 必须有一个内嵌函数. 内嵌函数必须引用外部函数中的变量. 外部函数返回值必须是内嵌函数的引用. ...

  4. 免密码登录postgresql

    如果在当前shell 下,如果设定 export PGPASSWORD='postgres密码' 环境变量,可以不用每次执行sql 语句或者导入一个sql 文件都输入一次密码的麻烦了.

  5. 5. Go语言—数据类型

    一.变量作用域 在函数内部声明的变量叫做局部变量,声明周期仅限于函数内部. 在函数外部声明的变量叫做全局变量,声明周期作用于整个包,如果是大写的,则作用于整个程序. 二.类型 1. 类型转换 ​ ty ...

  6. scanf函数和cin的区别、类的数组、C++排序函数

    给定n个字符串,将这n个字符串按照字典序进行排列,此处用排列函数是C++的库函数sort,产生如下两个疑问,望大佬解答 #include <iostream> #include <a ...

  7. 【第4题】 什么是https

    https是基于http和SSL/TLS实现的一个协议,他可以保证在网络上传输的数据都是加密的,从而保证数据安全. 接下来我们从http协议开始,提出想法并逐步进行分析,最终实现Https. 1. h ...

  8. 《为什么说Redis是单线程的以及Redis为什么这么快!》

    为什么说Redis是单线程的以及Redis为什么这么快!   一.前言 近乎所有与Java相关的面试都会问到缓存的问题,基础一点的会问到什么是“二八定律”.什么是“热数据和冷数据”,复杂一点的会问到缓 ...

  9. Django CSRF

    CSRF(Cross-site request forgery)跨站请求伪造 django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewM ...

  10. Fink| API| Time与Window

    1. Flink 批处理Api 1.1 Source Flink+kafka是如何实现exactly-once语义的 Flink通过checkpoint来保存数据是否处理完成的状态: 有JobMana ...