2019.4.30添加
粗略通读了整个蜂鸟e203的ALU模块的代码,其基本工作流程为:
在译码阶段,已经读取了对源操作数寄存器索引,源操作数的读取,需要写回的结果操作数,存在InfoBUS中的信息等
下面是在e203_exu_decode.v文件中对相关信息的提取,顺带一提,在RISC-V架构中,x0寄存器是一个相对特殊的寄存器,在v2.2版本的用户文档中是这样描述的:Register x0 is hardwired to the constant 0. 博主英文水平与基础的电路知识不佳,大致意思是这个寄存器是通过硬件手段强行置0的,也就是说这个寄存器无法写入值,其内存存放的永远都是0;
//e203_exu_decode.v
module e203_exu_decode(
....
)
....
//以下为对指令译码得到的信息
output dec_rs1x0,//源操作数1寄存器索引为x0
output dec_rs2x0,//源操作数2寄存器索引为x0
output dec_rs1en,//该指令需要读取源操作数1
output dec_rs2en,//该指令需要读取源操作数2
output dec_rdwen,//该指令需要写回结果操作数
output ['E203_RGIDX_WIDTH-1:0] dec_rs1idx,//源操作数1寄存器索引
output ['E203_RGIDX_WIDTH-1:0] dec_rs2idx,//源操作数2寄存器索引
output ['E203_RGIDX_WIDTH-1:0] dec_rdidx,//结果操作数寄存器索引
output ['E203_DECINFO_WIDTH-1:0] dec_info,//其余信息统一存在INFOBUS中
output ['E203_XLEN-1:0] dec_imm,//该指令使用立即数
...
output dec_ilegl,//该指令非法
...
endmodule
通过上面的代码片段可以看出译码完成后被传入ALU中的信号已经很规整了,ALU当中的子模块通过判断info bus中的信号来确定接下来需要复用运算数据通路子模块的具体部分,且可以认为此时两个源操作数和需要用来存放结果的寄存器都已经取到了。再结合下面的部分看相信就对这部分的工作流程有个框架已经在大家的脑海中成型了。
**************************************分割线**************************************************
首次添加2019.3.28,计划继续补充修改
// This module to implement the regular ALU instructions
//
//
// ====================================================================
`include "e203_defines.v"
module e203_exu_alu_rglr(
//
//
// The Handshake Interface
//
input alu_i_valid, // Handshake valid写入使能
output alu_i_ready, // Handshake ready写入准备就绪
//E203_XLEN32bit
input [`E203_XLEN-1:0] alu_i_rs1,
input [`E203_XLEN-1:0] alu_i_rs2,
input [`E203_XLEN-1:0] alu_i_imm,
input [`E203_PC_SIZE-1:0] alu_i_pc,
//当前E203_DECINFO_ALU_WIDTH为21[20:0],此项为从info总线取到的数据
input [`E203_DECINFO_ALU_WIDTH-1:0] alu_i_info,
//
//
// The ALU Write-back/Commit Interface
output alu_o_valid, // Handshake valid输出使能
input alu_o_ready, // Handshake ready输出就绪或完成
// The Write-Back Interface for Special (unaligned ldst and AMO instructions)
output [`E203_XLEN-1:0] alu_o_wbck_wdat,//连接至数据通路返回的结果,即写回的数据
output alu_o_wbck_err,
output alu_o_cmt_ecall,
output alu_o_cmt_ebreak,
output alu_o_cmt_wfi,
//
//
// To share the ALU datapath将发送至数据通路的数据
//
// The operands and info to ALU
output alu_req_alu_add ,
output alu_req_alu_sub ,
output alu_req_alu_xor ,
output alu_req_alu_sll ,
output alu_req_alu_srl ,
output alu_req_alu_sra ,
output alu_req_alu_or ,
output alu_req_alu_and ,
output alu_req_alu_slt ,
output alu_req_alu_sltu,
output alu_req_alu_lui ,
output [`E203_XLEN-1:0] alu_req_alu_op1,//两个源操作数
output [`E203_XLEN-1:0] alu_req_alu_op2,
input [`E203_XLEN-1:0] alu_req_alu_res,//从数据通路模块取回的结果
input clk,
input rst_n
);
wire op1pc = alu_i_info [`E203_DECINFO_ALU_OP1PC ];//判定第一个源操作数是否使用PC 16:16
wire op2imm = alu_i_info [`E203_DECINFO_ALU_OP2IMM ];//判定第二个源操作数是否为立即数 15:15
assign alu_req_alu_op1 = op1pc ? alu_i_pc : alu_i_rs1;//两个源操作数
assign alu_req_alu_op2 = op2imm ? alu_i_imm : alu_i_rs2;
wire nop = alu_i_info [`E203_DECINFO_ALU_NOP ] ;//17:17
wire ecall = alu_i_info [`E203_DECINFO_ALU_ECAL ];//18:18
wire ebreak = alu_i_info [`E203_DECINFO_ALU_EBRK ];//19:19
wire wfi = alu_i_info [`E203_DECINFO_ALU_WFI ];//20:20
// The NOP is encoded as ADDI, so need to uncheck it
assign alu_req_alu_add = alu_i_info [`E203_DECINFO_ALU_ADD ] & (~nop);//4:4
assign alu_req_alu_sub = alu_i_info [`E203_DECINFO_ALU_SUB ];//5:5
assign alu_req_alu_xor = alu_i_info [`E203_DECINFO_ALU_XOR ];//6:6
assign alu_req_alu_sll = alu_i_info [`E203_DECINFO_ALU_SLL ];//7
assign alu_req_alu_srl = alu_i_info [`E203_DECINFO_ALU_SRL ];//8
assign alu_req_alu_sra = alu_i_info [`E203_DECINFO_ALU_SRA ];//9
assign alu_req_alu_or = alu_i_info [`E203_DECINFO_ALU_OR ];//10
assign alu_req_alu_and = alu_i_info [`E203_DECINFO_ALU_AND ];//11
assign alu_req_alu_slt = alu_i_info [`E203_DECINFO_ALU_SLT ];//12
assign alu_req_alu_sltu = alu_i_info [`E203_DECINFO_ALU_SLTU];//13
assign alu_req_alu_lui = alu_i_info [`E203_DECINFO_ALU_LUI ];//14:14
assign alu_o_valid = alu_i_valid;//根据输入使能得到输出使能
assign alu_i_ready = alu_o_ready;//
assign alu_o_wbck_wdat = alu_req_alu_res;//将从数据通路取回的数据输出
assign alu_o_cmt_ecall = ecall;
assign alu_o_cmt_ebreak = ebreak;
assign alu_o_cmt_wfi = wfi;
// The exception or error result cannot write-back
assign alu_o_wbck_err = alu_o_cmt_ecall | alu_o_cmt_ebreak | alu_o_cmt_wfi;
endmodule