这个文章记录了我学习RISC-V蜂鸟E203处理器的学习历程
针对代码的学习,我结合自己的理解对每个module的接口,以及内部关键信号做了详细的注释说明
原创不易,请保护版权,须转载请私信通知联系作者,并请注明出处,标出原始链接,谢谢~~~
e203_exu_regfile.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 Regfile module to implement the core's general purpose registers file
//
// ====================================================================
// +++++++++++++++++++++++++++++++
// 这个文件记载的是cpu核的通用寄存器组的实现
// 读操作是直接译码取结果,读和读结果是直接的组合逻辑,写是1拍写入
// +++++++++++++++++++++++++++++++
`include "e203_defines.v"
module e203_exu_regfile(
input [`E203_RFIDX_WIDTH-1:0] read_src1_idx, // exu译码出的指令源操作数rs1的索引
input [`E203_RFIDX_WIDTH-1:0] read_src2_idx, // exu译码出的指令源操作数rs2的索引
output [`E203_XLEN-1:0] read_src1_dat, // 取出的源操作数的值
output [`E203_XLEN-1:0] read_src2_dat, //
input wbck_dest_wen, //exu执行结果的写回操作的写使能
input [`E203_RFIDX_WIDTH-1:0] wbck_dest_idx, // 写回操作的寄存器地址
input [`E203_XLEN-1:0] wbck_dest_dat, // 写回操作的待写入数据
output [`E203_XLEN-1:0] x1_r, // 由于x1常用于link寄存器用于函数的跳转返回,这里直接接出来的x1的值做加速,读x1不需要读端口
// 但是需要检查数据相关性
input test_mode,
input clk,
input rst_n
);
wire [`E203_XLEN-1:0] rf_r [`E203_RFREG_NUM-1:0]; // 定义一个reg堆
wire [`E203_RFREG_NUM-1:0] rf_wen; // 对应于每一个reg的写使能
`ifdef E203_REGFILE_LATCH_BASED //{ 如果使用锁存器来实现,需要将写端口使用dff专门寄存一拍,防止锁存器带来的写端口到读端口之间的锁存器穿通效应
// Use DFF to buffer the write-port
wire [`E203_XLEN-1:0] wbck_dest_dat_r;
sirv_gnrl_dffl #(`E203_XLEN) wbck_dat_dffl (wbck_dest_wen, wbck_dest_dat, wbck_dest_dat_r, clk);
wire [`E203_RFREG_NUM-1:0] clk_rf_ltch;
`endif//}
genvar i;
generate //{
for (i=0; i<`E203_RFREG_NUM; i=i+1) begin:regfile//{
if(i==0) begin: rf0 // rf0 为x0 寄存器的时候,该寄存器的值固定为0;其写信号也是固定为0
// x0 cannot be wrote since it is constant-zeros
assign rf_wen[i] = 1'b0;
assign rf_r[i] = `E203_XLEN'b0;
`ifdef E203_REGFILE_LATCH_BASED //{
assign clk_rf_ltch[i] = 1'b0;
`endif//}
end
else begin: rfno0 // 除x0以外的寄存器,
assign rf_wen[i] = wbck_dest_wen & (wbck_dest_idx == i) ; //写端口写有效,且写地址等于寄存器的索引,那么该寄存器的写有效置位
`ifdef E203_REGFILE_LATCH_BASED //{ // 如果寄存器采用latch来实现的话,那么用写有效信号作为latch的时钟门控,只有写有效的时候才给latch时钟
e203_clkgate u_e203_clkgate(
.clk_in (clk ),
.test_mode(test_mode),
.clock_en(rf_wen[i]),
.clk_out (clk_rf_ltch[i])
);
//from write-enable to clk_rf_ltch to rf_ltch
sirv_gnrl_ltch #(`E203_XLEN) rf_ltch (clk_rf_ltch[i], wbck_dest_dat_r, rf_r[i]);
`else//}{
sirv_gnrl_dffl #(`E203_XLEN) rf_dffl (rf_wen[i], wbck_dest_dat, rf_r[i], clk);
`endif//}
end
end//}
endgenerate//}
assign read_src1_dat = rf_r[read_src1_idx]; // 读通道的输出就是直接把寄存器堆进行译码输出,输入和输出处于同一拍
assign read_src2_dat = rf_r[read_src2_idx];
// wire [`E203_XLEN-1:0] x0 = rf_r[0];
// wire [`E203_XLEN-1:0] x1 = rf_r[1];
// wire [`E203_XLEN-1:0] x2 = rf_r[2];
// wire [`E203_XLEN-1:0] x3 = rf_r[3];
// wire [`E203_XLEN-1:0] x4 = rf_r[4];
// wire [`E203_XLEN-1:0] x5 = rf_r[5];
// wire [`E203_XLEN-1:0] x6 = rf_r[6];
// wire [`E203_XLEN-1:0] x7 = rf_r[7];
// wire [`E203_XLEN-1:0] x8 = rf_r[8];
// wire [`E203_XLEN-1:0] x9 = rf_r[9];
// wire [`E203_XLEN-1:0] x10 = rf_r[10];
// wire [`E203_XLEN-1:0] x11 = rf_r[11];
// wire [`E203_XLEN-1:0] x12 = rf_r[12];
// wire [`E203_XLEN-1:0] x13 = rf_r[13];
// wire [`E203_XLEN-1:0] x14 = rf_r[14];
// wire [`E203_XLEN-1:0] x15 = rf_r[15];
// `ifdef E203_RFREG_NUM_IS_32 //{
// wire [`E203_XLEN-1:0] x16 = rf_r[16];
// wire [`E203_XLEN-1:0] x17 = rf_r[17];
// wire [`E203_XLEN-1:0] x18 = rf_r[18];
// wire [`E203_XLEN-1:0] x19 = rf_r[19];
// wire [`E203_XLEN-1:0] x20 = rf_r[20];
// wire [`E203_XLEN-1:0] x21 = rf_r[21];
// wire [`E203_XLEN-1:0] x22 = rf_r[22];
// wire [`E203_XLEN-1:0] x23 = rf_r[23];
// wire [`E203_XLEN-1:0] x24 = rf_r[24];
// wire [`E203_XLEN-1:0] x25 = rf_r[25];
// wire [`E203_XLEN-1:0] x26 = rf_r[26];
// wire [`E203_XLEN-1:0] x27 = rf_r[27];
// wire [`E203_XLEN-1:0] x28 = rf_r[28];
// wire [`E203_XLEN-1:0] x29 = rf_r[29];
// wire [`E203_XLEN-1:0] x30 = rf_r[30];
// wire [`E203_XLEN-1:0] x31 = rf_r[31];
// `endif//}
assign x1_r = rf_r[1]; // 直接将X1的值拉出来
endmodule