这个文章记录了我学习RISC-V蜂鸟E203处理器的学习历程
这是我正式阅读代码学习的第1个源代码文件
针对代码的学习,我结合自己的理解对每个module的接口,以及内部关键信号做了详细的注释说明
原创不易,请保护版权,转载联系作者,并请注明出处,标出原始链接谢谢~~
e203_exu_decode.v
/*
Copyright 2017 Silicon Integrated Microelectronics, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
//=====================================================================
//-- _______ ___
//-- ( ____/ /__/
//-- \ \ __
//-- ____\ \ / /
//-- /_______\ /_/ MICROELECTRONICS
//--
//=====================================================================
//
// Designer : Bob Hu
//
// Description:
// The decode module to decode the instruction details
//
// ====================================================================
// ========= 我自己的注释:
// exu根据指令的指示执行相应的动作,指令可以理解成编排好的二进制数,exu在执行前需要将
// 组成指令的这些二进制数解释成各个便于exu识别的信号,也就是所谓的指令译码
// 译码逻辑是纯组合逻辑,没有时序概念在里面;但是i_instr和in_pc等输入是按时序送进来,指令结果的输出也是由exu按时序去取
// =========
`include "e203_defines.v"
module e203_exu_decode(
//
// The IR stage to Decoder
input [`E203_INSTR_SIZE-1:0] i_instr, //取指逻辑取回的指令,作为输入等待译码
input [`E203_PC_SIZE-1:0] i_pc, //取值逻辑取回的指令的地址,也就是说取回的这条指令的PC值
input i_prdt_taken,
input i_misalgn, // The fetch misalign 输入的指令总线送过来的信号
input i_buserr, // The fetch bus error 输入的指令总线的错误信号
input i_muldiv_b2b, // The back2back case for mul/div
input dbg_mode, // 指示当前CPU是否处于dbg模式
//
// The Decoded Info-Bus 下面输出译码结果
output dec_rs1x0, //指令的源操作数rs1为X0的指示
output dec_rs2x0, //指令的源操作数rs2为X0的指示
output dec_rs1en, //指令是否需要操作rs1寄存器
output dec_rs2en, //指令是否需要操作rs2寄存器
output dec_rdwen, //指令是否需要操作rd寄存器
output [`E203_RFIDX_WIDTH-1:0] dec_rs1idx, //源操作数rs1的cpu内部地址
output [`E203_RFIDX_WIDTH-1:0] dec_rs2idx, //源操作数rs2的cpu内部地址
output [`E203_RFIDX_WIDTH-1:0] dec_rdidx, //目的操作数rd的cpu内部地址
output [`E203_DECINFO_WIDTH-1:0] dec_info, //解码出的指令信息,用于表示指令具体是啥指令,做啥操作的
output [`E203_XLEN-1:0] dec_imm, //译码出指令中的立即数
output [`E203_PC_SIZE-1:0] dec_pc, //译码的指令的PC值
output dec_misalgn, //直接根据i_misalgn生成的,如果总线送过来就是misalgn,那么指令就是misalign
output dec_buserr, //根据i_buserr直接生成的
output dec_ilegl, //解析出的指令不合法标记,就是说指令中有些位段是有要求的,比如说立即数中某一bit必须为0,如果不是0,那么就输出不合法等等
output dec_mulhsu, // mul-high-signed-unsigned rs1有符号,rs2无符号,相乘结果(64bit)的高32bit放入rd
output dec_mul , // mul rs1无符号,rs2无符号,(有符号无符号其实是一样的)相乘结果(64bit)的低32bit放入rd
output dec_div , // div rs1有符号,rs2有符号
output dec_rem , // 取 rs1有符号与rs2有符号数,取余数送到dr;
output dec_divu , // 无符号取商送dr
output dec_remu , // 无符号取余送dr
output dec_rv32, //表示当前指令是rsic-v32位指令,还是16位指令
output dec_bjp, //表示当前指令是普通指令还是分支跳转指令,表示是否属于bxx指令或jxx指令的一种
output dec_jal, //属于jal指令
output dec_jalr, //数据jalr指令
output dec_bxx, //属于BXX指令,(BEQ,BNE等带条件分支指令)
output [`E203_RFIDX_WIDTH-1:0] dec_jalr_rs1idx, //针对jalr指令,其首先要取出rs1操作数,然后与立即数相加才能得到值+4作为新的pc,为了取rs1,指令里带了rs1的地址(cpu内部index)
output [`E203_XLEN-1:0] dec_bjp_imm //针对bxx指令,如果条件满足的话,会把12bit立即数(有符号)×2然后与pc相加,作为新的pc;这里是译码出的指令的立即数
);
wire [32-1:0] rv32_instr = i_instr;
wire [16-1:0] rv16_instr = i_instr[15:0];
wire [6:0] opcode = rv32_instr[6:0]; //指令的低7bit为指令的操作码,指示了指令具体是哪一条指令,是做什么操作的
wire opcode_1_0_00 = (opcode[1:0] == 2'b00); // 这里判断操作码的低两位,低两位如果为11的话,说明不是16位指令,否则就是16位指令
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 = (~(i_instr[4:2] == 3'b111)) & opcode_1_0_11; //指令的[1:0]bit为2'b111,[4:2]bit != 3'b111;那么指令为32位指令
wire [4:0] rv32_rd = rv32_instr[11:7]; //指令编码中[11:7]是指令的目的操作数rd的cpu内部地址索引
wire [2:0] rv32_func3 = rv32_instr[14:12]; //编码指令功能的区域
wire [4:0] rv32_rs1 = rv32_instr[19:15]; //指令的源操作数rs1的cpu内部地址索引
wire [4:0] rv32_rs2 = rv32_instr[24:20]; //指令的源操作数rs2的cpu内部地址索引
wire [6:0] rv32_func7 = rv32_instr[31:25]; //编码指令功能的区域
wire [4:0] rv16_rd = rv32_rd;
wire [4:0] rv16_rs1 = rv16_rd; //16位指令源操作数和目的操作数在同一个位置,关于指令的具体字段含义可以查看书最后的附录F
wire [4:0] rv16_rs2 = rv32_instr[6:2];
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); // rs1源操作数是X0
wire rv32_rs2_x0 = (rv32_rs2 == 5'b00000); // rs2源操作数是X0
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);
wire rv32_load = opcode_6_5_00 & opcode_4_2_000 & opcode_1_0_11;
wire rv32_store = opcode_6_5_01 & opcode_4_2_000 & opcode_1_0_11;
wire rv32_madd = opcode_6_5_10 & opcode_4_2_000 & opcode_1_0_11;
wire rv32_branch = opcode_6_5_11 & opcode_4_2_000 & opcode_1_0_11;
wire rv32_load_fp = opcode_6_5_00 & opcode_4_2_001 & opcode_1_0_11; // FLW
wire rv32_store_fp = opcode_6_5_01 & opcode_4_2_001 & opcode_1_0_11;
wire rv32_msub = opcode_6_5_10 & opcode_4_2_001 & opcode_1_0_11;
wire rv32_jalr = opcode_6_5_11 & opcode_4_2_001 & opcode_1_0_11;
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;
wire rv32_nmsub = opcode_6_5_10 & opcode_4_2_010 & opcode_1_0_11;
wire rv32_resved0 = opcode_6_5_11 & opcode_4_2_010 & opcode_1_0_11;
wire rv32_miscmem = opcode_6_5_00 & opcode_4_2_011 & opcode_1_0_11; //00_011_11 FENCE
`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//}
wire rv32_nmadd = opcode_6_5_10 & opcode_4_2_011 & opcode_1_0_11;
wire rv32_jal = opcode_6_5_11 & opcode_4_2_011 & opcode_1_0_11;
wire rv32_op_imm = opcode_6_5_00 & opcode_4_2_100 & opcode_1_0_11;
wire rv32_op = opcode_6_5_01 & opcode_4_2_100 & opcode_1_0_11;
wire rv32_op_fp = opcode_6_5_10 & opcode_4_2_100 & opcode_1_0_11;
wire rv32_system = opcode_6_5_11 & opcode_4_2_100 & opcode_1_0_11;