E203 译码模块(1)
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)的更多相关文章
- E203译码模块(3)
下面的代码译码出指令的立即数,不同的指令有不同的立即数编码形式. //I类型指令的imm,[31:20],符号位扩展成32位. wire [31:0] rv32_i_imm = { {20{rv32_ ...
- E203 译码模块(2)
常用的alu算术运算指令(包括ecall和 ebreak)在regular alu单元处理.regular alu单元为alu单元的一个子单元.regular单元的信息总线共21位,格式如下图所示,其 ...
- 蜂鸟E203 IFU模块
E203的IFU(instruction fetch unit)模块主要功能和接口如下: IFU的PC生成单元产生下一条指令的PC. 该PC传输到地址判断和ICB生成单元,就是根据PC值产生相应读指请 ...
- what is the purpose of channel coding?(信道编码的作用?)
信道.信道编码及其作用 1.信道(channel) 信道和通信电路并不等同,用来表示向某一个方向传送信息的媒体.因此一条通信线路往往包含一条发送信道和一条接收信道. 从通信的双方信息交互方式看有三个基 ...
- 串行CPU设计
一.概述 串行CPU工作流程 串行CPU的时序流程如下图所示:取指.译码.执行.回写. 其中,取指.回写是与存储器打交道:而译码与执行则是CPU内部自个儿的操作. 我们究竟想要CPU干什么? ...
- FPGA实现“打字机”(VGA & UART)
看到标题中的"打字机"三个字,你是不是脑补了下面这幅图像.这是二战电影中常出现的道具,现在恐怕都见不到了. ●电影道具"打字机" 我要实现的当然不是这个样子,只 ...
- FPGA学习笔记(五)—— 组合逻辑电路功能的描述
设计方法: 分析真值表规律 两种描述方式: 方式1:用assign描述,用阻塞赋值= 方式2:用always@(*)描述,用非阻塞赋值<= 选择功能的三种描述方式: ...
- 从Learning to Segment Every Thing说起
原文地址:https://arxiv.org/pdf/1711.10370.pdf 这是何恺明老师发表于CVPR2018的一篇优秀paper. 先简单回顾一下语义分割领域之前的工作 那么什么是语义分割 ...
- Verilog HDL语言实现的单周期CPU设计(全部代码及其注释)
写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文! 本博客全网唯一合法URL:ht ...
随机推荐
- 【XML】利用Dom4j读取XML文档以及写入XML文档
Dom4j简介 dom4j是一个Java的XML API,是jdom的升级品,用来读写XML文件的.dom4j是一个十分优秀的JavaXML API,具有性能优异.功能强大和极其易使用的特点,它的性能 ...
- 论文学习-wlg-基于二维材料的肖特基异质结构的通用尺度定律
目录 主要公式: 各个段落的内容 第一页 第二页 第三页 名词的含义 功函数: 电子亲和力 肖特基势垒 肖特基二极管的原理 非相对论性电子气:未知 Rashba自旋电子系统: 参考链接: 主要公式: ...
- SQLyog使用期限(治标不治本的,治本的还没找到)
在注册表中找到 HKEY_CURRENT_USER\Software 选中其中的类似下列文件名的文件 HKEY_CURRENT_USER\Software\{d58cb4b1-47f3-45cb ...
- 使用odbc从notes中导数据,配置odbc时报错
上次在配置odbc从notes中导数据时一直报错(忘记是什么错误了),后来,尝试着把notes和notesSQL的路径加入到path中就OK了!
- mysql简单的sql操作语句
一,常用.简单的SQL操作语句 1.数据库操作: 1)创建数据库: create database database_name: 创建并设置字符编码 create database database_ ...
- (办公)vue下载excel,后台用post方法
后台方法的参数必须是@RequestBody修饰的. 前台关键代码: axios ( { method : 'post', url : api.exportPlayTime , // 请求地址 dat ...
- 浅谈[].slice.call(arguments, 1)
今天在跟踪调试项目的代码时,发现在一个function中用到了这么一段[].slice.call(arguments, 1) 的代码.心中便起了疑惑,对于slice 和 call 的方法,倒是不怎么陌 ...
- 高阶JS---函数柯里化
什么是函数柯里化? 百度百科: 在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术.通 ...
- 理解docker镜像
镜像是用来启动容器的只读模板,是容器启动所需要的rootfs,类似于虚拟机所使用的镜像. 列出本机镜像 [root@localhost ~]# docker imagesREPOSITORY TAG ...
- angular和ionic4对过滤器pipe的使用
以下为自定义过滤器 import { Pipe, PipeTransform, Injectable } from '@angular/core'; import { DomSanitizer} fr ...