From 9943d026001867df20030637043c83b784c70e9d Mon Sep 17 00:00:00 2001 From: liangkangnan Date: Wed, 31 Mar 2021 18:00:19 +0800 Subject: [PATCH] temp commit Signed-off-by: liangkangnan --- rtl/core/clint.sv | 446 ++++++++++---------- rtl/core/csr_reg.sv | 280 ++++++------- rtl/core/defines.sv | 244 +++++------ rtl/core/divider.sv | 392 +++++++++--------- rtl/core/exu.sv | 763 ++++++++++++++++++----------------- rtl/core/exu_alu_datapath.sv | 508 +++++++++++------------ rtl/core/exu_commit.sv | 184 ++++----- rtl/core/exu_dispatch.sv | 420 +++++++++---------- rtl/core/exu_mem.sv | 324 +++++++-------- rtl/core/exu_muldiv.sv | 212 +++++----- rtl/core/gpr_reg.sv | 184 ++++----- rtl/core/idu.sv | 606 ++++++++++++++-------------- rtl/core/idu_exu.sv | 187 ++++----- rtl/core/ifu.sv | 251 ++++++------ rtl/core/ifu_idu.sv | 102 ++--- rtl/core/pipe_ctrl.sv | 130 +++--- rtl/core/rst_ctrl.sv | 118 +++--- rtl/core/tinyriscv_core.sv | 15 +- rtl/core/tracer.sv | 6 +- 19 files changed, 2704 insertions(+), 2668 deletions(-) diff --git a/rtl/core/clint.sv b/rtl/core/clint.sv index 2421b1b..9f1277a 100644 --- a/rtl/core/clint.sv +++ b/rtl/core/clint.sv @@ -1,223 +1,223 @@ - /* - Copyright 2020 Blue Liang, liangkangnan@163.com - - 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. - */ - -`include "defines.sv" - -// core local interruptor module -// 核心中断管理、仲裁模块 -module clint( - - input wire clk, - input wire rst_n, - - // from core - input wire[`INT_WIDTH-1:0] int_flag_i, // 中断输入信号 - - // from exu - input wire inst_ecall_i, // ecall指令 - input wire inst_ebreak_i, // ebreak指令 - input wire inst_mret_i, // mret指令 - input wire[31:0] inst_addr_i, // 指令地址 - input wire jump_flag_i, - input wire mem_access_misaligned_i, - - // from csr_reg - input wire[31:0] csr_mtvec_i, // mtvec寄存器 - input wire[31:0] csr_mepc_i, // mepc寄存器 - input wire[31:0] csr_mstatus_i, // mstatus寄存器 - - // to csr_reg - output reg csr_we_o, // 写CSR寄存器标志 - output reg[31:0] csr_waddr_o, // 写CSR寄存器地址 - output reg[31:0] csr_wdata_o, // 写CSR寄存器数据 - - // to pipe_ctrl - output wire stall_flag_o, // 流水线暂停标志 - output wire[31:0] int_addr_o, // 中断入口地址 - output wire int_assert_o // 中断标志 - - ); - - // 中断状态定义 - localparam S_INT_IDLE = 4'b0001; - localparam S_INT_SYNC_ASSERT = 4'b0010; - localparam S_INT_ASYNC_ASSERT = 4'b0100; - localparam S_INT_MRET = 4'b1000; - - // 写CSR寄存器状态定义 - localparam S_CSR_IDLE = 5'b00001; - localparam S_CSR_MSTATUS = 5'b00010; - localparam S_CSR_MEPC = 5'b00100; - localparam S_CSR_MSTATUS_MRET = 5'b01000; - localparam S_CSR_MCAUSE = 5'b10000; - - reg[3:0] int_state; - reg[4:0] csr_state; - reg[31:0] inst_addr; - reg[31:0] cause; - - wire global_int_en = csr_mstatus_i[3]; - - assign stall_flag_o = ((int_state != S_INT_IDLE) | (csr_state != S_CSR_IDLE))? 1'b1: 1'b0; - - // 将跳转标志放在流水线上传递 - wire pc_state_jump_flag; - gen_rst_0_dff #(1) pc_state_dff(clk, rst_n, jump_flag_i, pc_state_jump_flag); - - wire if_state_jump_flag; - gen_rst_0_dff #(1) if_state_dff(clk, rst_n, pc_state_jump_flag, if_state_jump_flag); - - wire id_state_jump_flag; - gen_rst_0_dff #(1) id_state_dff(clk, rst_n, if_state_jump_flag, id_state_jump_flag); - - wire ex_state_jump_flag; - gen_rst_0_dff #(1) ex_state_dff(clk, rst_n, id_state_jump_flag, ex_state_jump_flag); - - wire[3:0] state_jump_flag = {pc_state_jump_flag, if_state_jump_flag, id_state_jump_flag, ex_state_jump_flag}; - // 如果流水线没有冲刷完成则不响应中断 - wire inst_addr_valid = (~(|state_jump_flag)) | ex_state_jump_flag; - - - // 中断仲裁逻辑 - always @ (*) begin - // 同步中断 - if (inst_ecall_i | inst_ebreak_i | mem_access_misaligned_i) begin - int_state = S_INT_SYNC_ASSERT; - // 异步中断 - end else if ((int_flag_i != `INT_NONE) & global_int_en & inst_addr_valid) begin - int_state = S_INT_ASYNC_ASSERT; - // 中断返回 - end else if (inst_mret_i) begin - int_state = S_INT_MRET; - // 无中断响应 - end else begin - int_state = S_INT_IDLE; - end - end - - // 写CSR寄存器状态切换 - always @ (posedge clk or negedge rst_n) begin - if (!rst_n) begin - csr_state <= S_CSR_IDLE; - cause <= 32'h0; - inst_addr <= 32'h0; - end else begin - case (csr_state) - S_CSR_IDLE: begin - case (int_state) - // 同步中断 - S_INT_SYNC_ASSERT: begin - csr_state <= S_CSR_MEPC; - // 在中断处理函数里会将中断返回地址加4 - inst_addr <= inst_addr_i; - cause <= inst_ebreak_i? 32'd3: - inst_ecall_i? 32'd11: - mem_access_misaligned_i? 32'd4: - 32'd10; - end - // 异步中断 - S_INT_ASYNC_ASSERT: begin - csr_state <= S_CSR_MEPC; - inst_addr <= inst_addr_i; - // 定时器中断 - cause <= 32'h80000004; - end - // 中断返回 - S_INT_MRET: begin - csr_state <= S_CSR_MSTATUS_MRET; - end - endcase - end - S_CSR_MEPC: begin - csr_state <= S_CSR_MSTATUS; - end - S_CSR_MSTATUS: begin - csr_state <= S_CSR_MCAUSE; - end - S_CSR_MCAUSE: begin - csr_state <= S_CSR_IDLE; - end - S_CSR_MSTATUS_MRET: begin - csr_state <= S_CSR_IDLE; - end - default: begin - csr_state <= S_CSR_IDLE; - end - endcase - end - end - - // 发出中断信号前,先写几个CSR寄存器 - always @ (posedge clk or negedge rst_n) begin - if (!rst_n) begin - csr_we_o <= 1'b0; - csr_waddr_o <= 32'h0; - csr_wdata_o <= 32'h0; - end else begin - case (csr_state) - // 将mepc寄存器的值设为当前指令地址 - S_CSR_MEPC: begin - csr_we_o <= 1'b1; - csr_waddr_o <= {20'h0, `CSR_MEPC}; - csr_wdata_o <= inst_addr; - end - // 写中断产生的原因 - S_CSR_MCAUSE: begin - csr_we_o <= 1'b1; - csr_waddr_o <= {20'h0, `CSR_MCAUSE}; - csr_wdata_o <= cause; - end - // 关闭全局中断 - S_CSR_MSTATUS: begin - csr_we_o <= 1'b1; - csr_waddr_o <= {20'h0, `CSR_MSTATUS}; - csr_wdata_o <= {csr_mstatus_i[31:4], 1'b0, csr_mstatus_i[2:0]}; - end - // 中断返回 - S_CSR_MSTATUS_MRET: begin - csr_we_o <= 1'b1; - csr_waddr_o <= {20'h0, `CSR_MSTATUS}; - csr_wdata_o <= {csr_mstatus_i[31:4], csr_mstatus_i[7], csr_mstatus_i[2:0]}; - end - default: begin - csr_we_o <= 1'b0; - csr_waddr_o <= 32'h0; - csr_wdata_o <= 32'h0; - end - endcase - end - end - - reg in_int_context; - - always @ (posedge clk or negedge rst_n) begin - if (!rst_n) begin - in_int_context <= 1'b0; - end else begin - if (csr_state == S_CSR_MSTATUS_MRET) begin - in_int_context <= 1'b0; - end else if (csr_state != S_CSR_IDLE) begin - in_int_context <= 1'b1; - end - end - end - - assign int_assert_o = (csr_state == S_CSR_MCAUSE) | (csr_state == S_CSR_MSTATUS_MRET); - assign int_addr_o = (csr_state == S_CSR_MCAUSE)? csr_mtvec_i: - (csr_state == S_CSR_MSTATUS_MRET)? csr_mepc_i: - 32'h0; - -endmodule + /* + Copyright 2020 Blue Liang, liangkangnan@163.com + + 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. + */ + +`include "defines.sv" + +// core local interruptor module +// 核心中断管理、仲裁模块 +module clint( + + input wire clk, + input wire rst_n, + + // from core + input wire[`INT_WIDTH-1:0] int_flag_i, // 中断输入信号 + + // from exu + input wire inst_ecall_i, // ecall指令 + input wire inst_ebreak_i, // ebreak指令 + input wire inst_mret_i, // mret指令 + input wire[31:0] inst_addr_i, // 指令地址 + input wire jump_flag_i, + input wire mem_access_misaligned_i, + + // from csr_reg + input wire[31:0] csr_mtvec_i, // mtvec寄存器 + input wire[31:0] csr_mepc_i, // mepc寄存器 + input wire[31:0] csr_mstatus_i, // mstatus寄存器 + + // to csr_reg + output reg csr_we_o, // 写CSR寄存器标志 + output reg[31:0] csr_waddr_o, // 写CSR寄存器地址 + output reg[31:0] csr_wdata_o, // 写CSR寄存器数据 + + // to pipe_ctrl + output wire stall_flag_o, // 流水线暂停标志 + output wire[31:0] int_addr_o, // 中断入口地址 + output wire int_assert_o // 中断标志 + + ); + + // 中断状态定义 + localparam S_INT_IDLE = 4'b0001; + localparam S_INT_SYNC_ASSERT = 4'b0010; + localparam S_INT_ASYNC_ASSERT = 4'b0100; + localparam S_INT_MRET = 4'b1000; + + // 写CSR寄存器状态定义 + localparam S_CSR_IDLE = 5'b00001; + localparam S_CSR_MSTATUS = 5'b00010; + localparam S_CSR_MEPC = 5'b00100; + localparam S_CSR_MSTATUS_MRET = 5'b01000; + localparam S_CSR_MCAUSE = 5'b10000; + + reg[3:0] int_state; + reg[4:0] csr_state; + reg[31:0] inst_addr; + reg[31:0] cause; + + wire global_int_en = csr_mstatus_i[3]; + + assign stall_flag_o = ((int_state != S_INT_IDLE) | (csr_state != S_CSR_IDLE))? 1'b1: 1'b0; + + // 将跳转标志放在流水线上传递 + wire pc_state_jump_flag; + gen_rst_0_dff #(1) pc_state_dff(clk, rst_n, jump_flag_i, pc_state_jump_flag); + + wire if_state_jump_flag; + gen_rst_0_dff #(1) if_state_dff(clk, rst_n, pc_state_jump_flag, if_state_jump_flag); + + wire id_state_jump_flag; + gen_rst_0_dff #(1) id_state_dff(clk, rst_n, if_state_jump_flag, id_state_jump_flag); + + wire ex_state_jump_flag; + gen_rst_0_dff #(1) ex_state_dff(clk, rst_n, id_state_jump_flag, ex_state_jump_flag); + + wire[3:0] state_jump_flag = {pc_state_jump_flag, if_state_jump_flag, id_state_jump_flag, ex_state_jump_flag}; + // 如果流水线没有冲刷完成则不响应中断 + wire inst_addr_valid = (~(|state_jump_flag)) | ex_state_jump_flag; + + + // 中断仲裁逻辑 + always @ (*) begin + // 同步中断 + if (inst_ecall_i | inst_ebreak_i | mem_access_misaligned_i) begin + int_state = S_INT_SYNC_ASSERT; + // 异步中断 + end else if ((int_flag_i != `INT_NONE) & global_int_en & inst_addr_valid) begin + int_state = S_INT_ASYNC_ASSERT; + // 中断返回 + end else if (inst_mret_i) begin + int_state = S_INT_MRET; + // 无中断响应 + end else begin + int_state = S_INT_IDLE; + end + end + + // 写CSR寄存器状态切换 + always @ (posedge clk or negedge rst_n) begin + if (!rst_n) begin + csr_state <= S_CSR_IDLE; + cause <= 32'h0; + inst_addr <= 32'h0; + end else begin + case (csr_state) + S_CSR_IDLE: begin + case (int_state) + // 同步中断 + S_INT_SYNC_ASSERT: begin + csr_state <= S_CSR_MEPC; + // 在中断处理函数里会将中断返回地址加4 + inst_addr <= inst_addr_i; + cause <= inst_ebreak_i? 32'd3: + inst_ecall_i? 32'd11: + mem_access_misaligned_i? 32'd4: + 32'd10; + end + // 异步中断 + S_INT_ASYNC_ASSERT: begin + csr_state <= S_CSR_MEPC; + inst_addr <= inst_addr_i; + // 定时器中断 + cause <= 32'h80000004; + end + // 中断返回 + S_INT_MRET: begin + csr_state <= S_CSR_MSTATUS_MRET; + end + endcase + end + S_CSR_MEPC: begin + csr_state <= S_CSR_MSTATUS; + end + S_CSR_MSTATUS: begin + csr_state <= S_CSR_MCAUSE; + end + S_CSR_MCAUSE: begin + csr_state <= S_CSR_IDLE; + end + S_CSR_MSTATUS_MRET: begin + csr_state <= S_CSR_IDLE; + end + default: begin + csr_state <= S_CSR_IDLE; + end + endcase + end + end + + // 发出中断信号前,先写几个CSR寄存器 + always @ (posedge clk or negedge rst_n) begin + if (!rst_n) begin + csr_we_o <= 1'b0; + csr_waddr_o <= 32'h0; + csr_wdata_o <= 32'h0; + end else begin + case (csr_state) + // 将mepc寄存器的值设为当前指令地址 + S_CSR_MEPC: begin + csr_we_o <= 1'b1; + csr_waddr_o <= {20'h0, `CSR_MEPC}; + csr_wdata_o <= inst_addr; + end + // 写中断产生的原因 + S_CSR_MCAUSE: begin + csr_we_o <= 1'b1; + csr_waddr_o <= {20'h0, `CSR_MCAUSE}; + csr_wdata_o <= cause; + end + // 关闭全局中断 + S_CSR_MSTATUS: begin + csr_we_o <= 1'b1; + csr_waddr_o <= {20'h0, `CSR_MSTATUS}; + csr_wdata_o <= {csr_mstatus_i[31:4], 1'b0, csr_mstatus_i[2:0]}; + end + // 中断返回 + S_CSR_MSTATUS_MRET: begin + csr_we_o <= 1'b1; + csr_waddr_o <= {20'h0, `CSR_MSTATUS}; + csr_wdata_o <= {csr_mstatus_i[31:4], csr_mstatus_i[7], csr_mstatus_i[2:0]}; + end + default: begin + csr_we_o <= 1'b0; + csr_waddr_o <= 32'h0; + csr_wdata_o <= 32'h0; + end + endcase + end + end + + reg in_int_context; + + always @ (posedge clk or negedge rst_n) begin + if (!rst_n) begin + in_int_context <= 1'b0; + end else begin + if (csr_state == S_CSR_MSTATUS_MRET) begin + in_int_context <= 1'b0; + end else if (csr_state != S_CSR_IDLE) begin + in_int_context <= 1'b1; + end + end + end + + assign int_assert_o = (csr_state == S_CSR_MCAUSE) | (csr_state == S_CSR_MSTATUS_MRET); + assign int_addr_o = (csr_state == S_CSR_MCAUSE)? csr_mtvec_i: + (csr_state == S_CSR_MSTATUS_MRET)? csr_mepc_i: + 32'h0; + +endmodule diff --git a/rtl/core/csr_reg.sv b/rtl/core/csr_reg.sv index 8a19f46..45bf51a 100644 --- a/rtl/core/csr_reg.sv +++ b/rtl/core/csr_reg.sv @@ -1,140 +1,140 @@ - /* - Copyright 2020 Blue Liang, liangkangnan@163.com - - 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. - */ - -`include "defines.sv" - -// CSR瀵勫瓨鍣ㄦā鍧 -module csr_reg( - - input wire clk, - input wire rst_n, - - // exu - input wire exu_we_i, // exu妯″潡鍐欏瘎瀛樺櫒鏍囧織 - input wire[31:0] exu_waddr_i, // exu妯″潡鍐欏瘎瀛樺櫒鍦板潃 - input wire[31:0] exu_wdata_i, // exu妯″潡鍐欏瘎瀛樺櫒鏁版嵁 - input wire[31:0] exu_raddr_i, // exu妯″潡璇诲瘎瀛樺櫒鍦板潃 - output wire[31:0] exu_rdata_o, // exu妯″潡璇诲瘎瀛樺櫒鏁版嵁 - - // clint - input wire clint_we_i, // clint妯″潡鍐欏瘎瀛樺櫒鏍囧織 - input wire[31:0] clint_waddr_i, // clint妯″潡鍐欏瘎瀛樺櫒鍦板潃 - input wire[31:0] clint_wdata_i, // clint妯″潡鍐欏瘎瀛樺櫒鏁版嵁 - output wire[31:0] mtvec_o, // mtvec瀵勫瓨鍣ㄥ - output wire[31:0] mepc_o, // mepc瀵勫瓨鍣ㄥ - output wire[31:0] mstatus_o // mstatus瀵勫瓨鍣ㄥ - - ); - - reg[63:0] cycle; - reg[31:0] mtvec; - reg[31:0] mcause; - reg[31:0] mepc; - reg[31:0] mie; - reg[31:0] mstatus; - reg[31:0] mscratch; - - assign mtvec_o = mtvec; - assign mepc_o = mepc; - assign mstatus_o = mstatus; - - // cycle counter - // 澶嶄綅鎾ら攢鍚庡氨涓鐩磋鏁 - always @ (posedge clk or negedge rst_n) begin - if (!rst_n) begin - cycle <= {32'h0, 32'h0}; - end else begin - cycle <= cycle + 1'b1; - end - end - - wire we = exu_we_i | clint_we_i; - wire[31:0] waddr = exu_we_i? exu_waddr_i: clint_waddr_i; - wire[31:0] wdata = exu_we_i? exu_wdata_i: clint_wdata_i; - - // 鍐欏瘎瀛樺櫒 - always @ (posedge clk or negedge rst_n) begin - if (!rst_n) begin - mtvec <= 32'h0; - mcause <= 32'h0; - mepc <= 32'h0; - mie <= 32'h0; - mstatus <= 32'h0; - mscratch <= 32'h0; - end else begin - if (we) begin - case (waddr[11:0]) - `CSR_MTVEC: begin - mtvec <= wdata; - end - `CSR_MCAUSE: begin - mcause <= wdata; - end - `CSR_MEPC: begin - mepc <= wdata; - end - `CSR_MIE: begin - mie <= wdata; - end - `CSR_MSTATUS: begin - mstatus <= wdata; - end - `CSR_MSCRATCH: begin - mscratch <= wdata; - end - endcase - end - end - end - - reg[31:0] exu_rdata; - - // exu妯″潡璇籆SR瀵勫瓨鍣 - always @ (*) begin - case (exu_raddr_i[11:0]) - `CSR_CYCLE: begin - exu_rdata = cycle[31:0]; - end - `CSR_CYCLEH: begin - exu_rdata = cycle[63:32]; - end - `CSR_MTVEC: begin - exu_rdata = mtvec; - end - `CSR_MCAUSE: begin - exu_rdata = mcause; - end - `CSR_MEPC: begin - exu_rdata = mepc; - end - `CSR_MIE: begin - exu_rdata = mie; - end - `CSR_MSTATUS: begin - exu_rdata = mstatus; - end - `CSR_MSCRATCH: begin - exu_rdata = mscratch; - end - default: begin - exu_rdata = 32'h0; - end - endcase - end - - assign exu_rdata_o = exu_rdata; - -endmodule + /* + Copyright 2020 Blue Liang, liangkangnan@163.com + + 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. + */ + +`include "defines.sv" + +// CSR瀵勫瓨鍣ㄦā鍧 +module csr_reg( + + input wire clk, + input wire rst_n, + + // exu + input wire exu_we_i, // exu妯″潡鍐欏瘎瀛樺櫒鏍囧織 + input wire[31:0] exu_waddr_i, // exu妯″潡鍐欏瘎瀛樺櫒鍦板潃 + input wire[31:0] exu_wdata_i, // exu妯″潡鍐欏瘎瀛樺櫒鏁版嵁 + input wire[31:0] exu_raddr_i, // exu妯″潡璇诲瘎瀛樺櫒鍦板潃 + output wire[31:0] exu_rdata_o, // exu妯″潡璇诲瘎瀛樺櫒鏁版嵁 + + // clint + input wire clint_we_i, // clint妯″潡鍐欏瘎瀛樺櫒鏍囧織 + input wire[31:0] clint_waddr_i, // clint妯″潡鍐欏瘎瀛樺櫒鍦板潃 + input wire[31:0] clint_wdata_i, // clint妯″潡鍐欏瘎瀛樺櫒鏁版嵁 + output wire[31:0] mtvec_o, // mtvec瀵勫瓨鍣ㄥ + output wire[31:0] mepc_o, // mepc瀵勫瓨鍣ㄥ + output wire[31:0] mstatus_o // mstatus瀵勫瓨鍣ㄥ + + ); + + reg[63:0] cycle; + reg[31:0] mtvec; + reg[31:0] mcause; + reg[31:0] mepc; + reg[31:0] mie; + reg[31:0] mstatus; + reg[31:0] mscratch; + + assign mtvec_o = mtvec; + assign mepc_o = mepc; + assign mstatus_o = mstatus; + + // cycle counter + // 澶嶄綅鎾ら攢鍚庡氨涓鐩磋鏁 + always @ (posedge clk or negedge rst_n) begin + if (!rst_n) begin + cycle <= {32'h0, 32'h0}; + end else begin + cycle <= cycle + 1'b1; + end + end + + wire we = exu_we_i | clint_we_i; + wire[31:0] waddr = exu_we_i? exu_waddr_i: clint_waddr_i; + wire[31:0] wdata = exu_we_i? exu_wdata_i: clint_wdata_i; + + // 鍐欏瘎瀛樺櫒 + always @ (posedge clk or negedge rst_n) begin + if (!rst_n) begin + mtvec <= 32'h0; + mcause <= 32'h0; + mepc <= 32'h0; + mie <= 32'h0; + mstatus <= 32'h0; + mscratch <= 32'h0; + end else begin + if (we) begin + case (waddr[11:0]) + `CSR_MTVEC: begin + mtvec <= wdata; + end + `CSR_MCAUSE: begin + mcause <= wdata; + end + `CSR_MEPC: begin + mepc <= wdata; + end + `CSR_MIE: begin + mie <= wdata; + end + `CSR_MSTATUS: begin + mstatus <= wdata; + end + `CSR_MSCRATCH: begin + mscratch <= wdata; + end + endcase + end + end + end + + reg[31:0] exu_rdata; + + // exu妯″潡璇籆SR瀵勫瓨鍣 + always @ (*) begin + case (exu_raddr_i[11:0]) + `CSR_CYCLE: begin + exu_rdata = cycle[31:0]; + end + `CSR_CYCLEH: begin + exu_rdata = cycle[63:32]; + end + `CSR_MTVEC: begin + exu_rdata = mtvec; + end + `CSR_MCAUSE: begin + exu_rdata = mcause; + end + `CSR_MEPC: begin + exu_rdata = mepc; + end + `CSR_MIE: begin + exu_rdata = mie; + end + `CSR_MSTATUS: begin + exu_rdata = mstatus; + end + `CSR_MSCRATCH: begin + exu_rdata = mscratch; + end + default: begin + exu_rdata = 32'h0; + end + endcase + end + + assign exu_rdata_o = exu_rdata; + +endmodule diff --git a/rtl/core/defines.sv b/rtl/core/defines.sv index efbd4eb..f4b706c 100644 --- a/rtl/core/defines.sv +++ b/rtl/core/defines.sv @@ -1,122 +1,122 @@ - /* - Copyright 2019 Blue Liang, liangkangnan@163.com - - 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. - */ - -`define CPU_RESET_ADDR 32'h0 // CPU澶嶄綅鍦板潃 -`define CPU_CLOCK_HZ 50000000 // CPU鏃堕挓(50MHZ) -`define INST_MEM_START_ADDR 32'h0 // 鎸囦护瀛樺偍鍣ㄨ捣濮嬪湴鍧 -`define INST_MEM_END_ADDR 32'h0fffffff // 鎸囦护瀛樺偍鍣ㄧ粨鏉熷湴鍧 -`define JTAG_RESET_FF_LEVELS 5 - -`define ROM_DEPTH 8192 // 鎸囦护瀛樺偍鍣ㄦ繁搴︼紝鍗曚綅涓簑ord(4瀛楄妭) -`define RAM_DEPTH 4096 // 鏁版嵁瀛樺偍鍣ㄦ繁搴︼紝鍗曚綅涓簑ord(4瀛楄妭) - -`define INT_WIDTH 8 -`define INT_NONE 8'h0 - -`define STALL_WIDTH 4 -`define STALL_PC 2'd0 -`define STALL_IF 2'd1 -`define STALL_ID 2'd2 -`define STALL_EX 2'd3 - -`define INST_NOP 32'h00000013 -`define INST_MRET 32'h30200073 -`define INST_ECALL 32'h00000073 -`define INST_EBREAK 32'h00100073 - -// 鎸囦护璇戠爜淇℃伅 -`define DECINFO_GRP_BUS 2:0 -`define DECINFO_GRP_WIDTH 3 -`define DECINFO_GRP_ALU `DECINFO_GRP_WIDTH'd1 -`define DECINFO_GRP_BJP `DECINFO_GRP_WIDTH'd2 -`define DECINFO_GRP_MULDIV `DECINFO_GRP_WIDTH'd3 -`define DECINFO_GRP_CSR `DECINFO_GRP_WIDTH'd4 -`define DECINFO_GRP_MEM `DECINFO_GRP_WIDTH'd5 -`define DECINFO_GRP_SYS `DECINFO_GRP_WIDTH'd6 - -`define DECINFO_ALU_BUS_WIDTH (`DECINFO_GRP_WIDTH+14) -`define DECINFO_ALU_LUI (`DECINFO_GRP_WIDTH+0) -`define DECINFO_ALU_AUIPC (`DECINFO_GRP_WIDTH+1) -`define DECINFO_ALU_ADD (`DECINFO_GRP_WIDTH+2) -`define DECINFO_ALU_SUB (`DECINFO_GRP_WIDTH+3) -`define DECINFO_ALU_SLL (`DECINFO_GRP_WIDTH+4) -`define DECINFO_ALU_SLT (`DECINFO_GRP_WIDTH+5) -`define DECINFO_ALU_SLTU (`DECINFO_GRP_WIDTH+6) -`define DECINFO_ALU_XOR (`DECINFO_GRP_WIDTH+7) -`define DECINFO_ALU_SRL (`DECINFO_GRP_WIDTH+8) -`define DECINFO_ALU_SRA (`DECINFO_GRP_WIDTH+9) -`define DECINFO_ALU_OR (`DECINFO_GRP_WIDTH+10) -`define DECINFO_ALU_AND (`DECINFO_GRP_WIDTH+11) -`define DECINFO_ALU_OP2IMM (`DECINFO_GRP_WIDTH+12) -`define DECINFO_ALU_OP1PC (`DECINFO_GRP_WIDTH+13) - -`define DECINFO_BJP_BUS_WIDTH (`DECINFO_GRP_WIDTH+8) -`define DECINFO_BJP_JUMP (`DECINFO_GRP_WIDTH+0) -`define DECINFO_BJP_BEQ (`DECINFO_GRP_WIDTH+1) -`define DECINFO_BJP_BNE (`DECINFO_GRP_WIDTH+2) -`define DECINFO_BJP_BLT (`DECINFO_GRP_WIDTH+3) -`define DECINFO_BJP_BGE (`DECINFO_GRP_WIDTH+4) -`define DECINFO_BJP_BLTU (`DECINFO_GRP_WIDTH+5) -`define DECINFO_BJP_BGEU (`DECINFO_GRP_WIDTH+6) -`define DECINFO_BJP_OP1RS1 (`DECINFO_GRP_WIDTH+7) - -`define DECINFO_MULDIV_BUS_WIDTH (`DECINFO_GRP_WIDTH+8) -`define DECINFO_MULDIV_MUL (`DECINFO_GRP_WIDTH+0) -`define DECINFO_MULDIV_MULH (`DECINFO_GRP_WIDTH+1) -`define DECINFO_MULDIV_MULHSU (`DECINFO_GRP_WIDTH+2) -`define DECINFO_MULDIV_MULHU (`DECINFO_GRP_WIDTH+3) -`define DECINFO_MULDIV_DIV (`DECINFO_GRP_WIDTH+4) -`define DECINFO_MULDIV_DIVU (`DECINFO_GRP_WIDTH+5) -`define DECINFO_MULDIV_REM (`DECINFO_GRP_WIDTH+6) -`define DECINFO_MULDIV_REMU (`DECINFO_GRP_WIDTH+7) - -`define DECINFO_CSR_BUS_WIDTH (`DECINFO_GRP_WIDTH+16) -`define DECINFO_CSR_CSRRW (`DECINFO_GRP_WIDTH+0) -`define DECINFO_CSR_CSRRS (`DECINFO_GRP_WIDTH+1) -`define DECINFO_CSR_CSRRC (`DECINFO_GRP_WIDTH+2) -`define DECINFO_CSR_RS1IMM (`DECINFO_GRP_WIDTH+3) -`define DECINFO_CSR_CSRADDR `DECINFO_GRP_WIDTH+4+12-1:`DECINFO_GRP_WIDTH+4 - -`define DECINFO_MEM_BUS_WIDTH (`DECINFO_GRP_WIDTH+8) -`define DECINFO_MEM_LB (`DECINFO_GRP_WIDTH+0) -`define DECINFO_MEM_LH (`DECINFO_GRP_WIDTH+1) -`define DECINFO_MEM_LW (`DECINFO_GRP_WIDTH+2) -`define DECINFO_MEM_LBU (`DECINFO_GRP_WIDTH+3) -`define DECINFO_MEM_LHU (`DECINFO_GRP_WIDTH+4) -`define DECINFO_MEM_SB (`DECINFO_GRP_WIDTH+5) -`define DECINFO_MEM_SH (`DECINFO_GRP_WIDTH+6) -`define DECINFO_MEM_SW (`DECINFO_GRP_WIDTH+7) - -`define DECINFO_SYS_BUS_WIDTH (`DECINFO_GRP_WIDTH+5) -`define DECINFO_SYS_ECALL (`DECINFO_GRP_WIDTH+0) -`define DECINFO_SYS_EBREAK (`DECINFO_GRP_WIDTH+1) -`define DECINFO_SYS_NOP (`DECINFO_GRP_WIDTH+2) -`define DECINFO_SYS_MRET (`DECINFO_GRP_WIDTH+3) -`define DECINFO_SYS_FENCE (`DECINFO_GRP_WIDTH+4) - -// 鏈闀跨殑閭g粍 -`define DECINFO_WIDTH `DECINFO_CSR_BUS_WIDTH - -// CSR瀵勫瓨鍣ㄥ湴鍧 -`define CSR_CYCLE 12'hc00 -`define CSR_CYCLEH 12'hc80 -`define CSR_MTVEC 12'h305 -`define CSR_MCAUSE 12'h342 -`define CSR_MEPC 12'h341 -`define CSR_MIE 12'h304 -`define CSR_MSTATUS 12'h300 -`define CSR_MSCRATCH 12'h340 - + /* + Copyright 2019 Blue Liang, liangkangnan@163.com + + 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. + */ + +`define CPU_RESET_ADDR 32'h0 // CPU澶嶄綅鍦板潃 +`define CPU_CLOCK_HZ 50000000 // CPU鏃堕挓(50MHZ) +`define INST_MEM_START_ADDR 32'h0 // 鎸囦护瀛樺偍鍣ㄨ捣濮嬪湴鍧 +`define INST_MEM_END_ADDR 32'h0fffffff // 鎸囦护瀛樺偍鍣ㄧ粨鏉熷湴鍧 +`define JTAG_RESET_FF_LEVELS 5 + +`define ROM_DEPTH 8192 // 鎸囦护瀛樺偍鍣ㄦ繁搴︼紝鍗曚綅涓簑ord(4瀛楄妭) +`define RAM_DEPTH 4096 // 鏁版嵁瀛樺偍鍣ㄦ繁搴︼紝鍗曚綅涓簑ord(4瀛楄妭) + +`define INT_WIDTH 8 +`define INT_NONE 8'h0 + +`define STALL_WIDTH 4 +`define STALL_PC 2'd0 +`define STALL_IF 2'd1 +`define STALL_ID 2'd2 +`define STALL_EX 2'd3 + +`define INST_NOP 32'h00000013 +`define INST_MRET 32'h30200073 +`define INST_ECALL 32'h00000073 +`define INST_EBREAK 32'h00100073 + +// 鎸囦护璇戠爜淇℃伅 +`define DECINFO_GRP_BUS 2:0 +`define DECINFO_GRP_WIDTH 3 +`define DECINFO_GRP_ALU `DECINFO_GRP_WIDTH'd1 +`define DECINFO_GRP_BJP `DECINFO_GRP_WIDTH'd2 +`define DECINFO_GRP_MULDIV `DECINFO_GRP_WIDTH'd3 +`define DECINFO_GRP_CSR `DECINFO_GRP_WIDTH'd4 +`define DECINFO_GRP_MEM `DECINFO_GRP_WIDTH'd5 +`define DECINFO_GRP_SYS `DECINFO_GRP_WIDTH'd6 + +`define DECINFO_ALU_BUS_WIDTH (`DECINFO_GRP_WIDTH+14) +`define DECINFO_ALU_LUI (`DECINFO_GRP_WIDTH+0) +`define DECINFO_ALU_AUIPC (`DECINFO_GRP_WIDTH+1) +`define DECINFO_ALU_ADD (`DECINFO_GRP_WIDTH+2) +`define DECINFO_ALU_SUB (`DECINFO_GRP_WIDTH+3) +`define DECINFO_ALU_SLL (`DECINFO_GRP_WIDTH+4) +`define DECINFO_ALU_SLT (`DECINFO_GRP_WIDTH+5) +`define DECINFO_ALU_SLTU (`DECINFO_GRP_WIDTH+6) +`define DECINFO_ALU_XOR (`DECINFO_GRP_WIDTH+7) +`define DECINFO_ALU_SRL (`DECINFO_GRP_WIDTH+8) +`define DECINFO_ALU_SRA (`DECINFO_GRP_WIDTH+9) +`define DECINFO_ALU_OR (`DECINFO_GRP_WIDTH+10) +`define DECINFO_ALU_AND (`DECINFO_GRP_WIDTH+11) +`define DECINFO_ALU_OP2IMM (`DECINFO_GRP_WIDTH+12) +`define DECINFO_ALU_OP1PC (`DECINFO_GRP_WIDTH+13) + +`define DECINFO_BJP_BUS_WIDTH (`DECINFO_GRP_WIDTH+8) +`define DECINFO_BJP_JUMP (`DECINFO_GRP_WIDTH+0) +`define DECINFO_BJP_BEQ (`DECINFO_GRP_WIDTH+1) +`define DECINFO_BJP_BNE (`DECINFO_GRP_WIDTH+2) +`define DECINFO_BJP_BLT (`DECINFO_GRP_WIDTH+3) +`define DECINFO_BJP_BGE (`DECINFO_GRP_WIDTH+4) +`define DECINFO_BJP_BLTU (`DECINFO_GRP_WIDTH+5) +`define DECINFO_BJP_BGEU (`DECINFO_GRP_WIDTH+6) +`define DECINFO_BJP_OP1RS1 (`DECINFO_GRP_WIDTH+7) + +`define DECINFO_MULDIV_BUS_WIDTH (`DECINFO_GRP_WIDTH+8) +`define DECINFO_MULDIV_MUL (`DECINFO_GRP_WIDTH+0) +`define DECINFO_MULDIV_MULH (`DECINFO_GRP_WIDTH+1) +`define DECINFO_MULDIV_MULHSU (`DECINFO_GRP_WIDTH+2) +`define DECINFO_MULDIV_MULHU (`DECINFO_GRP_WIDTH+3) +`define DECINFO_MULDIV_DIV (`DECINFO_GRP_WIDTH+4) +`define DECINFO_MULDIV_DIVU (`DECINFO_GRP_WIDTH+5) +`define DECINFO_MULDIV_REM (`DECINFO_GRP_WIDTH+6) +`define DECINFO_MULDIV_REMU (`DECINFO_GRP_WIDTH+7) + +`define DECINFO_CSR_BUS_WIDTH (`DECINFO_GRP_WIDTH+16) +`define DECINFO_CSR_CSRRW (`DECINFO_GRP_WIDTH+0) +`define DECINFO_CSR_CSRRS (`DECINFO_GRP_WIDTH+1) +`define DECINFO_CSR_CSRRC (`DECINFO_GRP_WIDTH+2) +`define DECINFO_CSR_RS1IMM (`DECINFO_GRP_WIDTH+3) +`define DECINFO_CSR_CSRADDR `DECINFO_GRP_WIDTH+4+12-1:`DECINFO_GRP_WIDTH+4 + +`define DECINFO_MEM_BUS_WIDTH (`DECINFO_GRP_WIDTH+8) +`define DECINFO_MEM_LB (`DECINFO_GRP_WIDTH+0) +`define DECINFO_MEM_LH (`DECINFO_GRP_WIDTH+1) +`define DECINFO_MEM_LW (`DECINFO_GRP_WIDTH+2) +`define DECINFO_MEM_LBU (`DECINFO_GRP_WIDTH+3) +`define DECINFO_MEM_LHU (`DECINFO_GRP_WIDTH+4) +`define DECINFO_MEM_SB (`DECINFO_GRP_WIDTH+5) +`define DECINFO_MEM_SH (`DECINFO_GRP_WIDTH+6) +`define DECINFO_MEM_SW (`DECINFO_GRP_WIDTH+7) + +`define DECINFO_SYS_BUS_WIDTH (`DECINFO_GRP_WIDTH+5) +`define DECINFO_SYS_ECALL (`DECINFO_GRP_WIDTH+0) +`define DECINFO_SYS_EBREAK (`DECINFO_GRP_WIDTH+1) +`define DECINFO_SYS_NOP (`DECINFO_GRP_WIDTH+2) +`define DECINFO_SYS_MRET (`DECINFO_GRP_WIDTH+3) +`define DECINFO_SYS_FENCE (`DECINFO_GRP_WIDTH+4) + +// 鏈闀跨殑閭g粍 +`define DECINFO_WIDTH `DECINFO_CSR_BUS_WIDTH + +// CSR瀵勫瓨鍣ㄥ湴鍧 +`define CSR_CYCLE 12'hc00 +`define CSR_CYCLEH 12'hc80 +`define CSR_MTVEC 12'h305 +`define CSR_MCAUSE 12'h342 +`define CSR_MEPC 12'h341 +`define CSR_MIE 12'h304 +`define CSR_MSTATUS 12'h300 +`define CSR_MSCRATCH 12'h340 + diff --git a/rtl/core/divider.sv b/rtl/core/divider.sv index 253d7b8..760cd32 100644 --- a/rtl/core/divider.sv +++ b/rtl/core/divider.sv @@ -1,196 +1,196 @@ - /* - Copyright 2019 Blue Liang, liangkangnan@163.com - - 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. - */ - -`include "defines.sv" - -// 闄ゆ硶妯″潡 -// 璇曞晢娉曞疄鐜32浣嶆暣鏁伴櫎娉 -// 姣忔闄ゆ硶杩愮畻鑷冲皯闇瑕33涓椂閽熷懆鏈熸墠鑳藉畬鎴 -module divider( - - input wire clk, - input wire rst_n, - - input wire[31:0] dividend_i, // 琚櫎鏁 - input wire[31:0] divisor_i, // 闄ゆ暟 - input wire start_i, // 寮濮嬩俊鍙凤紝杩愮畻鏈熼棿杩欎釜淇″彿闇瑕佷竴鐩翠繚鎸佹湁鏁 - input wire[3:0] op_i, // 鍏蜂綋鏄摢涓鏉℃寚浠 - - output reg[31:0] result_o, // 闄ゆ硶缁撴灉锛岄珮32浣嶆槸浣欐暟锛屼綆32浣嶆槸鍟 - output reg ready_o // 杩愮畻缁撴潫淇″彿 - - ); - - // 鐘舵佸畾涔 - localparam STATE_IDLE = 4'b0001; - localparam STATE_START = 4'b0010; - localparam STATE_CALC = 4'b0100; - localparam STATE_END = 4'b1000; - - reg[31:0] dividend_r; - reg[31:0] divisor_r; - reg[3:0] op_r; - reg[3:0] state; - reg[31:0] count; - reg[31:0] div_result; - reg[31:0] div_remain; - reg[31:0] minuend; - reg invert_result; - - wire op_div = op_r[3]; - wire op_divu = op_r[2]; - wire op_rem = op_r[1]; - wire op_remu = op_r[0]; - - wire[31:0] dividend_invert = (-dividend_r); - wire[31:0] divisor_invert = (-divisor_r); - wire minuend_ge_divisor = minuend >= divisor_r; - wire[31:0] minuend_sub_res = minuend - divisor_r; - wire[31:0] div_result_tmp = minuend_ge_divisor? ({div_result[30:0], 1'b1}): ({div_result[30:0], 1'b0}); - wire[31:0] minuend_tmp = minuend_ge_divisor? minuend_sub_res[30:0]: minuend[30:0]; - - // 鐘舵佹満瀹炵幇 - always @ (posedge clk or negedge rst_n) begin - if (!rst_n) begin - state <= STATE_IDLE; - ready_o <= 1'b0; - result_o <= 32'h0; - div_result <= 32'h0; - div_remain <= 32'h0; - op_r <= 3'h0; - dividend_r <= 32'h0; - divisor_r <= 32'h0; - minuend <= 32'h0; - invert_result <= 1'b0; - count <= 32'h0; - end else begin - case (state) - STATE_IDLE: begin - if (start_i) begin - op_r <= op_i; - dividend_r <= dividend_i; - divisor_r <= divisor_i; - state <= STATE_START; - end else begin - op_r <= 3'h0; - dividend_r <= 32'h0; - divisor_r <= 32'h0; - ready_o <= 1'b0; - result_o <= 32'h0; - end - end - - STATE_START: begin - if (start_i) begin - // 闄ゆ暟涓0 - if (divisor_r == 32'h0) begin - if (op_div | op_divu) begin - result_o <= 32'hffffffff; - end else begin - result_o <= dividend_r; - end - ready_o <= 1'b1; - state <= STATE_IDLE; - // 闄ゆ暟涓嶄负0 - end else begin - count <= 32'h40000000; - state <= STATE_CALC; - div_result <= 32'h0; - div_remain <= 32'h0; - - // DIV鍜孯EM杩欎袱鏉℃寚浠ゆ槸鏈夌鍙锋暟杩愮畻鎸囦护 - if (op_div | op_rem) begin - // 琚櫎鏁版眰琛ョ爜 - if (dividend_r[31] == 1'b1) begin - dividend_r <= dividend_invert; - minuend <= dividend_invert[31]; - end else begin - minuend <= dividend_r[31]; - end - // 闄ゆ暟姹傝ˉ鐮 - if (divisor_r[31] == 1'b1) begin - divisor_r <= divisor_invert; - end - end else begin - minuend <= dividend_r[31]; - end - - // 杩愮畻缁撴潫鍚庢槸鍚﹁瀵圭粨鏋滃彇琛ョ爜 - if ((op_div && (dividend_r[31] ^ divisor_r[31] == 1'b1)) - || (op_rem && (dividend_r[31] == 1'b1))) begin - invert_result <= 1'b1; - end else begin - invert_result <= 1'b0; - end - end - end else begin - state <= STATE_IDLE; - result_o <= 32'h0; - ready_o <= 1'b0; - end - end - - STATE_CALC: begin - if (start_i) begin - dividend_r <= {dividend_r[30:0], 1'b0}; - div_result <= div_result_tmp; - count <= {1'b0, count[31:1]}; - if (|count) begin - minuend <= {minuend_tmp[30:0], dividend_r[30]}; - end else begin - state <= STATE_END; - if (minuend_ge_divisor) begin - div_remain <= minuend_sub_res; - end else begin - div_remain <= minuend; - end - end - end else begin - state <= STATE_IDLE; - result_o <= 32'h0; - ready_o <= 1'b0; - end - end - - STATE_END: begin - if (start_i) begin - ready_o <= 1'b1; - state <= STATE_IDLE; - if (op_div | op_divu) begin - if (invert_result) begin - result_o <= (-div_result); - end else begin - result_o <= div_result; - end - end else begin - if (invert_result) begin - result_o <= (-div_remain); - end else begin - result_o <= div_remain; - end - end - end else begin - state <= STATE_IDLE; - result_o <= 32'h0; - ready_o <= 1'b0; - end - end - - endcase - end - end - -endmodule + /* + Copyright 2019 Blue Liang, liangkangnan@163.com + + 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. + */ + +`include "defines.sv" + +// 闄ゆ硶妯″潡 +// 璇曞晢娉曞疄鐜32浣嶆暣鏁伴櫎娉 +// 姣忔闄ゆ硶杩愮畻鑷冲皯闇瑕33涓椂閽熷懆鏈熸墠鑳藉畬鎴 +module divider( + + input wire clk, + input wire rst_n, + + input wire[31:0] dividend_i, // 琚櫎鏁 + input wire[31:0] divisor_i, // 闄ゆ暟 + input wire start_i, // 寮濮嬩俊鍙凤紝杩愮畻鏈熼棿杩欎釜淇″彿闇瑕佷竴鐩翠繚鎸佹湁鏁 + input wire[3:0] op_i, // 鍏蜂綋鏄摢涓鏉℃寚浠 + + output reg[31:0] result_o, // 闄ゆ硶缁撴灉锛岄珮32浣嶆槸浣欐暟锛屼綆32浣嶆槸鍟 + output reg ready_o // 杩愮畻缁撴潫淇″彿 + + ); + + // 鐘舵佸畾涔 + localparam STATE_IDLE = 4'b0001; + localparam STATE_START = 4'b0010; + localparam STATE_CALC = 4'b0100; + localparam STATE_END = 4'b1000; + + reg[31:0] dividend_r; + reg[31:0] divisor_r; + reg[3:0] op_r; + reg[3:0] state; + reg[31:0] count; + reg[31:0] div_result; + reg[31:0] div_remain; + reg[31:0] minuend; + reg invert_result; + + wire op_div = op_r[3]; + wire op_divu = op_r[2]; + wire op_rem = op_r[1]; + wire op_remu = op_r[0]; + + wire[31:0] dividend_invert = (-dividend_r); + wire[31:0] divisor_invert = (-divisor_r); + wire minuend_ge_divisor = minuend >= divisor_r; + wire[31:0] minuend_sub_res = minuend - divisor_r; + wire[31:0] div_result_tmp = minuend_ge_divisor? ({div_result[30:0], 1'b1}): ({div_result[30:0], 1'b0}); + wire[31:0] minuend_tmp = minuend_ge_divisor? minuend_sub_res[30:0]: minuend[30:0]; + + // 鐘舵佹満瀹炵幇 + always @ (posedge clk or negedge rst_n) begin + if (!rst_n) begin + state <= STATE_IDLE; + ready_o <= 1'b0; + result_o <= 32'h0; + div_result <= 32'h0; + div_remain <= 32'h0; + op_r <= 3'h0; + dividend_r <= 32'h0; + divisor_r <= 32'h0; + minuend <= 32'h0; + invert_result <= 1'b0; + count <= 32'h0; + end else begin + case (state) + STATE_IDLE: begin + if (start_i) begin + op_r <= op_i; + dividend_r <= dividend_i; + divisor_r <= divisor_i; + state <= STATE_START; + end else begin + op_r <= 3'h0; + dividend_r <= 32'h0; + divisor_r <= 32'h0; + ready_o <= 1'b0; + result_o <= 32'h0; + end + end + + STATE_START: begin + if (start_i) begin + // 闄ゆ暟涓0 + if (divisor_r == 32'h0) begin + if (op_div | op_divu) begin + result_o <= 32'hffffffff; + end else begin + result_o <= dividend_r; + end + ready_o <= 1'b1; + state <= STATE_IDLE; + // 闄ゆ暟涓嶄负0 + end else begin + count <= 32'h40000000; + state <= STATE_CALC; + div_result <= 32'h0; + div_remain <= 32'h0; + + // DIV鍜孯EM杩欎袱鏉℃寚浠ゆ槸鏈夌鍙锋暟杩愮畻鎸囦护 + if (op_div | op_rem) begin + // 琚櫎鏁版眰琛ョ爜 + if (dividend_r[31] == 1'b1) begin + dividend_r <= dividend_invert; + minuend <= dividend_invert[31]; + end else begin + minuend <= dividend_r[31]; + end + // 闄ゆ暟姹傝ˉ鐮 + if (divisor_r[31] == 1'b1) begin + divisor_r <= divisor_invert; + end + end else begin + minuend <= dividend_r[31]; + end + + // 杩愮畻缁撴潫鍚庢槸鍚﹁瀵圭粨鏋滃彇琛ョ爜 + if ((op_div && (dividend_r[31] ^ divisor_r[31] == 1'b1)) + || (op_rem && (dividend_r[31] == 1'b1))) begin + invert_result <= 1'b1; + end else begin + invert_result <= 1'b0; + end + end + end else begin + state <= STATE_IDLE; + result_o <= 32'h0; + ready_o <= 1'b0; + end + end + + STATE_CALC: begin + if (start_i) begin + dividend_r <= {dividend_r[30:0], 1'b0}; + div_result <= div_result_tmp; + count <= {1'b0, count[31:1]}; + if (|count) begin + minuend <= {minuend_tmp[30:0], dividend_r[30]}; + end else begin + state <= STATE_END; + if (minuend_ge_divisor) begin + div_remain <= minuend_sub_res; + end else begin + div_remain <= minuend; + end + end + end else begin + state <= STATE_IDLE; + result_o <= 32'h0; + ready_o <= 1'b0; + end + end + + STATE_END: begin + if (start_i) begin + ready_o <= 1'b1; + state <= STATE_IDLE; + if (op_div | op_divu) begin + if (invert_result) begin + result_o <= (-div_result); + end else begin + result_o <= div_result; + end + end else begin + if (invert_result) begin + result_o <= (-div_remain); + end else begin + result_o <= div_remain; + end + end + end else begin + state <= STATE_IDLE; + result_o <= 32'h0; + ready_o <= 1'b0; + end + end + + endcase + end + end + +endmodule diff --git a/rtl/core/exu.sv b/rtl/core/exu.sv index 65fca99..bec4c32 100644 --- a/rtl/core/exu.sv +++ b/rtl/core/exu.sv @@ -1,378 +1,385 @@ - /* - Copyright 2019 Blue Liang, liangkangnan@163.com - - 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. - */ - -`include "defines.sv" - -// 鎵ц妯″潡 -// 绾粍鍚堥昏緫鐢佃矾 -module exu( - - input wire clk, - input wire rst_n, - - // clint - input wire int_assert_i, // 涓柇鍙戠敓鏍囧織 - input wire[31:0] int_addr_i, // 涓柇璺宠浆鍦板潃 - input wire int_stall_i, // 鏆傚仠鏍囧織 - output wire inst_ecall_o, // ecall鎸囦护 - output wire inst_ebreak_o, // ebreak鎸囦护 - output wire inst_mret_o, // mret鎸囦护 - - // mem - input wire[31:0] mem_rdata_i, // 鍐呭瓨杈撳叆鏁版嵁 - input wire mem_req_ready_i, - input wire mem_rsp_valid_i, - output wire[31:0] mem_wdata_o, // 鍐欏唴瀛樻暟鎹 - output wire[31:0] mem_addr_o, // 璇汇佸啓鍐呭瓨鍦板潃 - output wire mem_we_o, // 鏄惁瑕佸啓鍐呭瓨 - output wire[3:0] mem_sel_o, // 瀛楄妭浣 - output wire mem_req_valid_o, - output wire mem_rsp_ready_o, - output wire mem_access_misaligned_o, - - // gpr_reg - output wire[31:0] reg_wdata_o, // 鍐欏瘎瀛樺櫒鏁版嵁 - output wire reg_we_o, // 鏄惁瑕佸啓閫氱敤瀵勫瓨鍣 - output wire[4:0] reg_waddr_o, // 鍐欓氱敤瀵勫瓨鍣ㄥ湴鍧 - - // csr_reg - input wire[31:0] csr_rdata_i, - output wire[31:0] csr_raddr_o, // 璇籆SR瀵勫瓨鍣ㄥ湴鍧 - output wire[31:0] csr_wdata_o, // 鍐機SR瀵勫瓨鍣ㄦ暟鎹 - output wire csr_we_o, // 鏄惁瑕佸啓CSR瀵勫瓨鍣 - output wire[31:0] csr_waddr_o, // 鍐機SR瀵勫瓨鍣ㄥ湴鍧 - - // to pipe_ctrl - output wire hold_flag_o, // 鏄惁鏆傚仠鏍囧織 - output wire jump_flag_o, // 鏄惁璺宠浆鏍囧織 - output wire[31:0] jump_addr_o, // 璺宠浆鐩殑鍦板潃 - - // from idu_exu - input wire[`DECINFO_WIDTH-1:0] dec_info_bus_i, - input wire[31:0] dec_imm_i, - input wire[31:0] dec_pc_i, - input wire[31:0] next_pc_i, - input wire[4:0] rd_waddr_i, - input wire[31:0] reg1_rdata_i, // 閫氱敤瀵勫瓨鍣1杈撳叆鏁版嵁 - input wire[31:0] reg2_rdata_i, // 閫氱敤瀵勫瓨鍣2杈撳叆鏁版嵁 - input wire rd_we_i - - ); - - // dispatch to ALU - wire[31:0] alu_op1_o; - wire[31:0] alu_op2_o; - wire req_alu_o; - wire alu_op_lui_o; - wire alu_op_auipc_o; - wire alu_op_add_o; - wire alu_op_sub_o; - wire alu_op_sll_o; - wire alu_op_slt_o; - wire alu_op_sltu_o; - wire alu_op_xor_o; - wire alu_op_srl_o; - wire alu_op_sra_o; - wire alu_op_or_o; - wire alu_op_and_o; - // dispatch to BJP - wire[31:0] bjp_op1_o; - wire[31:0] bjp_op2_o; - wire[31:0] bjp_jump_op1_o; - wire[31:0] bjp_jump_op2_o; - wire req_bjp_o; - wire bjp_op_jump_o; - wire bjp_op_beq_o; - wire bjp_op_bne_o; - wire bjp_op_blt_o; - wire bjp_op_bltu_o; - wire bjp_op_bge_o; - wire bjp_op_bgeu_o; - // dispatch to MULDIV - wire req_muldiv_o; - wire[31:0] muldiv_op1_o; - wire[31:0] muldiv_op2_o; - wire muldiv_op_mul_o; - wire muldiv_op_mulh_o; - wire muldiv_op_mulhsu_o; - wire muldiv_op_mulhu_o; - wire muldiv_op_div_o; - wire muldiv_op_divu_o; - wire muldiv_op_rem_o; - wire muldiv_op_remu_o; - // dispatch to CSR - wire req_csr_o; - wire[31:0] csr_op1_o; - wire[31:0] csr_addr_o; - wire csr_csrrw_o; - wire csr_csrrs_o; - wire csr_csrrc_o; - // dispatch to MEM - wire req_mem_o; - wire[31:0] mem_op1_o; - wire[31:0] mem_op2_o; - wire[31:0] mem_rs2_data_o; - wire mem_op_lb_o; - wire mem_op_lh_o; - wire mem_op_lw_o; - wire mem_op_lbu_o; - wire mem_op_lhu_o; - wire mem_op_sb_o; - wire mem_op_sh_o; - wire mem_op_sw_o; - // dispatch to SYS - wire sys_op_nop_o; - wire sys_op_mret_o; - wire sys_op_ecall_o; - wire sys_op_ebreak_o; - wire sys_op_fence_o; - - exu_dispatch u_exu_dispatch( - // input - .clk(clk), - .rst_n(rst_n), - .dec_info_bus_i(dec_info_bus_i), - .dec_imm_i(dec_imm_i), - .dec_pc_i(dec_pc_i), - .rs1_rdata_i(reg1_rdata_i), - .rs2_rdata_i(reg2_rdata_i), - // dispatch to ALU - .alu_op1_o(alu_op1_o), - .alu_op2_o(alu_op2_o), - .req_alu_o(req_alu_o), - .alu_op_lui_o(alu_op_lui_o), - .alu_op_auipc_o(alu_op_auipc_o), - .alu_op_add_o(alu_op_add_o), - .alu_op_sub_o(alu_op_sub_o), - .alu_op_sll_o(alu_op_sll_o), - .alu_op_slt_o(alu_op_slt_o), - .alu_op_sltu_o(alu_op_sltu_o), - .alu_op_xor_o(alu_op_xor_o), - .alu_op_srl_o(alu_op_srl_o), - .alu_op_sra_o(alu_op_sra_o), - .alu_op_or_o(alu_op_or_o), - .alu_op_and_o(alu_op_and_o), - // dispatch to BJP - .bjp_op1_o(bjp_op1_o), - .bjp_op2_o(bjp_op2_o), - .bjp_jump_op1_o(bjp_jump_op1_o), - .bjp_jump_op2_o(bjp_jump_op2_o), - .req_bjp_o(req_bjp_o), - .bjp_op_jump_o(bjp_op_jump_o), - .bjp_op_beq_o(bjp_op_beq_o), - .bjp_op_bne_o(bjp_op_bne_o), - .bjp_op_blt_o(bjp_op_blt_o), - .bjp_op_bltu_o(bjp_op_bltu_o), - .bjp_op_bge_o(bjp_op_bge_o), - .bjp_op_bgeu_o(bjp_op_bgeu_o), - // dispatch to MULDIV - .req_muldiv_o(req_muldiv_o), - .muldiv_op1_o(muldiv_op1_o), - .muldiv_op2_o(muldiv_op2_o), - .muldiv_op_mul_o(muldiv_op_mul_o), - .muldiv_op_mulh_o(muldiv_op_mulh_o), - .muldiv_op_mulhsu_o(muldiv_op_mulhsu_o), - .muldiv_op_mulhu_o(muldiv_op_mulhu_o), - .muldiv_op_div_o(muldiv_op_div_o), - .muldiv_op_divu_o(muldiv_op_divu_o), - .muldiv_op_rem_o(muldiv_op_rem_o), - .muldiv_op_remu_o(muldiv_op_remu_o), - // dispatch to CSR - .req_csr_o(req_csr_o), - .csr_op1_o(csr_op1_o), - .csr_addr_o(csr_addr_o), - .csr_csrrw_o(csr_csrrw_o), - .csr_csrrs_o(csr_csrrs_o), - .csr_csrrc_o(csr_csrrc_o), - // dispatch to MEM - .req_mem_o(req_mem_o), - .mem_op1_o(mem_op1_o), - .mem_op2_o(mem_op2_o), - .mem_rs2_data_o(mem_rs2_data_o), - .mem_op_lb_o(mem_op_lb_o), - .mem_op_lh_o(mem_op_lh_o), - .mem_op_lw_o(mem_op_lw_o), - .mem_op_lbu_o(mem_op_lbu_o), - .mem_op_lhu_o(mem_op_lhu_o), - .mem_op_sb_o(mem_op_sb_o), - .mem_op_sh_o(mem_op_sh_o), - .mem_op_sw_o(mem_op_sw_o), - // dispatch to SYS - .sys_op_nop_o(sys_op_nop_o), - .sys_op_mret_o(sys_op_mret_o), - .sys_op_ecall_o(sys_op_ecall_o), - .sys_op_ebreak_o(sys_op_ebreak_o), - .sys_op_fence_o(sys_op_fence_o) - ); - - assign inst_ecall_o = sys_op_ecall_o; - assign inst_ebreak_o = sys_op_ebreak_o; - assign inst_mret_o = sys_op_mret_o; - - wire[31:0] alu_res_o; - wire[31:0] bjp_res_o; - wire bjp_cmp_res_o; - wire[31:0] csr_op1 = csr_csrrc_o? (~csr_op1_o): csr_op1_o; - wire[31:0] csr_op2 = csr_csrrw_o? (32'h0): csr_rdata_i; - - exu_alu_datapath u_exu_alu_datapath( - .clk(clk), - .rst_n(rst_n), - // ALU - .req_alu_i(req_alu_o), - .alu_op1_i(alu_op1_o), - .alu_op2_i(alu_op2_o), - .alu_op_add_i(alu_op_add_o | alu_op_lui_o | alu_op_auipc_o), - .alu_op_sub_i(alu_op_sub_o), - .alu_op_sll_i(alu_op_sll_o), - .alu_op_slt_i(alu_op_slt_o), - .alu_op_sltu_i(alu_op_sltu_o), - .alu_op_xor_i(alu_op_xor_o), - .alu_op_srl_i(alu_op_srl_o), - .alu_op_sra_i(alu_op_sra_o), - .alu_op_or_i(alu_op_or_o), - .alu_op_and_i(alu_op_and_o), - // BJP - .req_bjp_i(req_bjp_o), - .bjp_op1_i(bjp_op1_o), - .bjp_op2_i(bjp_op2_o), - .bjp_op_beq_i(bjp_op_beq_o), - .bjp_op_bne_i(bjp_op_bne_o), - .bjp_op_blt_i(bjp_op_blt_o), - .bjp_op_bltu_i(bjp_op_bltu_o), - .bjp_op_bge_i(bjp_op_bge_o), - .bjp_op_bgeu_i(bjp_op_bgeu_o), - .bjp_op_jump_i(bjp_op_jump_o), - .bjp_jump_op1_i(bjp_jump_op1_o), - .bjp_jump_op2_i(bjp_jump_op2_o), - // MEM - .req_mem_i(req_mem_o), - .mem_op1_i(mem_op1_o), - .mem_op2_i(mem_op2_o), - // CSR - .req_csr_i(req_csr_o), - .csr_op1_i(csr_op1), - .csr_op2_i(csr_op2), - .csr_csrrw_i(csr_csrrw_o), - .csr_csrrs_i(csr_csrrs_o), - .csr_csrrc_i(csr_csrrc_o), - - .alu_res_o(alu_res_o), - .bjp_res_o(bjp_res_o), - .bjp_cmp_res_o(bjp_cmp_res_o) - ); - - wire mem_reg_we_o; - wire mem_mem_we_o; - wire[31:0] mem_wdata; - wire mem_stall_o; - - exu_mem u_exu_mem( - .clk(clk), - .rst_n(rst_n), - .req_mem_i(req_mem_o), - .mem_addr_i(alu_res_o), - .mem_rs2_data_i(mem_rs2_data_o), - .mem_req_ready_i(mem_req_ready_i), - .mem_rsp_valid_i(mem_rsp_valid_i), - .mem_rdata_i(mem_rdata_i), - .mem_op_lb_i(mem_op_lb_o), - .mem_op_lh_i(mem_op_lh_o), - .mem_op_lw_i(mem_op_lw_o), - .mem_op_lbu_i(mem_op_lbu_o), - .mem_op_lhu_i(mem_op_lhu_o), - .mem_op_sb_i(mem_op_sb_o), - .mem_op_sh_i(mem_op_sh_o), - .mem_op_sw_i(mem_op_sw_o), - .mem_access_misaligned_o(mem_access_misaligned_o), - .mem_stall_o(mem_stall_o), - .mem_addr_o(mem_addr_o), - .mem_wdata_o(mem_wdata), - .mem_reg_we_o(mem_reg_we_o), - .mem_mem_we_o(mem_mem_we_o), - .mem_sel_o(mem_sel_o), - .mem_req_valid_o(mem_req_valid_o), - .mem_rsp_ready_o(mem_rsp_ready_o) - ); - - wire[31:0] muldiv_reg_wdata_o; - wire muldiv_reg_we_o; - wire muldiv_stall_o; - - exu_muldiv u_exu_muldiv( - .clk(clk), - .rst_n(rst_n), - .muldiv_op1_i(muldiv_op1_o), - .muldiv_op2_i(muldiv_op2_o), - .muldiv_op_mul_i(muldiv_op_mul_o), - .muldiv_op_mulh_i(muldiv_op_mulh_o), - .muldiv_op_mulhsu_i(muldiv_op_mulhsu_o), - .muldiv_op_mulhu_i(muldiv_op_mulhu_o), - .muldiv_op_div_i(muldiv_op_div_o), - .muldiv_op_divu_i(muldiv_op_divu_o), - .muldiv_op_rem_i(muldiv_op_rem_o), - .muldiv_op_remu_i(muldiv_op_remu_o), - .muldiv_reg_wdata_o(muldiv_reg_wdata_o), - .muldiv_reg_we_o(muldiv_reg_we_o), - .muldiv_stall_o(muldiv_stall_o) - ); - - wire commit_reg_we_o; - - exu_commit u_exu_commit( - .clk(clk), - .rst_n(rst_n), - .req_muldiv_i(req_muldiv_o), - .muldiv_reg_we_i(muldiv_reg_we_o), - .muldiv_reg_waddr_i(rd_waddr_i), - .muldiv_reg_wdata_i(muldiv_reg_wdata_o), - .req_mem_i(req_mem_o), - .mem_reg_we_i(mem_reg_we_o), - .mem_reg_waddr_i(rd_waddr_i), - .mem_reg_wdata_i(mem_wdata), - .req_csr_i(req_csr_o), - .csr_reg_we_i(req_csr_o), - .csr_reg_waddr_i(rd_waddr_i), - .csr_reg_wdata_i(csr_rdata_i), - .req_bjp_i(req_bjp_o), - .bjp_reg_we_i(bjp_op_jump_o), - .bjp_reg_wdata_i(next_pc_i), - .bjp_reg_waddr_i(rd_waddr_i), - .rd_we_i(rd_we_i), - .rd_waddr_i(rd_waddr_i), - .alu_reg_wdata_i(alu_res_o), - .reg_we_o(commit_reg_we_o), - .reg_waddr_o(reg_waddr_o), - .reg_wdata_o(reg_wdata_o) - ); - - assign reg_we_o = commit_reg_we_o; - - assign jump_flag_o = bjp_cmp_res_o | bjp_op_jump_o | sys_op_fence_o | int_assert_i; - assign jump_addr_o = int_assert_i? int_addr_i: - sys_op_fence_o? next_pc_i: - bjp_res_o; - assign hold_flag_o = muldiv_stall_o | mem_stall_o; - - assign csr_raddr_o = csr_addr_o; - assign csr_waddr_o = csr_addr_o; - assign csr_we_o = req_csr_o; - assign csr_wdata_o = alu_res_o; - - assign mem_we_o = mem_mem_we_o; - assign mem_wdata_o = mem_wdata; - -endmodule + /* + Copyright 2019 Blue Liang, liangkangnan@163.com + + 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. + */ + +`include "defines.sv" + +// 鎵ц妯″潡 +// 绾粍鍚堥昏緫鐢佃矾 +module exu( + + input wire clk, + input wire rst_n, + + // clint + input wire int_assert_i, // 涓柇鍙戠敓鏍囧織 + input wire[31:0] int_addr_i, // 涓柇璺宠浆鍦板潃 + input wire int_stall_i, // 鏆傚仠鏍囧織 + output wire inst_ecall_o, // ecall鎸囦护 + output wire inst_ebreak_o, // ebreak鎸囦护 + output wire inst_mret_o, // mret鎸囦护 + + // mem + input wire[31:0] mem_rdata_i, // 鍐呭瓨杈撳叆鏁版嵁 + input wire mem_req_ready_i, + input wire mem_rsp_valid_i, + output wire[31:0] mem_wdata_o, // 鍐欏唴瀛樻暟鎹 + output wire[31:0] mem_addr_o, // 璇汇佸啓鍐呭瓨鍦板潃 + output wire mem_we_o, // 鏄惁瑕佸啓鍐呭瓨 + output wire[3:0] mem_sel_o, // 瀛楄妭浣 + output wire mem_req_valid_o, + output wire mem_rsp_ready_o, + output wire mem_access_misaligned_o, + + // gpr_reg + output wire[31:0] reg_wdata_o, // 鍐欏瘎瀛樺櫒鏁版嵁 + output wire reg_we_o, // 鏄惁瑕佸啓閫氱敤瀵勫瓨鍣 + output wire[4:0] reg_waddr_o, // 鍐欓氱敤瀵勫瓨鍣ㄥ湴鍧 + + // csr_reg + input wire[31:0] csr_rdata_i, + output wire[31:0] csr_raddr_o, // 璇籆SR瀵勫瓨鍣ㄥ湴鍧 + output wire[31:0] csr_wdata_o, // 鍐機SR瀵勫瓨鍣ㄦ暟鎹 + output wire csr_we_o, // 鏄惁瑕佸啓CSR瀵勫瓨鍣 + output wire[31:0] csr_waddr_o, // 鍐機SR瀵勫瓨鍣ㄥ湴鍧 + + // to pipe_ctrl + output wire hold_flag_o, // 鏄惁鏆傚仠鏍囧織 + output wire jump_flag_o, // 鏄惁璺宠浆鏍囧織 + output wire[31:0] jump_addr_o, // 璺宠浆鐩殑鍦板潃 + + // + output wire inst_valid_o, + + // from idu_exu + input wire inst_valid_i, + input wire[31:0] inst_i, + input wire[`DECINFO_WIDTH-1:0] dec_info_bus_i, + input wire[31:0] dec_imm_i, + input wire[31:0] dec_pc_i, + input wire[31:0] next_pc_i, + input wire[4:0] rd_waddr_i, + input wire[31:0] reg1_rdata_i, // 閫氱敤瀵勫瓨鍣1杈撳叆鏁版嵁 + input wire[31:0] reg2_rdata_i, // 閫氱敤瀵勫瓨鍣2杈撳叆鏁版嵁 + input wire rd_we_i + + ); + + // dispatch to ALU + wire[31:0] alu_op1_o; + wire[31:0] alu_op2_o; + wire req_alu_o; + wire alu_op_lui_o; + wire alu_op_auipc_o; + wire alu_op_add_o; + wire alu_op_sub_o; + wire alu_op_sll_o; + wire alu_op_slt_o; + wire alu_op_sltu_o; + wire alu_op_xor_o; + wire alu_op_srl_o; + wire alu_op_sra_o; + wire alu_op_or_o; + wire alu_op_and_o; + // dispatch to BJP + wire[31:0] bjp_op1_o; + wire[31:0] bjp_op2_o; + wire[31:0] bjp_jump_op1_o; + wire[31:0] bjp_jump_op2_o; + wire req_bjp_o; + wire bjp_op_jump_o; + wire bjp_op_beq_o; + wire bjp_op_bne_o; + wire bjp_op_blt_o; + wire bjp_op_bltu_o; + wire bjp_op_bge_o; + wire bjp_op_bgeu_o; + // dispatch to MULDIV + wire req_muldiv_o; + wire[31:0] muldiv_op1_o; + wire[31:0] muldiv_op2_o; + wire muldiv_op_mul_o; + wire muldiv_op_mulh_o; + wire muldiv_op_mulhsu_o; + wire muldiv_op_mulhu_o; + wire muldiv_op_div_o; + wire muldiv_op_divu_o; + wire muldiv_op_rem_o; + wire muldiv_op_remu_o; + // dispatch to CSR + wire req_csr_o; + wire[31:0] csr_op1_o; + wire[31:0] csr_addr_o; + wire csr_csrrw_o; + wire csr_csrrs_o; + wire csr_csrrc_o; + // dispatch to MEM + wire req_mem_o; + wire[31:0] mem_op1_o; + wire[31:0] mem_op2_o; + wire[31:0] mem_rs2_data_o; + wire mem_op_lb_o; + wire mem_op_lh_o; + wire mem_op_lw_o; + wire mem_op_lbu_o; + wire mem_op_lhu_o; + wire mem_op_sb_o; + wire mem_op_sh_o; + wire mem_op_sw_o; + // dispatch to SYS + wire sys_op_nop_o; + wire sys_op_mret_o; + wire sys_op_ecall_o; + wire sys_op_ebreak_o; + wire sys_op_fence_o; + + exu_dispatch u_exu_dispatch( + // input + .clk(clk), + .rst_n(rst_n), + .dec_info_bus_i(dec_info_bus_i), + .dec_imm_i(dec_imm_i), + .dec_pc_i(dec_pc_i), + .rs1_rdata_i(reg1_rdata_i), + .rs2_rdata_i(reg2_rdata_i), + // dispatch to ALU + .alu_op1_o(alu_op1_o), + .alu_op2_o(alu_op2_o), + .req_alu_o(req_alu_o), + .alu_op_lui_o(alu_op_lui_o), + .alu_op_auipc_o(alu_op_auipc_o), + .alu_op_add_o(alu_op_add_o), + .alu_op_sub_o(alu_op_sub_o), + .alu_op_sll_o(alu_op_sll_o), + .alu_op_slt_o(alu_op_slt_o), + .alu_op_sltu_o(alu_op_sltu_o), + .alu_op_xor_o(alu_op_xor_o), + .alu_op_srl_o(alu_op_srl_o), + .alu_op_sra_o(alu_op_sra_o), + .alu_op_or_o(alu_op_or_o), + .alu_op_and_o(alu_op_and_o), + // dispatch to BJP + .bjp_op1_o(bjp_op1_o), + .bjp_op2_o(bjp_op2_o), + .bjp_jump_op1_o(bjp_jump_op1_o), + .bjp_jump_op2_o(bjp_jump_op2_o), + .req_bjp_o(req_bjp_o), + .bjp_op_jump_o(bjp_op_jump_o), + .bjp_op_beq_o(bjp_op_beq_o), + .bjp_op_bne_o(bjp_op_bne_o), + .bjp_op_blt_o(bjp_op_blt_o), + .bjp_op_bltu_o(bjp_op_bltu_o), + .bjp_op_bge_o(bjp_op_bge_o), + .bjp_op_bgeu_o(bjp_op_bgeu_o), + // dispatch to MULDIV + .req_muldiv_o(req_muldiv_o), + .muldiv_op1_o(muldiv_op1_o), + .muldiv_op2_o(muldiv_op2_o), + .muldiv_op_mul_o(muldiv_op_mul_o), + .muldiv_op_mulh_o(muldiv_op_mulh_o), + .muldiv_op_mulhsu_o(muldiv_op_mulhsu_o), + .muldiv_op_mulhu_o(muldiv_op_mulhu_o), + .muldiv_op_div_o(muldiv_op_div_o), + .muldiv_op_divu_o(muldiv_op_divu_o), + .muldiv_op_rem_o(muldiv_op_rem_o), + .muldiv_op_remu_o(muldiv_op_remu_o), + // dispatch to CSR + .req_csr_o(req_csr_o), + .csr_op1_o(csr_op1_o), + .csr_addr_o(csr_addr_o), + .csr_csrrw_o(csr_csrrw_o), + .csr_csrrs_o(csr_csrrs_o), + .csr_csrrc_o(csr_csrrc_o), + // dispatch to MEM + .req_mem_o(req_mem_o), + .mem_op1_o(mem_op1_o), + .mem_op2_o(mem_op2_o), + .mem_rs2_data_o(mem_rs2_data_o), + .mem_op_lb_o(mem_op_lb_o), + .mem_op_lh_o(mem_op_lh_o), + .mem_op_lw_o(mem_op_lw_o), + .mem_op_lbu_o(mem_op_lbu_o), + .mem_op_lhu_o(mem_op_lhu_o), + .mem_op_sb_o(mem_op_sb_o), + .mem_op_sh_o(mem_op_sh_o), + .mem_op_sw_o(mem_op_sw_o), + // dispatch to SYS + .sys_op_nop_o(sys_op_nop_o), + .sys_op_mret_o(sys_op_mret_o), + .sys_op_ecall_o(sys_op_ecall_o), + .sys_op_ebreak_o(sys_op_ebreak_o), + .sys_op_fence_o(sys_op_fence_o) + ); + + assign inst_ecall_o = sys_op_ecall_o; + assign inst_ebreak_o = sys_op_ebreak_o; + assign inst_mret_o = sys_op_mret_o; + + wire[31:0] alu_res_o; + wire[31:0] bjp_res_o; + wire bjp_cmp_res_o; + wire[31:0] csr_op1 = csr_csrrc_o? (~csr_op1_o): csr_op1_o; + wire[31:0] csr_op2 = csr_csrrw_o? (32'h0): csr_rdata_i; + + exu_alu_datapath u_exu_alu_datapath( + .clk(clk), + .rst_n(rst_n), + // ALU + .req_alu_i(req_alu_o), + .alu_op1_i(alu_op1_o), + .alu_op2_i(alu_op2_o), + .alu_op_add_i(alu_op_add_o | alu_op_lui_o | alu_op_auipc_o), + .alu_op_sub_i(alu_op_sub_o), + .alu_op_sll_i(alu_op_sll_o), + .alu_op_slt_i(alu_op_slt_o), + .alu_op_sltu_i(alu_op_sltu_o), + .alu_op_xor_i(alu_op_xor_o), + .alu_op_srl_i(alu_op_srl_o), + .alu_op_sra_i(alu_op_sra_o), + .alu_op_or_i(alu_op_or_o), + .alu_op_and_i(alu_op_and_o), + // BJP + .req_bjp_i(req_bjp_o), + .bjp_op1_i(bjp_op1_o), + .bjp_op2_i(bjp_op2_o), + .bjp_op_beq_i(bjp_op_beq_o), + .bjp_op_bne_i(bjp_op_bne_o), + .bjp_op_blt_i(bjp_op_blt_o), + .bjp_op_bltu_i(bjp_op_bltu_o), + .bjp_op_bge_i(bjp_op_bge_o), + .bjp_op_bgeu_i(bjp_op_bgeu_o), + .bjp_op_jump_i(bjp_op_jump_o), + .bjp_jump_op1_i(bjp_jump_op1_o), + .bjp_jump_op2_i(bjp_jump_op2_o), + // MEM + .req_mem_i(req_mem_o), + .mem_op1_i(mem_op1_o), + .mem_op2_i(mem_op2_o), + // CSR + .req_csr_i(req_csr_o), + .csr_op1_i(csr_op1), + .csr_op2_i(csr_op2), + .csr_csrrw_i(csr_csrrw_o), + .csr_csrrs_i(csr_csrrs_o), + .csr_csrrc_i(csr_csrrc_o), + + .alu_res_o(alu_res_o), + .bjp_res_o(bjp_res_o), + .bjp_cmp_res_o(bjp_cmp_res_o) + ); + + wire mem_reg_we_o; + wire mem_mem_we_o; + wire[31:0] mem_wdata; + wire mem_stall_o; + + exu_mem u_exu_mem( + .clk(clk), + .rst_n(rst_n), + .req_mem_i(req_mem_o), + .mem_addr_i(alu_res_o), + .mem_rs2_data_i(mem_rs2_data_o), + .mem_req_ready_i(mem_req_ready_i), + .mem_rsp_valid_i(mem_rsp_valid_i), + .mem_rdata_i(mem_rdata_i), + .mem_op_lb_i(mem_op_lb_o), + .mem_op_lh_i(mem_op_lh_o), + .mem_op_lw_i(mem_op_lw_o), + .mem_op_lbu_i(mem_op_lbu_o), + .mem_op_lhu_i(mem_op_lhu_o), + .mem_op_sb_i(mem_op_sb_o), + .mem_op_sh_i(mem_op_sh_o), + .mem_op_sw_i(mem_op_sw_o), + .mem_access_misaligned_o(mem_access_misaligned_o), + .mem_stall_o(mem_stall_o), + .mem_addr_o(mem_addr_o), + .mem_wdata_o(mem_wdata), + .mem_reg_we_o(mem_reg_we_o), + .mem_mem_we_o(mem_mem_we_o), + .mem_sel_o(mem_sel_o), + .mem_req_valid_o(mem_req_valid_o), + .mem_rsp_ready_o(mem_rsp_ready_o) + ); + + wire[31:0] muldiv_reg_wdata_o; + wire muldiv_reg_we_o; + wire muldiv_stall_o; + + exu_muldiv u_exu_muldiv( + .clk(clk), + .rst_n(rst_n), + .muldiv_op1_i(muldiv_op1_o), + .muldiv_op2_i(muldiv_op2_o), + .muldiv_op_mul_i(muldiv_op_mul_o), + .muldiv_op_mulh_i(muldiv_op_mulh_o), + .muldiv_op_mulhsu_i(muldiv_op_mulhsu_o), + .muldiv_op_mulhu_i(muldiv_op_mulhu_o), + .muldiv_op_div_i(muldiv_op_div_o), + .muldiv_op_divu_i(muldiv_op_divu_o), + .muldiv_op_rem_i(muldiv_op_rem_o), + .muldiv_op_remu_i(muldiv_op_remu_o), + .muldiv_reg_wdata_o(muldiv_reg_wdata_o), + .muldiv_reg_we_o(muldiv_reg_we_o), + .muldiv_stall_o(muldiv_stall_o) + ); + + wire commit_reg_we_o; + + exu_commit u_exu_commit( + .clk(clk), + .rst_n(rst_n), + .req_muldiv_i(req_muldiv_o), + .muldiv_reg_we_i(muldiv_reg_we_o), + .muldiv_reg_waddr_i(rd_waddr_i), + .muldiv_reg_wdata_i(muldiv_reg_wdata_o), + .req_mem_i(req_mem_o), + .mem_reg_we_i(mem_reg_we_o), + .mem_reg_waddr_i(rd_waddr_i), + .mem_reg_wdata_i(mem_wdata), + .req_csr_i(req_csr_o), + .csr_reg_we_i(req_csr_o), + .csr_reg_waddr_i(rd_waddr_i), + .csr_reg_wdata_i(csr_rdata_i), + .req_bjp_i(req_bjp_o), + .bjp_reg_we_i(bjp_op_jump_o), + .bjp_reg_wdata_i(next_pc_i), + .bjp_reg_waddr_i(rd_waddr_i), + .rd_we_i(rd_we_i), + .rd_waddr_i(rd_waddr_i), + .alu_reg_wdata_i(alu_res_o), + .reg_we_o(commit_reg_we_o), + .reg_waddr_o(reg_waddr_o), + .reg_wdata_o(reg_wdata_o) + ); + + assign reg_we_o = commit_reg_we_o; + + assign jump_flag_o = bjp_cmp_res_o | bjp_op_jump_o | sys_op_fence_o | int_assert_i; + assign jump_addr_o = int_assert_i? int_addr_i: + sys_op_fence_o? next_pc_i: + bjp_res_o; + assign hold_flag_o = muldiv_stall_o | mem_stall_o; + + assign csr_raddr_o = csr_addr_o; + assign csr_waddr_o = csr_addr_o; + assign csr_we_o = req_csr_o; + assign csr_wdata_o = alu_res_o; + + assign mem_we_o = mem_mem_we_o; + assign mem_wdata_o = mem_wdata; + + assign inst_valid_o = hold_flag_o? 1'b0: inst_valid_i; + +endmodule diff --git a/rtl/core/exu_alu_datapath.sv b/rtl/core/exu_alu_datapath.sv index ee78d21..5817d4f 100644 --- a/rtl/core/exu_alu_datapath.sv +++ b/rtl/core/exu_alu_datapath.sv @@ -1,254 +1,254 @@ - /* - Copyright 2020 Blue Liang, liangkangnan@163.com - - 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. - */ - -`include "defines.sv" - - -`define DATAPATH_MUX_WIDTH (32+32+16) - - -module exu_alu_datapath( - - input wire clk, - input wire rst_n, - - // ALU - input wire req_alu_i, - input wire[31:0] alu_op1_i, - input wire[31:0] alu_op2_i, - input wire alu_op_add_i, - input wire alu_op_sub_i, - input wire alu_op_sll_i, - input wire alu_op_slt_i, - input wire alu_op_sltu_i, - input wire alu_op_xor_i, - input wire alu_op_srl_i, - input wire alu_op_sra_i, - input wire alu_op_or_i, - input wire alu_op_and_i, - - // BJP - input wire req_bjp_i, - input wire[31:0] bjp_op1_i, - input wire[31:0] bjp_op2_i, - input wire bjp_op_beq_i, - input wire bjp_op_bne_i, - input wire bjp_op_blt_i, - input wire bjp_op_bltu_i, - input wire bjp_op_bge_i, - input wire bjp_op_bgeu_i, - input wire bjp_op_jump_i, - input wire[31:0] bjp_jump_op1_i, - input wire[31:0] bjp_jump_op2_i, - - // MEM - input wire req_mem_i, - input wire[31:0] mem_op1_i, - input wire[31:0] mem_op2_i, - - // CSR - input wire req_csr_i, - input wire[31:0] csr_op1_i, - input wire[31:0] csr_op2_i, - input wire csr_csrrw_i, - input wire csr_csrrs_i, - input wire csr_csrrc_i, - - output wire[31:0] alu_res_o, - output wire[31:0] bjp_res_o, - output wire bjp_cmp_res_o - - ); - - wire[31:0] mux_op1; - wire[31:0] mux_op2; - wire op_add; - wire op_sub; - wire op_sll; - wire op_slt; - wire op_sltu; - wire op_xor; - wire op_srl; - wire op_sra; - wire op_or; - wire op_and; - wire op_beq; - wire op_bne; - wire op_blt; - wire op_bltu; - wire op_bge; - wire op_bgeu; - - // 寮傛垨 - wire[31:0] xor_res = mux_op1 ^ mux_op2; - // 鎴 - wire[31:0] or_res = mux_op1 | mux_op2; - // 涓 - wire[31:0] and_res = mux_op1 & mux_op2; - // 鍔犮佸噺 - wire[31:0] add_op1 = req_bjp_i? bjp_jump_op1_i: mux_op1; - wire[31:0] add_op2 = req_bjp_i? bjp_jump_op2_i: mux_op2; - wire[31:0] add_sub_res = add_op1 + (op_sub? (-add_op2): add_op2); - // 宸︾Щ - wire[31:0] sll_res = mux_op1 << mux_op2[4:0]; - // 閫昏緫鍙崇Щ - wire[31:0] srl_res = mux_op1 >> mux_op2[4:0]; - // 绠楁暟鍙崇Щ - wire[31:0] sr_shift_mask = 32'hffffffff >> mux_op2[4:0]; - wire[31:0] sra_res = (srl_res & sr_shift_mask) | ({32{mux_op1[31]}} & (~sr_shift_mask)); - - // 鏈夌鍙锋暟姣旇緝 - wire op1_ge_op2_signed = ($signed(mux_op1) >= $signed(mux_op2)); - // 鏃犵鍙锋暟姣旇緝 - wire op1_ge_op2_unsigned = (mux_op1 >= mux_op2); - - wire op1_neq_op2 = (|xor_res); - wire op1_eq_op2 = (~op1_neq_op2); - - wire cmp_res_eq = op_beq & op1_eq_op2; - wire cmp_res_neq = op_bne & op1_neq_op2; - wire cmp_res_lt = op_blt & (~op1_ge_op2_signed); - wire cmp_res_ltu = op_bltu & (~op1_ge_op2_unsigned); - wire cmp_res_gt = op_bge & op1_ge_op2_signed; - wire cmp_res_gtu = op_bgeu & op1_ge_op2_unsigned; - - wire[31:0] slt_res = (~op1_ge_op2_signed)? 32'h1: 32'h0; - wire[31:0] sltu_res = (~op1_ge_op2_unsigned)? 32'h1: 32'h0; - - reg[31:0] alu_datapath_res; - - always @ (*) begin - alu_datapath_res = 32'h0; - case (1'b1) - op_xor: alu_datapath_res = xor_res; - op_or: alu_datapath_res = or_res; - op_and: alu_datapath_res = and_res; - op_add: alu_datapath_res = add_sub_res; - op_sub: alu_datapath_res = add_sub_res; - op_sll: alu_datapath_res = sll_res; - op_srl: alu_datapath_res = srl_res; - op_sra: alu_datapath_res = sra_res; - op_slt: alu_datapath_res = slt_res; - op_sltu: alu_datapath_res = sltu_res; - endcase - end - - assign alu_res_o = alu_datapath_res; - - assign bjp_res_o = alu_datapath_res; - - assign bjp_cmp_res_o = cmp_res_eq | cmp_res_neq | cmp_res_lt | cmp_res_ltu | cmp_res_gt | cmp_res_gtu; - - assign {mux_op1, - mux_op2, - op_add, - op_sub, - op_sll, - op_slt, - op_sltu, - op_xor, - op_srl, - op_sra, - op_or, - op_and, - op_beq, - op_bne, - op_blt, - op_bltu, - op_bge, - op_bgeu - } = ({`DATAPATH_MUX_WIDTH{req_alu_i}} & { - alu_op1_i, - alu_op2_i, - alu_op_add_i, - alu_op_sub_i, - alu_op_sll_i, - alu_op_slt_i, - alu_op_sltu_i, - alu_op_xor_i, - alu_op_srl_i, - alu_op_sra_i, - alu_op_or_i, - alu_op_and_i, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0 - }) | - ({`DATAPATH_MUX_WIDTH{req_bjp_i}} & { - bjp_op1_i, - bjp_op2_i, - 1'b1, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - bjp_op_beq_i, - bjp_op_bne_i, - bjp_op_blt_i, - bjp_op_bltu_i, - bjp_op_bge_i, - bjp_op_bgeu_i - }) | - ({`DATAPATH_MUX_WIDTH{req_mem_i}} & { - mem_op1_i, - mem_op2_i, - 1'b1, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0 - }) | - ({`DATAPATH_MUX_WIDTH{req_csr_i}} & { - csr_op1_i, - csr_op2_i, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - csr_csrrw_i | csr_csrrs_i, - csr_csrrc_i, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0, - 1'b0 - }); - -endmodule + /* + Copyright 2020 Blue Liang, liangkangnan@163.com + + 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. + */ + +`include "defines.sv" + + +`define DATAPATH_MUX_WIDTH (32+32+16) + + +module exu_alu_datapath( + + input wire clk, + input wire rst_n, + + // ALU + input wire req_alu_i, + input wire[31:0] alu_op1_i, + input wire[31:0] alu_op2_i, + input wire alu_op_add_i, + input wire alu_op_sub_i, + input wire alu_op_sll_i, + input wire alu_op_slt_i, + input wire alu_op_sltu_i, + input wire alu_op_xor_i, + input wire alu_op_srl_i, + input wire alu_op_sra_i, + input wire alu_op_or_i, + input wire alu_op_and_i, + + // BJP + input wire req_bjp_i, + input wire[31:0] bjp_op1_i, + input wire[31:0] bjp_op2_i, + input wire bjp_op_beq_i, + input wire bjp_op_bne_i, + input wire bjp_op_blt_i, + input wire bjp_op_bltu_i, + input wire bjp_op_bge_i, + input wire bjp_op_bgeu_i, + input wire bjp_op_jump_i, + input wire[31:0] bjp_jump_op1_i, + input wire[31:0] bjp_jump_op2_i, + + // MEM + input wire req_mem_i, + input wire[31:0] mem_op1_i, + input wire[31:0] mem_op2_i, + + // CSR + input wire req_csr_i, + input wire[31:0] csr_op1_i, + input wire[31:0] csr_op2_i, + input wire csr_csrrw_i, + input wire csr_csrrs_i, + input wire csr_csrrc_i, + + output wire[31:0] alu_res_o, + output wire[31:0] bjp_res_o, + output wire bjp_cmp_res_o + + ); + + wire[31:0] mux_op1; + wire[31:0] mux_op2; + wire op_add; + wire op_sub; + wire op_sll; + wire op_slt; + wire op_sltu; + wire op_xor; + wire op_srl; + wire op_sra; + wire op_or; + wire op_and; + wire op_beq; + wire op_bne; + wire op_blt; + wire op_bltu; + wire op_bge; + wire op_bgeu; + + // 寮傛垨 + wire[31:0] xor_res = mux_op1 ^ mux_op2; + // 鎴 + wire[31:0] or_res = mux_op1 | mux_op2; + // 涓 + wire[31:0] and_res = mux_op1 & mux_op2; + // 鍔犮佸噺 + wire[31:0] add_op1 = req_bjp_i? bjp_jump_op1_i: mux_op1; + wire[31:0] add_op2 = req_bjp_i? bjp_jump_op2_i: mux_op2; + wire[31:0] add_sub_res = add_op1 + (op_sub? (-add_op2): add_op2); + // 宸︾Щ + wire[31:0] sll_res = mux_op1 << mux_op2[4:0]; + // 閫昏緫鍙崇Щ + wire[31:0] srl_res = mux_op1 >> mux_op2[4:0]; + // 绠楁暟鍙崇Щ + wire[31:0] sr_shift_mask = 32'hffffffff >> mux_op2[4:0]; + wire[31:0] sra_res = (srl_res & sr_shift_mask) | ({32{mux_op1[31]}} & (~sr_shift_mask)); + + // 鏈夌鍙锋暟姣旇緝 + wire op1_ge_op2_signed = ($signed(mux_op1) >= $signed(mux_op2)); + // 鏃犵鍙锋暟姣旇緝 + wire op1_ge_op2_unsigned = (mux_op1 >= mux_op2); + + wire op1_neq_op2 = (|xor_res); + wire op1_eq_op2 = (~op1_neq_op2); + + wire cmp_res_eq = op_beq & op1_eq_op2; + wire cmp_res_neq = op_bne & op1_neq_op2; + wire cmp_res_lt = op_blt & (~op1_ge_op2_signed); + wire cmp_res_ltu = op_bltu & (~op1_ge_op2_unsigned); + wire cmp_res_gt = op_bge & op1_ge_op2_signed; + wire cmp_res_gtu = op_bgeu & op1_ge_op2_unsigned; + + wire[31:0] slt_res = (~op1_ge_op2_signed)? 32'h1: 32'h0; + wire[31:0] sltu_res = (~op1_ge_op2_unsigned)? 32'h1: 32'h0; + + reg[31:0] alu_datapath_res; + + always @ (*) begin + alu_datapath_res = 32'h0; + case (1'b1) + op_xor: alu_datapath_res = xor_res; + op_or: alu_datapath_res = or_res; + op_and: alu_datapath_res = and_res; + op_add: alu_datapath_res = add_sub_res; + op_sub: alu_datapath_res = add_sub_res; + op_sll: alu_datapath_res = sll_res; + op_srl: alu_datapath_res = srl_res; + op_sra: alu_datapath_res = sra_res; + op_slt: alu_datapath_res = slt_res; + op_sltu: alu_datapath_res = sltu_res; + endcase + end + + assign alu_res_o = alu_datapath_res; + + assign bjp_res_o = alu_datapath_res; + + assign bjp_cmp_res_o = cmp_res_eq | cmp_res_neq | cmp_res_lt | cmp_res_ltu | cmp_res_gt | cmp_res_gtu; + + assign {mux_op1, + mux_op2, + op_add, + op_sub, + op_sll, + op_slt, + op_sltu, + op_xor, + op_srl, + op_sra, + op_or, + op_and, + op_beq, + op_bne, + op_blt, + op_bltu, + op_bge, + op_bgeu + } = ({`DATAPATH_MUX_WIDTH{req_alu_i}} & { + alu_op1_i, + alu_op2_i, + alu_op_add_i, + alu_op_sub_i, + alu_op_sll_i, + alu_op_slt_i, + alu_op_sltu_i, + alu_op_xor_i, + alu_op_srl_i, + alu_op_sra_i, + alu_op_or_i, + alu_op_and_i, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0 + }) | + ({`DATAPATH_MUX_WIDTH{req_bjp_i}} & { + bjp_op1_i, + bjp_op2_i, + 1'b1, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + bjp_op_beq_i, + bjp_op_bne_i, + bjp_op_blt_i, + bjp_op_bltu_i, + bjp_op_bge_i, + bjp_op_bgeu_i + }) | + ({`DATAPATH_MUX_WIDTH{req_mem_i}} & { + mem_op1_i, + mem_op2_i, + 1'b1, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0 + }) | + ({`DATAPATH_MUX_WIDTH{req_csr_i}} & { + csr_op1_i, + csr_op2_i, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + csr_csrrw_i | csr_csrrs_i, + csr_csrrc_i, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0, + 1'b0 + }); + +endmodule diff --git a/rtl/core/exu_commit.sv b/rtl/core/exu_commit.sv index 98edbd0..5a91505 100644 --- a/rtl/core/exu_commit.sv +++ b/rtl/core/exu_commit.sv @@ -1,92 +1,92 @@ - /* - Copyright 2020 Blue Liang, liangkangnan@163.com - - 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. - */ - -`include "defines.sv" - - -module exu_commit( - - input wire clk, - input wire rst_n, - - input wire req_muldiv_i, - input wire muldiv_reg_we_i, - input wire[4:0] muldiv_reg_waddr_i, - input wire[31:0] muldiv_reg_wdata_i, - - input wire req_mem_i, - input wire mem_reg_we_i, - input wire[4:0] mem_reg_waddr_i, - input wire[31:0] mem_reg_wdata_i, - - input wire req_csr_i, - input wire csr_reg_we_i, - input wire[4:0] csr_reg_waddr_i, - input wire[31:0] csr_reg_wdata_i, - - input wire req_bjp_i, - input wire bjp_reg_we_i, - input wire[31:0] bjp_reg_wdata_i, - input wire[4:0] bjp_reg_waddr_i, - - input wire rd_we_i, - input wire[4:0] rd_waddr_i, - input wire[31:0] alu_reg_wdata_i, - - output wire reg_we_o, - output wire[4:0] reg_waddr_o, - output wire[31:0] reg_wdata_o - - ); - - wire use_alu_res = (~req_muldiv_i) & - (~req_mem_i) & - (~req_csr_i) & - (~req_bjp_i); - - assign reg_we_o = muldiv_reg_we_i | mem_reg_we_i | csr_reg_we_i | use_alu_res | bjp_reg_we_i; - - reg[4:0] reg_waddr; - - always @ (*) begin - reg_waddr = 5'h0; - case (1'b1) - muldiv_reg_we_i: reg_waddr = muldiv_reg_waddr_i; - mem_reg_we_i: reg_waddr = mem_reg_waddr_i; - csr_reg_we_i: reg_waddr = csr_reg_waddr_i; - bjp_reg_we_i: reg_waddr = bjp_reg_waddr_i; - rd_we_i: reg_waddr = rd_waddr_i; - endcase - end - - assign reg_waddr_o = reg_waddr; - - reg[31:0] reg_wdata; - - always @ (*) begin - reg_wdata = 32'h0; - case (1'b1) - muldiv_reg_we_i: reg_wdata = muldiv_reg_wdata_i; - mem_reg_we_i: reg_wdata = mem_reg_wdata_i; - csr_reg_we_i: reg_wdata = csr_reg_wdata_i; - bjp_reg_we_i: reg_wdata = bjp_reg_wdata_i; - use_alu_res: reg_wdata = alu_reg_wdata_i; - endcase - end - - assign reg_wdata_o = reg_wdata; - -endmodule + /* + Copyright 2020 Blue Liang, liangkangnan@163.com + + 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. + */ + +`include "defines.sv" + + +module exu_commit( + + input wire clk, + input wire rst_n, + + input wire req_muldiv_i, + input wire muldiv_reg_we_i, + input wire[4:0] muldiv_reg_waddr_i, + input wire[31:0] muldiv_reg_wdata_i, + + input wire req_mem_i, + input wire mem_reg_we_i, + input wire[4:0] mem_reg_waddr_i, + input wire[31:0] mem_reg_wdata_i, + + input wire req_csr_i, + input wire csr_reg_we_i, + input wire[4:0] csr_reg_waddr_i, + input wire[31:0] csr_reg_wdata_i, + + input wire req_bjp_i, + input wire bjp_reg_we_i, + input wire[31:0] bjp_reg_wdata_i, + input wire[4:0] bjp_reg_waddr_i, + + input wire rd_we_i, + input wire[4:0] rd_waddr_i, + input wire[31:0] alu_reg_wdata_i, + + output wire reg_we_o, + output wire[4:0] reg_waddr_o, + output wire[31:0] reg_wdata_o + + ); + + wire use_alu_res = (~req_muldiv_i) & + (~req_mem_i) & + (~req_csr_i) & + (~req_bjp_i); + + assign reg_we_o = muldiv_reg_we_i | mem_reg_we_i | csr_reg_we_i | use_alu_res | bjp_reg_we_i; + + reg[4:0] reg_waddr; + + always @ (*) begin + reg_waddr = 5'h0; + case (1'b1) + muldiv_reg_we_i: reg_waddr = muldiv_reg_waddr_i; + mem_reg_we_i: reg_waddr = mem_reg_waddr_i; + csr_reg_we_i: reg_waddr = csr_reg_waddr_i; + bjp_reg_we_i: reg_waddr = bjp_reg_waddr_i; + rd_we_i: reg_waddr = rd_waddr_i; + endcase + end + + assign reg_waddr_o = reg_waddr; + + reg[31:0] reg_wdata; + + always @ (*) begin + reg_wdata = 32'h0; + case (1'b1) + muldiv_reg_we_i: reg_wdata = muldiv_reg_wdata_i; + mem_reg_we_i: reg_wdata = mem_reg_wdata_i; + csr_reg_we_i: reg_wdata = csr_reg_wdata_i; + bjp_reg_we_i: reg_wdata = bjp_reg_wdata_i; + use_alu_res: reg_wdata = alu_reg_wdata_i; + endcase + end + + assign reg_wdata_o = reg_wdata; + +endmodule diff --git a/rtl/core/exu_dispatch.sv b/rtl/core/exu_dispatch.sv index cd39713..6b5a2f2 100644 --- a/rtl/core/exu_dispatch.sv +++ b/rtl/core/exu_dispatch.sv @@ -1,210 +1,210 @@ - /* - Copyright 2020 Blue Liang, liangkangnan@163.com - - 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. - */ - -`include "defines.sv" - - -module exu_dispatch( - - input wire clk, - input wire rst_n, - - input wire[`DECINFO_WIDTH-1:0] dec_info_bus_i, - input wire[31:0] dec_imm_i, - input wire[31:0] dec_pc_i, - input wire[31:0] rs1_rdata_i, - input wire[31:0] rs2_rdata_i, - - // dispatch to ALU - output wire req_alu_o, - output wire[31:0] alu_op1_o, - output wire[31:0] alu_op2_o, - output wire alu_op_lui_o, - output wire alu_op_auipc_o, - output wire alu_op_add_o, - output wire alu_op_sub_o, - output wire alu_op_sll_o, - output wire alu_op_slt_o, - output wire alu_op_sltu_o, - output wire alu_op_xor_o, - output wire alu_op_srl_o, - output wire alu_op_sra_o, - output wire alu_op_or_o, - output wire alu_op_and_o, - - // dispatch to BJP - output wire req_bjp_o, - output wire[31:0] bjp_op1_o, - output wire[31:0] bjp_op2_o, - output wire[31:0] bjp_jump_op1_o, - output wire[31:0] bjp_jump_op2_o, - output wire bjp_op_jump_o, - output wire bjp_op_beq_o, - output wire bjp_op_bne_o, - output wire bjp_op_blt_o, - output wire bjp_op_bltu_o, - output wire bjp_op_bge_o, - output wire bjp_op_bgeu_o, - - // dispatch to MULDIV - output wire req_muldiv_o, - output wire[31:0] muldiv_op1_o, - output wire[31:0] muldiv_op2_o, - output wire muldiv_op_mul_o, - output wire muldiv_op_mulh_o, - output wire muldiv_op_mulhsu_o, - output wire muldiv_op_mulhu_o, - output wire muldiv_op_div_o, - output wire muldiv_op_divu_o, - output wire muldiv_op_rem_o, - output wire muldiv_op_remu_o, - - // dispatch to CSR - output wire req_csr_o, - output wire[31:0] csr_op1_o, - output wire[31:0] csr_addr_o, - output wire csr_csrrw_o, - output wire csr_csrrs_o, - output wire csr_csrrc_o, - - // dispatch to MEM - output wire req_mem_o, - output wire[31:0] mem_op1_o, - output wire[31:0] mem_op2_o, - output wire[31:0] mem_rs2_data_o, - output wire mem_op_lb_o, - output wire mem_op_lh_o, - output wire mem_op_lw_o, - output wire mem_op_lbu_o, - output wire mem_op_lhu_o, - output wire mem_op_sb_o, - output wire mem_op_sh_o, - output wire mem_op_sw_o, - - // dispatch to SYS - output wire sys_op_nop_o, - output wire sys_op_mret_o, - output wire sys_op_ecall_o, - output wire sys_op_ebreak_o, - output wire sys_op_fence_o - - ); - - wire[`DECINFO_GRP_WIDTH-1:0] disp_info_grp = dec_info_bus_i[`DECINFO_GRP_BUS]; - - // ALU info - wire op_alu = (disp_info_grp == `DECINFO_GRP_ALU); - wire[`DECINFO_WIDTH-1:0] alu_info = {`DECINFO_WIDTH{op_alu}} & dec_info_bus_i; - // ALU op1 - wire alu_op1_pc = alu_info[`DECINFO_ALU_OP1PC]; - wire alu_op1_zero = alu_info[`DECINFO_ALU_LUI]; - wire[31:0] alu_op1 = alu_op1_pc? dec_pc_i: alu_op1_zero? 32'h0: rs1_rdata_i; - assign alu_op1_o = op_alu? alu_op1: 32'h0; - // ALU op2 - wire alu_op2_imm = alu_info[`DECINFO_ALU_OP2IMM]; - wire[31:0] alu_op2 = alu_op2_imm? dec_imm_i: rs2_rdata_i; - assign alu_op2_o = op_alu? alu_op2: 32'h0; - assign alu_op_lui_o = alu_info[`DECINFO_ALU_LUI]; - assign alu_op_auipc_o = alu_info[`DECINFO_ALU_AUIPC]; - assign alu_op_add_o = alu_info[`DECINFO_ALU_ADD]; - assign alu_op_sub_o = alu_info[`DECINFO_ALU_SUB]; - assign alu_op_sll_o = alu_info[`DECINFO_ALU_SLL]; - assign alu_op_slt_o = alu_info[`DECINFO_ALU_SLT]; - assign alu_op_sltu_o = alu_info[`DECINFO_ALU_SLTU]; - assign alu_op_xor_o = alu_info[`DECINFO_ALU_XOR]; - assign alu_op_srl_o = alu_info[`DECINFO_ALU_SRL]; - assign alu_op_sra_o = alu_info[`DECINFO_ALU_SRA]; - assign alu_op_or_o = alu_info[`DECINFO_ALU_OR]; - assign alu_op_and_o = alu_info[`DECINFO_ALU_AND]; - assign req_alu_o = op_alu; - - // BJP info - wire op_bjp = (disp_info_grp == `DECINFO_GRP_BJP); - wire[`DECINFO_WIDTH-1:0] bjp_info = {`DECINFO_WIDTH{op_bjp}} & dec_info_bus_i; - // BJP op1 - wire bjp_op1_rs1 = bjp_info[`DECINFO_BJP_OP1RS1]; - wire[31:0] bjp_op1 = bjp_op1_rs1? rs1_rdata_i: dec_pc_i; - assign bjp_jump_op1_o = op_bjp? bjp_op1: 32'h0; - // BJP op2 - wire[31:0] bjp_op2 = dec_imm_i; - assign bjp_jump_op2_o = op_bjp? bjp_op2: 32'h0; - assign bjp_op1_o = op_bjp? rs1_rdata_i: 32'h0; - assign bjp_op2_o = op_bjp? rs2_rdata_i: 32'h0; - assign bjp_op_jump_o = bjp_info[`DECINFO_BJP_JUMP]; - assign bjp_op_beq_o = bjp_info[`DECINFO_BJP_BEQ]; - assign bjp_op_bne_o = bjp_info[`DECINFO_BJP_BNE]; - assign bjp_op_blt_o = bjp_info[`DECINFO_BJP_BLT]; - assign bjp_op_bltu_o = bjp_info[`DECINFO_BJP_BLTU]; - assign bjp_op_bge_o = bjp_info[`DECINFO_BJP_BGE]; - assign bjp_op_bgeu_o = bjp_info[`DECINFO_BJP_BGEU]; - assign req_bjp_o = op_bjp; - - // MULDIV info - wire op_muldiv = (disp_info_grp == `DECINFO_GRP_MULDIV); - wire[`DECINFO_WIDTH-1:0] muldiv_info = {`DECINFO_WIDTH{op_muldiv}} & dec_info_bus_i; - // MULDIV op1 - assign muldiv_op1_o = op_muldiv? rs1_rdata_i: 32'h0; - // MULDIV op2 - assign muldiv_op2_o = op_muldiv? rs2_rdata_i: 32'h0; - assign muldiv_op_mul_o = muldiv_info[`DECINFO_MULDIV_MUL]; - assign muldiv_op_mulh_o = muldiv_info[`DECINFO_MULDIV_MULH]; - assign muldiv_op_mulhu_o = muldiv_info[`DECINFO_MULDIV_MULHU]; - assign muldiv_op_mulhsu_o = muldiv_info[`DECINFO_MULDIV_MULHSU]; - assign muldiv_op_div_o = muldiv_info[`DECINFO_MULDIV_DIV]; - assign muldiv_op_divu_o = muldiv_info[`DECINFO_MULDIV_DIVU]; - assign muldiv_op_rem_o = muldiv_info[`DECINFO_MULDIV_REM]; - assign muldiv_op_remu_o = muldiv_info[`DECINFO_MULDIV_REMU]; - assign req_muldiv_o = op_muldiv; - - // CSR info - wire op_csr = (disp_info_grp == `DECINFO_GRP_CSR); - wire[`DECINFO_WIDTH-1:0] csr_info = {`DECINFO_WIDTH{op_csr}} & dec_info_bus_i; - // CSR op1 - wire csr_rs1imm = csr_info[`DECINFO_CSR_RS1IMM]; - wire[31:0] csr_rs1 = csr_rs1imm? dec_imm_i: rs1_rdata_i; - assign csr_op1_o = op_csr? csr_rs1: 32'h0; - assign csr_addr_o = {{20{1'b0}}, csr_info[`DECINFO_CSR_CSRADDR]}; - assign csr_csrrw_o = csr_info[`DECINFO_CSR_CSRRW]; - assign csr_csrrs_o = csr_info[`DECINFO_CSR_CSRRS]; - assign csr_csrrc_o = csr_info[`DECINFO_CSR_CSRRC]; - assign req_csr_o = op_csr; - - // MEM info - wire op_mem = (disp_info_grp == `DECINFO_GRP_MEM); - wire[`DECINFO_WIDTH-1:0] mem_info = {`DECINFO_WIDTH{op_mem}} & dec_info_bus_i; - assign mem_op_lb_o = mem_info[`DECINFO_MEM_LB]; - assign mem_op_lh_o = mem_info[`DECINFO_MEM_LH]; - assign mem_op_lw_o = mem_info[`DECINFO_MEM_LW]; - assign mem_op_lbu_o = mem_info[`DECINFO_MEM_LBU]; - assign mem_op_lhu_o = mem_info[`DECINFO_MEM_LHU]; - assign mem_op_sb_o = mem_info[`DECINFO_MEM_SB]; - assign mem_op_sh_o = mem_info[`DECINFO_MEM_SH]; - assign mem_op_sw_o = mem_info[`DECINFO_MEM_SW]; - assign mem_op1_o = op_mem? rs1_rdata_i: 32'h0; - assign mem_op2_o = op_mem? dec_imm_i: 32'h0; - assign mem_rs2_data_o = op_mem? rs2_rdata_i: 32'h0; - assign req_mem_o = op_mem; - - // SYS info - wire op_sys = (disp_info_grp == `DECINFO_GRP_SYS); - wire[`DECINFO_WIDTH-1:0] sys_info = {`DECINFO_WIDTH{op_sys}} & dec_info_bus_i; - assign sys_op_nop_o = sys_info[`DECINFO_SYS_NOP]; - assign sys_op_mret_o = sys_info[`DECINFO_SYS_MRET]; - assign sys_op_ecall_o = sys_info[`DECINFO_SYS_ECALL]; - assign sys_op_ebreak_o = sys_info[`DECINFO_SYS_EBREAK]; - assign sys_op_fence_o = sys_info[`DECINFO_SYS_FENCE]; - -endmodule + /* + Copyright 2020 Blue Liang, liangkangnan@163.com + + 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. + */ + +`include "defines.sv" + + +module exu_dispatch( + + input wire clk, + input wire rst_n, + + input wire[`DECINFO_WIDTH-1:0] dec_info_bus_i, + input wire[31:0] dec_imm_i, + input wire[31:0] dec_pc_i, + input wire[31:0] rs1_rdata_i, + input wire[31:0] rs2_rdata_i, + + // dispatch to ALU + output wire req_alu_o, + output wire[31:0] alu_op1_o, + output wire[31:0] alu_op2_o, + output wire alu_op_lui_o, + output wire alu_op_auipc_o, + output wire alu_op_add_o, + output wire alu_op_sub_o, + output wire alu_op_sll_o, + output wire alu_op_slt_o, + output wire alu_op_sltu_o, + output wire alu_op_xor_o, + output wire alu_op_srl_o, + output wire alu_op_sra_o, + output wire alu_op_or_o, + output wire alu_op_and_o, + + // dispatch to BJP + output wire req_bjp_o, + output wire[31:0] bjp_op1_o, + output wire[31:0] bjp_op2_o, + output wire[31:0] bjp_jump_op1_o, + output wire[31:0] bjp_jump_op2_o, + output wire bjp_op_jump_o, + output wire bjp_op_beq_o, + output wire bjp_op_bne_o, + output wire bjp_op_blt_o, + output wire bjp_op_bltu_o, + output wire bjp_op_bge_o, + output wire bjp_op_bgeu_o, + + // dispatch to MULDIV + output wire req_muldiv_o, + output wire[31:0] muldiv_op1_o, + output wire[31:0] muldiv_op2_o, + output wire muldiv_op_mul_o, + output wire muldiv_op_mulh_o, + output wire muldiv_op_mulhsu_o, + output wire muldiv_op_mulhu_o, + output wire muldiv_op_div_o, + output wire muldiv_op_divu_o, + output wire muldiv_op_rem_o, + output wire muldiv_op_remu_o, + + // dispatch to CSR + output wire req_csr_o, + output wire[31:0] csr_op1_o, + output wire[31:0] csr_addr_o, + output wire csr_csrrw_o, + output wire csr_csrrs_o, + output wire csr_csrrc_o, + + // dispatch to MEM + output wire req_mem_o, + output wire[31:0] mem_op1_o, + output wire[31:0] mem_op2_o, + output wire[31:0] mem_rs2_data_o, + output wire mem_op_lb_o, + output wire mem_op_lh_o, + output wire mem_op_lw_o, + output wire mem_op_lbu_o, + output wire mem_op_lhu_o, + output wire mem_op_sb_o, + output wire mem_op_sh_o, + output wire mem_op_sw_o, + + // dispatch to SYS + output wire sys_op_nop_o, + output wire sys_op_mret_o, + output wire sys_op_ecall_o, + output wire sys_op_ebreak_o, + output wire sys_op_fence_o + + ); + + wire[`DECINFO_GRP_WIDTH-1:0] disp_info_grp = dec_info_bus_i[`DECINFO_GRP_BUS]; + + // ALU info + wire op_alu = (disp_info_grp == `DECINFO_GRP_ALU); + wire[`DECINFO_WIDTH-1:0] alu_info = {`DECINFO_WIDTH{op_alu}} & dec_info_bus_i; + // ALU op1 + wire alu_op1_pc = alu_info[`DECINFO_ALU_OP1PC]; + wire alu_op1_zero = alu_info[`DECINFO_ALU_LUI]; + wire[31:0] alu_op1 = alu_op1_pc? dec_pc_i: alu_op1_zero? 32'h0: rs1_rdata_i; + assign alu_op1_o = op_alu? alu_op1: 32'h0; + // ALU op2 + wire alu_op2_imm = alu_info[`DECINFO_ALU_OP2IMM]; + wire[31:0] alu_op2 = alu_op2_imm? dec_imm_i: rs2_rdata_i; + assign alu_op2_o = op_alu? alu_op2: 32'h0; + assign alu_op_lui_o = alu_info[`DECINFO_ALU_LUI]; + assign alu_op_auipc_o = alu_info[`DECINFO_ALU_AUIPC]; + assign alu_op_add_o = alu_info[`DECINFO_ALU_ADD]; + assign alu_op_sub_o = alu_info[`DECINFO_ALU_SUB]; + assign alu_op_sll_o = alu_info[`DECINFO_ALU_SLL]; + assign alu_op_slt_o = alu_info[`DECINFO_ALU_SLT]; + assign alu_op_sltu_o = alu_info[`DECINFO_ALU_SLTU]; + assign alu_op_xor_o = alu_info[`DECINFO_ALU_XOR]; + assign alu_op_srl_o = alu_info[`DECINFO_ALU_SRL]; + assign alu_op_sra_o = alu_info[`DECINFO_ALU_SRA]; + assign alu_op_or_o = alu_info[`DECINFO_ALU_OR]; + assign alu_op_and_o = alu_info[`DECINFO_ALU_AND]; + assign req_alu_o = op_alu; + + // BJP info + wire op_bjp = (disp_info_grp == `DECINFO_GRP_BJP); + wire[`DECINFO_WIDTH-1:0] bjp_info = {`DECINFO_WIDTH{op_bjp}} & dec_info_bus_i; + // BJP op1 + wire bjp_op1_rs1 = bjp_info[`DECINFO_BJP_OP1RS1]; + wire[31:0] bjp_op1 = bjp_op1_rs1? rs1_rdata_i: dec_pc_i; + assign bjp_jump_op1_o = op_bjp? bjp_op1: 32'h0; + // BJP op2 + wire[31:0] bjp_op2 = dec_imm_i; + assign bjp_jump_op2_o = op_bjp? bjp_op2: 32'h0; + assign bjp_op1_o = op_bjp? rs1_rdata_i: 32'h0; + assign bjp_op2_o = op_bjp? rs2_rdata_i: 32'h0; + assign bjp_op_jump_o = bjp_info[`DECINFO_BJP_JUMP]; + assign bjp_op_beq_o = bjp_info[`DECINFO_BJP_BEQ]; + assign bjp_op_bne_o = bjp_info[`DECINFO_BJP_BNE]; + assign bjp_op_blt_o = bjp_info[`DECINFO_BJP_BLT]; + assign bjp_op_bltu_o = bjp_info[`DECINFO_BJP_BLTU]; + assign bjp_op_bge_o = bjp_info[`DECINFO_BJP_BGE]; + assign bjp_op_bgeu_o = bjp_info[`DECINFO_BJP_BGEU]; + assign req_bjp_o = op_bjp; + + // MULDIV info + wire op_muldiv = (disp_info_grp == `DECINFO_GRP_MULDIV); + wire[`DECINFO_WIDTH-1:0] muldiv_info = {`DECINFO_WIDTH{op_muldiv}} & dec_info_bus_i; + // MULDIV op1 + assign muldiv_op1_o = op_muldiv? rs1_rdata_i: 32'h0; + // MULDIV op2 + assign muldiv_op2_o = op_muldiv? rs2_rdata_i: 32'h0; + assign muldiv_op_mul_o = muldiv_info[`DECINFO_MULDIV_MUL]; + assign muldiv_op_mulh_o = muldiv_info[`DECINFO_MULDIV_MULH]; + assign muldiv_op_mulhu_o = muldiv_info[`DECINFO_MULDIV_MULHU]; + assign muldiv_op_mulhsu_o = muldiv_info[`DECINFO_MULDIV_MULHSU]; + assign muldiv_op_div_o = muldiv_info[`DECINFO_MULDIV_DIV]; + assign muldiv_op_divu_o = muldiv_info[`DECINFO_MULDIV_DIVU]; + assign muldiv_op_rem_o = muldiv_info[`DECINFO_MULDIV_REM]; + assign muldiv_op_remu_o = muldiv_info[`DECINFO_MULDIV_REMU]; + assign req_muldiv_o = op_muldiv; + + // CSR info + wire op_csr = (disp_info_grp == `DECINFO_GRP_CSR); + wire[`DECINFO_WIDTH-1:0] csr_info = {`DECINFO_WIDTH{op_csr}} & dec_info_bus_i; + // CSR op1 + wire csr_rs1imm = csr_info[`DECINFO_CSR_RS1IMM]; + wire[31:0] csr_rs1 = csr_rs1imm? dec_imm_i: rs1_rdata_i; + assign csr_op1_o = op_csr? csr_rs1: 32'h0; + assign csr_addr_o = {{20{1'b0}}, csr_info[`DECINFO_CSR_CSRADDR]}; + assign csr_csrrw_o = csr_info[`DECINFO_CSR_CSRRW]; + assign csr_csrrs_o = csr_info[`DECINFO_CSR_CSRRS]; + assign csr_csrrc_o = csr_info[`DECINFO_CSR_CSRRC]; + assign req_csr_o = op_csr; + + // MEM info + wire op_mem = (disp_info_grp == `DECINFO_GRP_MEM); + wire[`DECINFO_WIDTH-1:0] mem_info = {`DECINFO_WIDTH{op_mem}} & dec_info_bus_i; + assign mem_op_lb_o = mem_info[`DECINFO_MEM_LB]; + assign mem_op_lh_o = mem_info[`DECINFO_MEM_LH]; + assign mem_op_lw_o = mem_info[`DECINFO_MEM_LW]; + assign mem_op_lbu_o = mem_info[`DECINFO_MEM_LBU]; + assign mem_op_lhu_o = mem_info[`DECINFO_MEM_LHU]; + assign mem_op_sb_o = mem_info[`DECINFO_MEM_SB]; + assign mem_op_sh_o = mem_info[`DECINFO_MEM_SH]; + assign mem_op_sw_o = mem_info[`DECINFO_MEM_SW]; + assign mem_op1_o = op_mem? rs1_rdata_i: 32'h0; + assign mem_op2_o = op_mem? dec_imm_i: 32'h0; + assign mem_rs2_data_o = op_mem? rs2_rdata_i: 32'h0; + assign req_mem_o = op_mem; + + // SYS info + wire op_sys = (disp_info_grp == `DECINFO_GRP_SYS); + wire[`DECINFO_WIDTH-1:0] sys_info = {`DECINFO_WIDTH{op_sys}} & dec_info_bus_i; + assign sys_op_nop_o = sys_info[`DECINFO_SYS_NOP]; + assign sys_op_mret_o = sys_info[`DECINFO_SYS_MRET]; + assign sys_op_ecall_o = sys_info[`DECINFO_SYS_ECALL]; + assign sys_op_ebreak_o = sys_info[`DECINFO_SYS_EBREAK]; + assign sys_op_fence_o = sys_info[`DECINFO_SYS_FENCE]; + +endmodule diff --git a/rtl/core/exu_mem.sv b/rtl/core/exu_mem.sv index 2a16784..ba794b6 100644 --- a/rtl/core/exu_mem.sv +++ b/rtl/core/exu_mem.sv @@ -1,162 +1,162 @@ - /* - Copyright 2020 Blue Liang, liangkangnan@163.com - - 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. - */ - -`include "defines.sv" - - -module exu_mem( - - input wire clk, - input wire rst_n, - - input req_mem_i, - input wire[31:0] mem_addr_i, - input wire[31:0] mem_rs2_data_i, - input wire[31:0] mem_rdata_i, - input wire mem_req_ready_i, - input wire mem_rsp_valid_i, - input wire mem_op_lb_i, - input wire mem_op_lh_i, - input wire mem_op_lw_i, - input wire mem_op_lbu_i, - input wire mem_op_lhu_i, - input wire mem_op_sb_i, - input wire mem_op_sh_i, - input wire mem_op_sw_i, - - output wire mem_access_misaligned_o, - output wire mem_stall_o, - output wire[31:0] mem_addr_o, - output wire[31:0] mem_wdata_o, - output wire mem_reg_we_o, - output wire mem_mem_we_o, - output wire[3:0] mem_sel_o, - output wire mem_req_valid_o, - output wire mem_rsp_ready_o - - ); - - - wire[1:0] mem_addr_index = mem_addr_i[1:0]; - wire mem_addr_index00 = (mem_addr_index == 2'b00); - wire mem_addr_index01 = (mem_addr_index == 2'b01); - wire mem_addr_index10 = (mem_addr_index == 2'b10); - wire mem_addr_index11 = (mem_addr_index == 2'b11); - - assign mem_sel_o[0] = mem_addr_index00 | mem_op_sw_i; - assign mem_sel_o[1] = mem_addr_index01 | (mem_op_sh_i & mem_addr_index00) | mem_op_sw_i; - assign mem_sel_o[2] = mem_addr_index10 | mem_op_sw_i; - assign mem_sel_o[3] = mem_addr_index11 | (mem_op_sh_i & mem_addr_index10) | mem_op_sw_i; - - reg[31:0] sb_res; - - always @ (*) begin - sb_res = 32'h0; - case (1'b1) - mem_addr_index00: sb_res = {24'h0, mem_rs2_data_i[7:0]}; - mem_addr_index01: sb_res = {16'h0, mem_rs2_data_i[7:0], 8'h0}; - mem_addr_index10: sb_res = {8'h0, mem_rs2_data_i[7:0], 16'h0}; - mem_addr_index11: sb_res = {mem_rs2_data_i[7:0], 24'h0}; - endcase - end - - reg[31:0] sh_res; - - always @ (*) begin - sh_res = 32'h0; - case (1'b1) - mem_addr_index00: sh_res = {16'h0, mem_rs2_data_i[15:0]}; - mem_addr_index10: sh_res = {mem_rs2_data_i[15:0], 16'h0}; - endcase - end - - wire[31:0] sw_res = mem_rs2_data_i; - - reg[31:0] lb_res; - - always @ (*) begin - lb_res = 32'h0; - case (1'b1) - mem_addr_index00: lb_res = {{24{mem_op_lb_i & mem_rdata_i[7]}}, mem_rdata_i[7:0]}; - mem_addr_index01: lb_res = {{24{mem_op_lb_i & mem_rdata_i[15]}}, mem_rdata_i[15:8]}; - mem_addr_index10: lb_res = {{24{mem_op_lb_i & mem_rdata_i[23]}}, mem_rdata_i[23:16]}; - mem_addr_index11: lb_res = {{24{mem_op_lb_i & mem_rdata_i[31]}}, mem_rdata_i[31:24]}; - endcase - end - - reg[31:0] lh_res; - - always @ (*) begin - lh_res = 32'h0; - case (1'b1) - mem_addr_index00: lh_res = {{24{mem_op_lh_i & mem_rdata_i[15]}}, mem_rdata_i[15:0]}; - mem_addr_index10: lh_res = {{24{mem_op_lh_i & mem_rdata_i[31]}}, mem_rdata_i[31:16]}; - endcase - end - - wire[31:0] lw_res = mem_rdata_i; - - reg[31:0] mem_wdata; - - always @ (*) begin - mem_wdata = 32'h0; - case (1'b1) - mem_op_sb_i: mem_wdata = sb_res; - mem_op_sh_i: mem_wdata = sh_res; - mem_op_sw_i: mem_wdata = sw_res; - mem_op_lb_i: mem_wdata = lb_res; - mem_op_lbu_i: mem_wdata = lb_res; - mem_op_lh_i: mem_wdata = lh_res; - mem_op_lhu_i: mem_wdata = lh_res; - mem_op_lw_i: mem_wdata = lw_res; - endcase - end - - assign mem_wdata_o = mem_wdata; - - wire mem_req_hsked = (mem_req_valid_o & mem_req_ready_i); - wire mem_rsp_hsked = (mem_rsp_valid_i & mem_rsp_ready_o); - - reg mem_rsp_hsked_r; - - always @ (posedge clk or negedge rst_n) begin - if (!rst_n) begin - mem_rsp_hsked_r <= 1'b0; - end else begin - mem_rsp_hsked_r <= mem_rsp_hsked & (~mem_rsp_hsked_r); - end - end - - assign mem_rsp_ready_o = 1'b1; - - // 璇锋眰璁块棶鎬荤嚎 - assign mem_req_valid_o = req_mem_i; - // 鏆傚仠娴佹按绾 - assign mem_stall_o = req_mem_i & (~mem_rsp_hsked_r); - // 璇汇佸啓鍐呭瓨鍦板潃 - assign mem_addr_o = mem_addr_i; - - // 鍐欏瘎瀛樺櫒浣胯兘锛屾敹鍒癮ck鏃舵暟鎹墠鏈夋晥 - assign mem_reg_we_o = (mem_op_lb_i | mem_op_lh_i | mem_op_lw_i | mem_op_lbu_i | mem_op_lhu_i) & mem_rsp_hsked_r; - - // 鍐欏唴瀛樹娇鑳 - assign mem_mem_we_o = (mem_op_sb_i | mem_op_sh_i | mem_op_sw_i) & mem_rsp_hsked_r; - - assign mem_access_misaligned_o = (mem_op_sw_i | mem_op_lw_i)? (mem_addr_i[0] | mem_addr_i[1]): - (mem_op_sh_i | mem_op_lh_i | mem_op_lhu_i)? mem_addr_i[0]: - 0; - -endmodule + /* + Copyright 2020 Blue Liang, liangkangnan@163.com + + 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. + */ + +`include "defines.sv" + + +module exu_mem( + + input wire clk, + input wire rst_n, + + input req_mem_i, + input wire[31:0] mem_addr_i, + input wire[31:0] mem_rs2_data_i, + input wire[31:0] mem_rdata_i, + input wire mem_req_ready_i, + input wire mem_rsp_valid_i, + input wire mem_op_lb_i, + input wire mem_op_lh_i, + input wire mem_op_lw_i, + input wire mem_op_lbu_i, + input wire mem_op_lhu_i, + input wire mem_op_sb_i, + input wire mem_op_sh_i, + input wire mem_op_sw_i, + + output wire mem_access_misaligned_o, + output wire mem_stall_o, + output wire[31:0] mem_addr_o, + output wire[31:0] mem_wdata_o, + output wire mem_reg_we_o, + output wire mem_mem_we_o, + output wire[3:0] mem_sel_o, + output wire mem_req_valid_o, + output wire mem_rsp_ready_o + + ); + + + wire[1:0] mem_addr_index = mem_addr_i[1:0]; + wire mem_addr_index00 = (mem_addr_index == 2'b00); + wire mem_addr_index01 = (mem_addr_index == 2'b01); + wire mem_addr_index10 = (mem_addr_index == 2'b10); + wire mem_addr_index11 = (mem_addr_index == 2'b11); + + assign mem_sel_o[0] = mem_addr_index00 | mem_op_sw_i; + assign mem_sel_o[1] = mem_addr_index01 | (mem_op_sh_i & mem_addr_index00) | mem_op_sw_i; + assign mem_sel_o[2] = mem_addr_index10 | mem_op_sw_i; + assign mem_sel_o[3] = mem_addr_index11 | (mem_op_sh_i & mem_addr_index10) | mem_op_sw_i; + + reg[31:0] sb_res; + + always @ (*) begin + sb_res = 32'h0; + case (1'b1) + mem_addr_index00: sb_res = {24'h0, mem_rs2_data_i[7:0]}; + mem_addr_index01: sb_res = {16'h0, mem_rs2_data_i[7:0], 8'h0}; + mem_addr_index10: sb_res = {8'h0, mem_rs2_data_i[7:0], 16'h0}; + mem_addr_index11: sb_res = {mem_rs2_data_i[7:0], 24'h0}; + endcase + end + + reg[31:0] sh_res; + + always @ (*) begin + sh_res = 32'h0; + case (1'b1) + mem_addr_index00: sh_res = {16'h0, mem_rs2_data_i[15:0]}; + mem_addr_index10: sh_res = {mem_rs2_data_i[15:0], 16'h0}; + endcase + end + + wire[31:0] sw_res = mem_rs2_data_i; + + reg[31:0] lb_res; + + always @ (*) begin + lb_res = 32'h0; + case (1'b1) + mem_addr_index00: lb_res = {{24{mem_op_lb_i & mem_rdata_i[7]}}, mem_rdata_i[7:0]}; + mem_addr_index01: lb_res = {{24{mem_op_lb_i & mem_rdata_i[15]}}, mem_rdata_i[15:8]}; + mem_addr_index10: lb_res = {{24{mem_op_lb_i & mem_rdata_i[23]}}, mem_rdata_i[23:16]}; + mem_addr_index11: lb_res = {{24{mem_op_lb_i & mem_rdata_i[31]}}, mem_rdata_i[31:24]}; + endcase + end + + reg[31:0] lh_res; + + always @ (*) begin + lh_res = 32'h0; + case (1'b1) + mem_addr_index00: lh_res = {{24{mem_op_lh_i & mem_rdata_i[15]}}, mem_rdata_i[15:0]}; + mem_addr_index10: lh_res = {{24{mem_op_lh_i & mem_rdata_i[31]}}, mem_rdata_i[31:16]}; + endcase + end + + wire[31:0] lw_res = mem_rdata_i; + + reg[31:0] mem_wdata; + + always @ (*) begin + mem_wdata = 32'h0; + case (1'b1) + mem_op_sb_i: mem_wdata = sb_res; + mem_op_sh_i: mem_wdata = sh_res; + mem_op_sw_i: mem_wdata = sw_res; + mem_op_lb_i: mem_wdata = lb_res; + mem_op_lbu_i: mem_wdata = lb_res; + mem_op_lh_i: mem_wdata = lh_res; + mem_op_lhu_i: mem_wdata = lh_res; + mem_op_lw_i: mem_wdata = lw_res; + endcase + end + + assign mem_wdata_o = mem_wdata; + + wire mem_req_hsked = (mem_req_valid_o & mem_req_ready_i); + wire mem_rsp_hsked = (mem_rsp_valid_i & mem_rsp_ready_o); + + reg mem_rsp_hsked_r; + + always @ (posedge clk or negedge rst_n) begin + if (!rst_n) begin + mem_rsp_hsked_r <= 1'b0; + end else begin + mem_rsp_hsked_r <= mem_rsp_hsked & (~mem_rsp_hsked_r); + end + end + + assign mem_rsp_ready_o = 1'b1; + + // 璇锋眰璁块棶鎬荤嚎 + assign mem_req_valid_o = req_mem_i; + // 鏆傚仠娴佹按绾 + assign mem_stall_o = req_mem_i & (~mem_rsp_hsked_r); + // 璇汇佸啓鍐呭瓨鍦板潃 + assign mem_addr_o = mem_addr_i; + + // 鍐欏瘎瀛樺櫒浣胯兘锛屾敹鍒癮ck鏃舵暟鎹墠鏈夋晥 + assign mem_reg_we_o = (mem_op_lb_i | mem_op_lh_i | mem_op_lw_i | mem_op_lbu_i | mem_op_lhu_i) & mem_rsp_hsked_r; + + // 鍐欏唴瀛樹娇鑳 + assign mem_mem_we_o = (mem_op_sb_i | mem_op_sh_i | mem_op_sw_i) & mem_rsp_hsked_r; + + assign mem_access_misaligned_o = (mem_op_sw_i | mem_op_lw_i)? (mem_addr_i[0] | mem_addr_i[1]): + (mem_op_sh_i | mem_op_lh_i | mem_op_lhu_i)? mem_addr_i[0]: + 0; + +endmodule diff --git a/rtl/core/exu_muldiv.sv b/rtl/core/exu_muldiv.sv index a3c0873..cda79a3 100644 --- a/rtl/core/exu_muldiv.sv +++ b/rtl/core/exu_muldiv.sv @@ -1,106 +1,106 @@ - /* - Copyright 2020 Blue Liang, liangkangnan@163.com - - 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. - */ - -`include "defines.sv" - - -module exu_muldiv( - - input wire clk, - input wire rst_n, - - input wire[31:0] muldiv_op1_i, - input wire[31:0] muldiv_op2_i, - input wire muldiv_op_mul_i, - input wire muldiv_op_mulh_i, - input wire muldiv_op_mulhsu_i, - input wire muldiv_op_mulhu_i, - input wire muldiv_op_div_i, - input wire muldiv_op_divu_i, - input wire muldiv_op_rem_i, - input wire muldiv_op_remu_i, - - output wire[31:0] muldiv_reg_wdata_o, - output wire muldiv_reg_we_o, - output wire muldiv_stall_o - - ); - - // 闄ゆ硶鎿嶄綔 - wire op_div = muldiv_op_div_i | muldiv_op_divu_i | muldiv_op_rem_i | muldiv_op_remu_i; - wire div_start = op_div & (!div_ready); - wire[3:0] div_op = {muldiv_op_div_i, muldiv_op_divu_i, muldiv_op_rem_i, muldiv_op_remu_i}; - wire[31:0] div_result; - wire div_ready; - - divider u_divider( - .clk(clk), - .rst_n(rst_n), - .dividend_i(muldiv_op1_i), - .divisor_i(muldiv_op2_i), - .start_i(div_start), - .op_i(div_op), - .result_o(div_result), - .ready_o(div_ready) - ); - - // 涔樻硶鎿嶄綔 - wire op_mul = muldiv_op_mul_i | muldiv_op_mulh_i | muldiv_op_mulhsu_i | muldiv_op_mulhu_i; - wire[31:0] muldiv_op1_r; - gen_en_dff #(32) mul_op1_ff(clk, rst_n, op_mul, muldiv_op1_i, muldiv_op1_r); - wire[31:0] muldiv_op2_r; - gen_en_dff #(32) mul_op2_ff(clk, rst_n, op_mul, muldiv_op2_i, muldiv_op2_r); - - wire mul_ready_r; - wire mul_ready = (~mul_ready_r) & op_mul; - gen_rst_0_dff #(1) mul_ready_ff(clk, rst_n, mul_ready, mul_ready_r); - - wire mul_start = (~mul_ready_r) & op_mul; - - wire op1_is_signed = muldiv_op1_r[31]; - wire op2_is_signed = muldiv_op2_r[31]; - wire[31:0] op1_complcode = op1_is_signed? (-muldiv_op1_r): muldiv_op1_r; - wire[31:0] op2_complcode = op2_is_signed? (-muldiv_op2_r): muldiv_op2_r; - - wire[31:0] op1_mul = ({32{(muldiv_op_mul_i | muldiv_op_mulhu_i)}} & muldiv_op1_r) | - ({32{(muldiv_op_mulh_i | muldiv_op_mulhsu_i)}} & op1_complcode); - wire[31:0] op2_mul = ({32{(muldiv_op_mul_i | muldiv_op_mulhu_i | muldiv_op_mulhsu_i)}} & muldiv_op2_r) | - ({32{(muldiv_op_mulh_i)}} & op2_complcode); - wire[63:0] mul_res_tmp = op1_mul * op2_mul; - wire[63:0] mul_res_tmp_complcode = -mul_res_tmp; - wire[31:0] mul_res = mul_res_tmp[31:0]; - wire[31:0] mulhu_res = mul_res_tmp[63:32]; - wire[31:0] mulh_res = (op1_is_signed ^ op2_is_signed)? mul_res_tmp_complcode[63:32]: mul_res_tmp[63:32]; - wire[31:0] mulhsu_res = (op1_is_signed)? mul_res_tmp_complcode[63:32]: mul_res_tmp[63:32]; - - reg[31:0] mul_op_res; - - always @ (*) begin - mul_op_res = 32'h0; - case (1'b1) - muldiv_op_mul_i: mul_op_res = mul_res; - muldiv_op_mulhu_i: mul_op_res = mulhu_res; - muldiv_op_mulh_i: mul_op_res = mulh_res; - muldiv_op_mulhsu_i: mul_op_res = mulhsu_res; - endcase - end - - // 杩愮畻缁撴灉 - assign muldiv_reg_wdata_o = div_result | mul_op_res; - assign muldiv_reg_we_o = div_ready | mul_ready_r; - assign muldiv_stall_o = div_start | mul_start; - -endmodule + /* + Copyright 2020 Blue Liang, liangkangnan@163.com + + 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. + */ + +`include "defines.sv" + + +module exu_muldiv( + + input wire clk, + input wire rst_n, + + input wire[31:0] muldiv_op1_i, + input wire[31:0] muldiv_op2_i, + input wire muldiv_op_mul_i, + input wire muldiv_op_mulh_i, + input wire muldiv_op_mulhsu_i, + input wire muldiv_op_mulhu_i, + input wire muldiv_op_div_i, + input wire muldiv_op_divu_i, + input wire muldiv_op_rem_i, + input wire muldiv_op_remu_i, + + output wire[31:0] muldiv_reg_wdata_o, + output wire muldiv_reg_we_o, + output wire muldiv_stall_o + + ); + + // 闄ゆ硶鎿嶄綔 + wire op_div = muldiv_op_div_i | muldiv_op_divu_i | muldiv_op_rem_i | muldiv_op_remu_i; + wire div_start = op_div & (!div_ready); + wire[3:0] div_op = {muldiv_op_div_i, muldiv_op_divu_i, muldiv_op_rem_i, muldiv_op_remu_i}; + wire[31:0] div_result; + wire div_ready; + + divider u_divider( + .clk(clk), + .rst_n(rst_n), + .dividend_i(muldiv_op1_i), + .divisor_i(muldiv_op2_i), + .start_i(div_start), + .op_i(div_op), + .result_o(div_result), + .ready_o(div_ready) + ); + + // 涔樻硶鎿嶄綔 + wire op_mul = muldiv_op_mul_i | muldiv_op_mulh_i | muldiv_op_mulhsu_i | muldiv_op_mulhu_i; + wire[31:0] muldiv_op1_r; + gen_en_dff #(32) mul_op1_ff(clk, rst_n, op_mul, muldiv_op1_i, muldiv_op1_r); + wire[31:0] muldiv_op2_r; + gen_en_dff #(32) mul_op2_ff(clk, rst_n, op_mul, muldiv_op2_i, muldiv_op2_r); + + wire mul_ready_r; + wire mul_ready = (~mul_ready_r) & op_mul; + gen_rst_0_dff #(1) mul_ready_ff(clk, rst_n, mul_ready, mul_ready_r); + + wire mul_start = (~mul_ready_r) & op_mul; + + wire op1_is_signed = muldiv_op1_r[31]; + wire op2_is_signed = muldiv_op2_r[31]; + wire[31:0] op1_complcode = op1_is_signed? (-muldiv_op1_r): muldiv_op1_r; + wire[31:0] op2_complcode = op2_is_signed? (-muldiv_op2_r): muldiv_op2_r; + + wire[31:0] op1_mul = ({32{(muldiv_op_mul_i | muldiv_op_mulhu_i)}} & muldiv_op1_r) | + ({32{(muldiv_op_mulh_i | muldiv_op_mulhsu_i)}} & op1_complcode); + wire[31:0] op2_mul = ({32{(muldiv_op_mul_i | muldiv_op_mulhu_i | muldiv_op_mulhsu_i)}} & muldiv_op2_r) | + ({32{(muldiv_op_mulh_i)}} & op2_complcode); + wire[63:0] mul_res_tmp = op1_mul * op2_mul; + wire[63:0] mul_res_tmp_complcode = -mul_res_tmp; + wire[31:0] mul_res = mul_res_tmp[31:0]; + wire[31:0] mulhu_res = mul_res_tmp[63:32]; + wire[31:0] mulh_res = (op1_is_signed ^ op2_is_signed)? mul_res_tmp_complcode[63:32]: mul_res_tmp[63:32]; + wire[31:0] mulhsu_res = (op1_is_signed)? mul_res_tmp_complcode[63:32]: mul_res_tmp[63:32]; + + reg[31:0] mul_op_res; + + always @ (*) begin + mul_op_res = 32'h0; + case (1'b1) + muldiv_op_mul_i: mul_op_res = mul_res; + muldiv_op_mulhu_i: mul_op_res = mulhu_res; + muldiv_op_mulh_i: mul_op_res = mulh_res; + muldiv_op_mulhsu_i: mul_op_res = mulhsu_res; + endcase + end + + // 杩愮畻缁撴灉 + assign muldiv_reg_wdata_o = div_result | mul_op_res; + assign muldiv_reg_we_o = div_ready | mul_ready_r; + assign muldiv_stall_o = div_start | mul_start; + +endmodule diff --git a/rtl/core/gpr_reg.sv b/rtl/core/gpr_reg.sv index 885f518..79e0390 100644 --- a/rtl/core/gpr_reg.sv +++ b/rtl/core/gpr_reg.sv @@ -1,92 +1,92 @@ - /* - Copyright 2019 Blue Liang, liangkangnan@163.com - - 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. - */ - -`include "defines.sv" - -// 閫氱敤瀵勫瓨鍣ㄦā鍧 -module gpr_reg( - - input wire clk, - input wire rst_n, - - input wire we_i, // 鍐欏瘎瀛樺櫒浣胯兘 - input wire[4:0] waddr_i, // 鍐欏瘎瀛樺櫒鍦板潃 - input wire[31:0] wdata_i, // 鍐欏瘎瀛樺櫒鏁版嵁 - - input wire[4:0] raddr1_i, // 璇诲瘎瀛樺櫒1鍦板潃 - output wire[31:0] rdata1_o, // 璇诲瘎瀛樺櫒1鏁版嵁 - - input wire[4:0] raddr2_i, // 璇诲瘎瀛樺櫒2鍦板潃 - output wire[31:0] rdata2_o // 璇诲瘎瀛樺櫒2鏁版嵁 - - ); - - wire[32-1:0] regs[32-1:0]; - wire[32-1:0] we; - - genvar i; - - generate - for (i = 0; i < 32; i = i + 1) begin: gpr_rw - // x0 cannot be wrote since it is constant-zeros - if (i == 0) begin: is_x0 - assign we[i] = 1'b0; - assign regs[i] = 32'h0; - end else begin: not_x0 - assign we[i] = we_i & (waddr_i == i); - gen_en_dffnr #(32) rf_dff(clk, we[i], wdata_i, regs[i]); - end - end - endgenerate - - assign rdata1_o = (|raddr1_i)? ((we_i & (waddr_i == raddr1_i))? wdata_i: regs[raddr1_i]): 32'h0; - assign rdata2_o = (|raddr2_i)? ((we_i & (waddr_i == raddr2_i))? wdata_i: regs[raddr2_i]): 32'h0; - - // for debug - wire[31:0] ra = regs[1]; - wire[31:0] sp = regs[2]; - wire[31:0] gp = regs[3]; - wire[31:0] tp = regs[4]; - wire[31:0] t0 = regs[5]; - wire[31:0] t1 = regs[6]; - wire[31:0] t2 = regs[7]; - wire[31:0] s0 = regs[8]; - wire[31:0] fp = regs[8]; - wire[31:0] s1 = regs[9]; - wire[31:0] a0 = regs[10]; - wire[31:0] a1 = regs[11]; - wire[31:0] a2 = regs[12]; - wire[31:0] a3 = regs[13]; - wire[31:0] a4 = regs[14]; - wire[31:0] a5 = regs[15]; - wire[31:0] a6 = regs[16]; - wire[31:0] a7 = regs[17]; - wire[31:0] s2 = regs[18]; - wire[31:0] s3 = regs[19]; - wire[31:0] s4 = regs[20]; - wire[31:0] s5 = regs[21]; - wire[31:0] s6 = regs[22]; - wire[31:0] s7 = regs[23]; - wire[31:0] s8 = regs[24]; - wire[31:0] s9 = regs[25]; - wire[31:0] s10 = regs[26]; - wire[31:0] s11 = regs[27]; - wire[31:0] t3 = regs[28]; - wire[31:0] t4 = regs[29]; - wire[31:0] t5 = regs[30]; - wire[31:0] t6 = regs[31]; - -endmodule + /* + Copyright 2019 Blue Liang, liangkangnan@163.com + + 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. + */ + +`include "defines.sv" + +// 閫氱敤瀵勫瓨鍣ㄦā鍧 +module gpr_reg( + + input wire clk, + input wire rst_n, + + input wire we_i, // 鍐欏瘎瀛樺櫒浣胯兘 + input wire[4:0] waddr_i, // 鍐欏瘎瀛樺櫒鍦板潃 + input wire[31:0] wdata_i, // 鍐欏瘎瀛樺櫒鏁版嵁 + + input wire[4:0] raddr1_i, // 璇诲瘎瀛樺櫒1鍦板潃 + output wire[31:0] rdata1_o, // 璇诲瘎瀛樺櫒1鏁版嵁 + + input wire[4:0] raddr2_i, // 璇诲瘎瀛樺櫒2鍦板潃 + output wire[31:0] rdata2_o // 璇诲瘎瀛樺櫒2鏁版嵁 + + ); + + wire[32-1:0] regs[32-1:0]; + wire[32-1:0] we; + + genvar i; + + generate + for (i = 0; i < 32; i = i + 1) begin: gpr_rw + // x0 cannot be wrote since it is constant-zeros + if (i == 0) begin: is_x0 + assign we[i] = 1'b0; + assign regs[i] = 32'h0; + end else begin: not_x0 + assign we[i] = we_i & (waddr_i == i); + gen_en_dffnr #(32) rf_dff(clk, we[i], wdata_i, regs[i]); + end + end + endgenerate + + assign rdata1_o = (|raddr1_i)? ((we_i & (waddr_i == raddr1_i))? wdata_i: regs[raddr1_i]): 32'h0; + assign rdata2_o = (|raddr2_i)? ((we_i & (waddr_i == raddr2_i))? wdata_i: regs[raddr2_i]): 32'h0; + + // for debug + wire[31:0] ra = regs[1]; + wire[31:0] sp = regs[2]; + wire[31:0] gp = regs[3]; + wire[31:0] tp = regs[4]; + wire[31:0] t0 = regs[5]; + wire[31:0] t1 = regs[6]; + wire[31:0] t2 = regs[7]; + wire[31:0] s0 = regs[8]; + wire[31:0] fp = regs[8]; + wire[31:0] s1 = regs[9]; + wire[31:0] a0 = regs[10]; + wire[31:0] a1 = regs[11]; + wire[31:0] a2 = regs[12]; + wire[31:0] a3 = regs[13]; + wire[31:0] a4 = regs[14]; + wire[31:0] a5 = regs[15]; + wire[31:0] a6 = regs[16]; + wire[31:0] a7 = regs[17]; + wire[31:0] s2 = regs[18]; + wire[31:0] s3 = regs[19]; + wire[31:0] s4 = regs[20]; + wire[31:0] s5 = regs[21]; + wire[31:0] s6 = regs[22]; + wire[31:0] s7 = regs[23]; + wire[31:0] s8 = regs[24]; + wire[31:0] s9 = regs[25]; + wire[31:0] s10 = regs[26]; + wire[31:0] s11 = regs[27]; + wire[31:0] t3 = regs[28]; + wire[31:0] t4 = regs[29]; + wire[31:0] t5 = regs[30]; + wire[31:0] t6 = regs[31]; + +endmodule diff --git a/rtl/core/idu.sv b/rtl/core/idu.sv index 8ca9b17..31016d6 100644 --- a/rtl/core/idu.sv +++ b/rtl/core/idu.sv @@ -1,303 +1,303 @@ - /* - Copyright 2019 Blue Liang, liangkangnan@163.com - - 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. - */ - -`include "defines.sv" - -// 璇戠爜妯″潡 -// 绾粍鍚堥昏緫鐢佃矾 -module idu( - - input wire clk, - input wire rst_n, - - // from if_id - input wire[31:0] inst_i, // 鎸囦护鍐呭 - input wire[31:0] inst_addr_i, // 鎸囦护鍦板潃 - - // from gpr_reg - input wire[31:0] rs1_rdata_i, // 閫氱敤瀵勫瓨鍣1杈撳叆鏁版嵁 - input wire[31:0] rs2_rdata_i, // 閫氱敤瀵勫瓨鍣2杈撳叆鏁版嵁 - - output wire stall_o, - - // to id_ex - output wire[31:0] inst_o, - output wire[`DECINFO_WIDTH-1:0] dec_info_bus_o, - output wire[31:0] dec_imm_o, - output wire[31:0] dec_pc_o, - output wire[4:0] rs1_raddr_o, - output wire[4:0] rs2_raddr_o, - output wire[31:0] rs1_rdata_o, - output wire[31:0] rs2_rdata_o, - output wire[4:0] rd_waddr_o, - output wire rd_we_o - - ); - - assign inst_o = inst_i; - assign rs1_rdata_o = rs1_rdata_i; - assign rs2_rdata_o = rs2_rdata_i; - - // 鍙栧嚭鎸囦护涓殑姣忎竴涓煙 - wire[6:0] opcode = inst_i[6:0]; - wire[2:0] funct3 = inst_i[14:12]; - wire[6:0] funct7 = inst_i[31:25]; - wire[4:0] rd = inst_i[11:7]; - wire[4:0] rs1 = inst_i[19:15]; - wire[4:0] rs2 = inst_i[24:20]; - wire[11:0] type_i_imm_11_0 = inst_i[31:20]; - wire[6:0] type_s_imm_11_5 = inst_i[31:25]; - wire[4:0] type_s_imm_4_0 = inst_i[11:7]; - wire[6:0] type_b_imm_12_10_5 = inst_i[31:25]; - wire[4:0] type_b_imm_4_1_11 = inst_i[11:7]; - wire[19:0] type_u_imm_31_12 = inst_i[31:12]; - wire[19:0] type_j_imm_31_12 = inst_i[31:12]; - - // 鎸囦护opcode鍩熺殑鍙栧 - wire opcode_0110111 = (opcode == 7'b0110111); - wire opcode_0010111 = (opcode == 7'b0010111); - wire opcode_1101111 = (opcode == 7'b1101111); - wire opcode_1100111 = (opcode == 7'b1100111); - wire opcode_1100011 = (opcode == 7'b1100011); - wire opcode_0000011 = (opcode == 7'b0000011); - wire opcode_0100011 = (opcode == 7'b0100011); - wire opcode_0010011 = (opcode == 7'b0010011); - wire opcode_0110011 = (opcode == 7'b0110011); - wire opcode_0001111 = (opcode == 7'b0001111); - wire opcode_1110011 = (opcode == 7'b1110011); - - // 鎸囦护funct3鍩熺殑鍙栧 - wire funct3_000 = (funct3 == 3'b000); - wire funct3_001 = (funct3 == 3'b001); - wire funct3_010 = (funct3 == 3'b010); - wire funct3_011 = (funct3 == 3'b011); - wire funct3_100 = (funct3 == 3'b100); - wire funct3_101 = (funct3 == 3'b101); - wire funct3_110 = (funct3 == 3'b110); - wire funct3_111 = (funct3 == 3'b111); - - // 鎸囦护funct7鍩熺殑鍙栧 - wire funct7_0000000 = (funct7 == 7'b0000000); - wire funct7_0100000 = (funct7 == 7'b0100000); - wire funct7_0000001 = (funct7 == 7'b0000001); - - // I绫诲瀷鎸囦护imm鍩熺殑鍙栧 - wire type_i_imm_000000000000 = (type_i_imm_11_0 == 12'b000000000000); - wire type_i_imm_000000000001 = (type_i_imm_11_0 == 12'b000000000001); - - // 璇戠爜鍑哄叿浣撴寚浠 - wire inst_lui = opcode_0110111; - wire inst_auipc = opcode_0010111; - wire inst_jal = opcode_1101111; - wire inst_jalr = opcode_1100111 & funct3_000; - wire inst_beq = opcode_1100011 & funct3_000; - wire inst_bne = opcode_1100011 & funct3_001; - wire inst_blt = opcode_1100011 & funct3_100; - wire inst_bge = opcode_1100011 & funct3_101; - wire inst_bltu = opcode_1100011 & funct3_110; - wire inst_bgeu = opcode_1100011 & funct3_111; - wire inst_lb = opcode_0000011 & funct3_000; - wire inst_lh = opcode_0000011 & funct3_001; - wire inst_lw = opcode_0000011 & funct3_010; - wire inst_lbu = opcode_0000011 & funct3_100; - wire inst_lhu = opcode_0000011 & funct3_101; - wire inst_sb = opcode_0100011 & funct3_000; - wire inst_sh = opcode_0100011 & funct3_001; - wire inst_sw = opcode_0100011 & funct3_010; - wire inst_addi = opcode_0010011 & funct3_000; - wire inst_slti = opcode_0010011 & funct3_010; - wire inst_sltiu = opcode_0010011 & funct3_011; - wire inst_xori = opcode_0010011 & funct3_100; - wire inst_ori = opcode_0010011 & funct3_110; - wire inst_andi = opcode_0010011 & funct3_111; - wire inst_slli = opcode_0010011 & funct3_001 & funct7_0000000; - wire inst_srli = opcode_0010011 & funct3_101 & funct7_0000000; - wire inst_srai = opcode_0010011 & funct3_101 & funct7_0100000; - wire inst_add = opcode_0110011 & funct3_000 & funct7_0000000; - wire inst_sub = opcode_0110011 & funct3_000 & funct7_0100000; - wire inst_sll = opcode_0110011 & funct3_001 & funct7_0000000; - wire inst_slt = opcode_0110011 & funct3_010 & funct7_0000000; - wire inst_sltu = opcode_0110011 & funct3_011 & funct7_0000000; - wire inst_xor = opcode_0110011 & funct3_100 & funct7_0000000; - wire inst_srl = opcode_0110011 & funct3_101 & funct7_0000000; - wire inst_sra = opcode_0110011 & funct3_101 & funct7_0100000; - wire inst_or = opcode_0110011 & funct3_110 & funct7_0000000; - wire inst_and = opcode_0110011 & funct3_111 & funct7_0000000; - wire inst_fence = opcode_0001111 & funct3_000; - wire inst_ecall = (inst_i == `INST_ECALL); - wire inst_ebreak = (inst_i == `INST_EBREAK); - wire inst_fence_i = opcode_0001111 & funct3_001; - wire inst_csrrw = opcode_1110011 & funct3_001; - wire inst_csrrs = opcode_1110011 & funct3_010; - wire inst_csrrc = opcode_1110011 & funct3_011; - wire inst_csrrwi = opcode_1110011 & funct3_101; - wire inst_csrrsi = opcode_1110011 & funct3_110; - wire inst_csrrci = opcode_1110011 & funct3_111; - wire inst_mul = opcode_0110011 & funct3_000 & funct7_0000001; - wire inst_mulh = opcode_0110011 & funct3_001 & funct7_0000001; - wire inst_mulhsu = opcode_0110011 & funct3_010 & funct7_0000001; - wire inst_mulhu = opcode_0110011 & funct3_011 & funct7_0000001; - wire inst_div = opcode_0110011 & funct3_100 & funct7_0000001; - wire inst_divu = opcode_0110011 & funct3_101 & funct7_0000001; - wire inst_rem = opcode_0110011 & funct3_110 & funct7_0000001; - wire inst_remu = opcode_0110011 & funct3_111 & funct7_0000001; - wire inst_nop = (inst_i == `INST_NOP); - wire inst_mret = (inst_i == `INST_MRET); - - // 灏嗘寚浠ゅ垎绫 - wire inst_type_load = opcode_0000011; - wire inst_type_store = opcode_0100011; - wire inst_type_branch = opcode_1100011; - wire inst_type_muldiv = inst_mul | inst_mulh | inst_mulhsu | inst_mulhu | inst_div | inst_divu | inst_rem | inst_remu; - wire inst_type_div = inst_div | inst_divu | inst_rem | inst_remu; - - wire[`DECINFO_ALU_BUS_WIDTH-1:0] dec_alu_info_bus; - assign dec_alu_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_ALU; - assign dec_alu_info_bus[`DECINFO_ALU_LUI] = inst_lui; - assign dec_alu_info_bus[`DECINFO_ALU_AUIPC] = inst_auipc; - assign dec_alu_info_bus[`DECINFO_ALU_ADD] = inst_add | inst_addi; - assign dec_alu_info_bus[`DECINFO_ALU_SUB] = inst_sub; - assign dec_alu_info_bus[`DECINFO_ALU_SLL] = inst_sll | inst_slli; - assign dec_alu_info_bus[`DECINFO_ALU_SLT] = inst_slt | inst_slti; - assign dec_alu_info_bus[`DECINFO_ALU_SLTU] = inst_sltu | inst_sltiu; - assign dec_alu_info_bus[`DECINFO_ALU_XOR] = inst_xor | inst_xori; - assign dec_alu_info_bus[`DECINFO_ALU_SRL] = inst_srl | inst_srli; - assign dec_alu_info_bus[`DECINFO_ALU_SRA] = inst_sra | inst_srai; - assign dec_alu_info_bus[`DECINFO_ALU_OR] = inst_or | inst_ori; - assign dec_alu_info_bus[`DECINFO_ALU_AND] = inst_and | inst_andi; - assign dec_alu_info_bus[`DECINFO_ALU_OP2IMM] = opcode_0010011 | inst_lui | inst_auipc; - assign dec_alu_info_bus[`DECINFO_ALU_OP1PC] = inst_auipc; - - wire[`DECINFO_BJP_BUS_WIDTH-1:0] dec_bjp_info_bus; - assign dec_bjp_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_BJP; - assign dec_bjp_info_bus[`DECINFO_BJP_JUMP] = inst_jal | inst_jalr; - assign dec_bjp_info_bus[`DECINFO_BJP_BEQ] = inst_beq; - assign dec_bjp_info_bus[`DECINFO_BJP_BNE] = inst_bne; - assign dec_bjp_info_bus[`DECINFO_BJP_BLT] = inst_blt; - assign dec_bjp_info_bus[`DECINFO_BJP_BGE] = inst_bge; - assign dec_bjp_info_bus[`DECINFO_BJP_BLTU] = inst_bltu; - assign dec_bjp_info_bus[`DECINFO_BJP_BGEU] = inst_bgeu; - assign dec_bjp_info_bus[`DECINFO_BJP_OP1RS1] = inst_jalr; - - wire[`DECINFO_MULDIV_BUS_WIDTH-1:0] dec_muldiv_info_bus; - assign dec_muldiv_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_MULDIV; - assign dec_muldiv_info_bus[`DECINFO_MULDIV_MUL] = inst_mul; - assign dec_muldiv_info_bus[`DECINFO_MULDIV_MULH] = inst_mulh; - assign dec_muldiv_info_bus[`DECINFO_MULDIV_MULHSU] = inst_mulhsu; - assign dec_muldiv_info_bus[`DECINFO_MULDIV_MULHU] = inst_mulhu; - assign dec_muldiv_info_bus[`DECINFO_MULDIV_DIV] = inst_div; - assign dec_muldiv_info_bus[`DECINFO_MULDIV_DIVU] = inst_divu; - assign dec_muldiv_info_bus[`DECINFO_MULDIV_REM] = inst_rem; - assign dec_muldiv_info_bus[`DECINFO_MULDIV_REMU] = inst_remu; - - wire[`DECINFO_CSR_BUS_WIDTH-1:0] dec_csr_info_bus; - assign dec_csr_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_CSR; - assign dec_csr_info_bus[`DECINFO_CSR_CSRRW] = inst_csrrw | inst_csrrwi; - assign dec_csr_info_bus[`DECINFO_CSR_CSRRS] = inst_csrrs | inst_csrrsi; - assign dec_csr_info_bus[`DECINFO_CSR_CSRRC] = inst_csrrc | inst_csrrci; - assign dec_csr_info_bus[`DECINFO_CSR_RS1IMM] = inst_csrrwi | inst_csrrsi | inst_csrrci; - assign dec_csr_info_bus[`DECINFO_CSR_CSRADDR] = inst_i[31:20]; - - wire[`DECINFO_MEM_BUS_WIDTH-1:0] dec_mem_info_bus; - assign dec_mem_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_MEM; - assign dec_mem_info_bus[`DECINFO_MEM_LB] = inst_lb; - assign dec_mem_info_bus[`DECINFO_MEM_LH] = inst_lh; - assign dec_mem_info_bus[`DECINFO_MEM_LW] = inst_lw; - assign dec_mem_info_bus[`DECINFO_MEM_LBU] = inst_lbu; - assign dec_mem_info_bus[`DECINFO_MEM_LHU] = inst_lhu; - assign dec_mem_info_bus[`DECINFO_MEM_SB] = inst_sb; - assign dec_mem_info_bus[`DECINFO_MEM_SH] = inst_sh; - assign dec_mem_info_bus[`DECINFO_MEM_SW] = inst_sw; - - wire[`DECINFO_SYS_BUS_WIDTH-1:0] dec_sys_info_bus; - assign dec_sys_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_SYS; - assign dec_sys_info_bus[`DECINFO_SYS_ECALL] = inst_ecall; - assign dec_sys_info_bus[`DECINFO_SYS_EBREAK] = inst_ebreak; - assign dec_sys_info_bus[`DECINFO_SYS_NOP] = inst_nop; - assign dec_sys_info_bus[`DECINFO_SYS_MRET] = inst_mret; - assign dec_sys_info_bus[`DECINFO_SYS_FENCE] = inst_fence | inst_fence_i; - - // 鎸囦护涓殑绔嬪嵆鏁 - wire[31:0] inst_u_type_imm = {inst_i[31:12], 12'b0}; - wire[31:0] inst_j_type_imm = {{12{inst_i[31]}}, inst_i[19:12], inst_i[20], inst_i[30:21], 1'b0}; - wire[31:0] inst_b_type_imm = {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0}; - wire[31:0] inst_s_type_imm = {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]}; - wire[31:0] inst_i_type_imm = {{20{inst_i[31]}}, inst_i[31:20]}; - wire[31:0] inst_csr_type_imm = {27'h0, inst_i[19:15]}; - wire[31:0] inst_shift_type_imm = {27'h0, inst_i[24:20]}; - - wire inst_sel_u_imm = inst_lui | inst_auipc; - wire inst_sel_j_imm = inst_jal; - wire inst_sel_b_imm = inst_type_branch; - wire inst_sel_s_imm = inst_type_store; - wire inst_sel_i_imm = inst_addi | inst_slti | inst_sltiu | inst_xori | inst_ori | inst_andi | inst_type_load | inst_jalr; - wire inst_sel_csr_imm = inst_csrrwi | inst_csrrsi | inst_csrrci; - wire inst_sel_shift_imm = inst_slli | inst_srli | inst_srai; - - assign dec_imm_o = ({32{inst_sel_u_imm}} & inst_u_type_imm) | - ({32{inst_sel_j_imm}} & inst_j_type_imm) | - ({32{inst_sel_b_imm}} & inst_b_type_imm) | - ({32{inst_sel_s_imm}} & inst_s_type_imm) | - ({32{inst_sel_i_imm}} & inst_i_type_imm) | - ({32{inst_sel_csr_imm}} & inst_csr_type_imm) | - ({32{inst_sel_shift_imm}} & inst_shift_type_imm); - - wire op_alu = inst_lui | inst_auipc | opcode_0010011 | (opcode_0110011 & (~inst_type_muldiv)); - wire op_bjp = inst_jal | inst_jalr | inst_type_branch; - wire op_muldiv = inst_type_muldiv; - wire op_csr = inst_csrrw | inst_csrrwi | inst_csrrs | inst_csrrsi | inst_csrrc | inst_csrrci; - wire op_sys = inst_ebreak | inst_ecall | inst_nop | inst_mret | inst_fence | inst_fence_i; - wire op_mem = inst_type_load | inst_type_store; - - assign dec_info_bus_o = ({`DECINFO_WIDTH{op_alu}} & {{`DECINFO_WIDTH-`DECINFO_ALU_BUS_WIDTH{1'b0}}, dec_alu_info_bus}) | - ({`DECINFO_WIDTH{op_bjp}} & {{`DECINFO_WIDTH-`DECINFO_BJP_BUS_WIDTH{1'b0}}, dec_bjp_info_bus}) | - ({`DECINFO_WIDTH{op_muldiv}} & {{`DECINFO_WIDTH-`DECINFO_MULDIV_BUS_WIDTH{1'b0}}, dec_muldiv_info_bus}) | - ({`DECINFO_WIDTH{op_csr}} & {{`DECINFO_WIDTH-`DECINFO_CSR_BUS_WIDTH{1'b0}}, dec_csr_info_bus}) | - ({`DECINFO_WIDTH{op_mem}} & {{`DECINFO_WIDTH-`DECINFO_MEM_BUS_WIDTH{1'b0}}, dec_mem_info_bus}) | - ({`DECINFO_WIDTH{op_sys}} & {{`DECINFO_WIDTH-`DECINFO_SYS_BUS_WIDTH{1'b0}}, dec_sys_info_bus}); - - assign dec_pc_o = inst_addr_i; - - // 鏄惁闇瑕佽闂畆s1瀵勫瓨鍣 - wire access_rs1 = (~inst_lui) & - (~inst_auipc) & - (~inst_jal) & - (~inst_ecall) & - (~inst_ebreak) & - (~inst_csrrwi) & - (~inst_csrrsi) & - (~inst_csrrci) & - (~inst_nop) & - (~inst_fence) & - (~inst_fence_i) & - (~inst_mret); - - assign rs1_raddr_o = access_rs1? rs1: 5'h0; - - // 鏄惁闇瑕佽闂畆s2瀵勫瓨鍣 - wire access_rs2 = opcode_0110011 | inst_type_store | inst_type_branch; - - assign rs2_raddr_o = access_rs2? rs2: 5'h0; - - // 鏄惁闇瑕佽闂畆d瀵勫瓨鍣 - wire access_rd = inst_lui | inst_auipc | inst_jal | inst_jalr | inst_type_load | opcode_0010011 | opcode_0110011 | op_csr; - - assign rd_waddr_o = access_rd? rd: 5'h0; - assign rd_we_o = access_rd; - - assign stall_o = 1'b0; - -endmodule + /* + Copyright 2019 Blue Liang, liangkangnan@163.com + + 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. + */ + +`include "defines.sv" + +// 璇戠爜妯″潡 +// 绾粍鍚堥昏緫鐢佃矾 +module idu( + + input wire clk, + input wire rst_n, + + // from if_id + input wire[31:0] inst_i, // 鎸囦护鍐呭 + input wire[31:0] inst_addr_i, // 鎸囦护鍦板潃 + + // from gpr_reg + input wire[31:0] rs1_rdata_i, // 閫氱敤瀵勫瓨鍣1杈撳叆鏁版嵁 + input wire[31:0] rs2_rdata_i, // 閫氱敤瀵勫瓨鍣2杈撳叆鏁版嵁 + + output wire stall_o, + + // to id_ex + output wire[31:0] inst_o, + output wire[`DECINFO_WIDTH-1:0] dec_info_bus_o, + output wire[31:0] dec_imm_o, + output wire[31:0] dec_pc_o, + output wire[4:0] rs1_raddr_o, + output wire[4:0] rs2_raddr_o, + output wire[31:0] rs1_rdata_o, + output wire[31:0] rs2_rdata_o, + output wire[4:0] rd_waddr_o, + output wire rd_we_o + + ); + + assign inst_o = inst_i; + assign rs1_rdata_o = rs1_rdata_i; + assign rs2_rdata_o = rs2_rdata_i; + + // 鍙栧嚭鎸囦护涓殑姣忎竴涓煙 + wire[6:0] opcode = inst_i[6:0]; + wire[2:0] funct3 = inst_i[14:12]; + wire[6:0] funct7 = inst_i[31:25]; + wire[4:0] rd = inst_i[11:7]; + wire[4:0] rs1 = inst_i[19:15]; + wire[4:0] rs2 = inst_i[24:20]; + wire[11:0] type_i_imm_11_0 = inst_i[31:20]; + wire[6:0] type_s_imm_11_5 = inst_i[31:25]; + wire[4:0] type_s_imm_4_0 = inst_i[11:7]; + wire[6:0] type_b_imm_12_10_5 = inst_i[31:25]; + wire[4:0] type_b_imm_4_1_11 = inst_i[11:7]; + wire[19:0] type_u_imm_31_12 = inst_i[31:12]; + wire[19:0] type_j_imm_31_12 = inst_i[31:12]; + + // 鎸囦护opcode鍩熺殑鍙栧 + wire opcode_0110111 = (opcode == 7'b0110111); + wire opcode_0010111 = (opcode == 7'b0010111); + wire opcode_1101111 = (opcode == 7'b1101111); + wire opcode_1100111 = (opcode == 7'b1100111); + wire opcode_1100011 = (opcode == 7'b1100011); + wire opcode_0000011 = (opcode == 7'b0000011); + wire opcode_0100011 = (opcode == 7'b0100011); + wire opcode_0010011 = (opcode == 7'b0010011); + wire opcode_0110011 = (opcode == 7'b0110011); + wire opcode_0001111 = (opcode == 7'b0001111); + wire opcode_1110011 = (opcode == 7'b1110011); + + // 鎸囦护funct3鍩熺殑鍙栧 + wire funct3_000 = (funct3 == 3'b000); + wire funct3_001 = (funct3 == 3'b001); + wire funct3_010 = (funct3 == 3'b010); + wire funct3_011 = (funct3 == 3'b011); + wire funct3_100 = (funct3 == 3'b100); + wire funct3_101 = (funct3 == 3'b101); + wire funct3_110 = (funct3 == 3'b110); + wire funct3_111 = (funct3 == 3'b111); + + // 鎸囦护funct7鍩熺殑鍙栧 + wire funct7_0000000 = (funct7 == 7'b0000000); + wire funct7_0100000 = (funct7 == 7'b0100000); + wire funct7_0000001 = (funct7 == 7'b0000001); + + // I绫诲瀷鎸囦护imm鍩熺殑鍙栧 + wire type_i_imm_000000000000 = (type_i_imm_11_0 == 12'b000000000000); + wire type_i_imm_000000000001 = (type_i_imm_11_0 == 12'b000000000001); + + // 璇戠爜鍑哄叿浣撴寚浠 + wire inst_lui = opcode_0110111; + wire inst_auipc = opcode_0010111; + wire inst_jal = opcode_1101111; + wire inst_jalr = opcode_1100111 & funct3_000; + wire inst_beq = opcode_1100011 & funct3_000; + wire inst_bne = opcode_1100011 & funct3_001; + wire inst_blt = opcode_1100011 & funct3_100; + wire inst_bge = opcode_1100011 & funct3_101; + wire inst_bltu = opcode_1100011 & funct3_110; + wire inst_bgeu = opcode_1100011 & funct3_111; + wire inst_lb = opcode_0000011 & funct3_000; + wire inst_lh = opcode_0000011 & funct3_001; + wire inst_lw = opcode_0000011 & funct3_010; + wire inst_lbu = opcode_0000011 & funct3_100; + wire inst_lhu = opcode_0000011 & funct3_101; + wire inst_sb = opcode_0100011 & funct3_000; + wire inst_sh = opcode_0100011 & funct3_001; + wire inst_sw = opcode_0100011 & funct3_010; + wire inst_addi = opcode_0010011 & funct3_000; + wire inst_slti = opcode_0010011 & funct3_010; + wire inst_sltiu = opcode_0010011 & funct3_011; + wire inst_xori = opcode_0010011 & funct3_100; + wire inst_ori = opcode_0010011 & funct3_110; + wire inst_andi = opcode_0010011 & funct3_111; + wire inst_slli = opcode_0010011 & funct3_001 & funct7_0000000; + wire inst_srli = opcode_0010011 & funct3_101 & funct7_0000000; + wire inst_srai = opcode_0010011 & funct3_101 & funct7_0100000; + wire inst_add = opcode_0110011 & funct3_000 & funct7_0000000; + wire inst_sub = opcode_0110011 & funct3_000 & funct7_0100000; + wire inst_sll = opcode_0110011 & funct3_001 & funct7_0000000; + wire inst_slt = opcode_0110011 & funct3_010 & funct7_0000000; + wire inst_sltu = opcode_0110011 & funct3_011 & funct7_0000000; + wire inst_xor = opcode_0110011 & funct3_100 & funct7_0000000; + wire inst_srl = opcode_0110011 & funct3_101 & funct7_0000000; + wire inst_sra = opcode_0110011 & funct3_101 & funct7_0100000; + wire inst_or = opcode_0110011 & funct3_110 & funct7_0000000; + wire inst_and = opcode_0110011 & funct3_111 & funct7_0000000; + wire inst_fence = opcode_0001111 & funct3_000; + wire inst_ecall = (inst_i == `INST_ECALL); + wire inst_ebreak = (inst_i == `INST_EBREAK); + wire inst_fence_i = opcode_0001111 & funct3_001; + wire inst_csrrw = opcode_1110011 & funct3_001; + wire inst_csrrs = opcode_1110011 & funct3_010; + wire inst_csrrc = opcode_1110011 & funct3_011; + wire inst_csrrwi = opcode_1110011 & funct3_101; + wire inst_csrrsi = opcode_1110011 & funct3_110; + wire inst_csrrci = opcode_1110011 & funct3_111; + wire inst_mul = opcode_0110011 & funct3_000 & funct7_0000001; + wire inst_mulh = opcode_0110011 & funct3_001 & funct7_0000001; + wire inst_mulhsu = opcode_0110011 & funct3_010 & funct7_0000001; + wire inst_mulhu = opcode_0110011 & funct3_011 & funct7_0000001; + wire inst_div = opcode_0110011 & funct3_100 & funct7_0000001; + wire inst_divu = opcode_0110011 & funct3_101 & funct7_0000001; + wire inst_rem = opcode_0110011 & funct3_110 & funct7_0000001; + wire inst_remu = opcode_0110011 & funct3_111 & funct7_0000001; + wire inst_nop = (inst_i == `INST_NOP); + wire inst_mret = (inst_i == `INST_MRET); + + // 灏嗘寚浠ゅ垎绫 + wire inst_type_load = opcode_0000011; + wire inst_type_store = opcode_0100011; + wire inst_type_branch = opcode_1100011; + wire inst_type_muldiv = inst_mul | inst_mulh | inst_mulhsu | inst_mulhu | inst_div | inst_divu | inst_rem | inst_remu; + wire inst_type_div = inst_div | inst_divu | inst_rem | inst_remu; + + wire[`DECINFO_ALU_BUS_WIDTH-1:0] dec_alu_info_bus; + assign dec_alu_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_ALU; + assign dec_alu_info_bus[`DECINFO_ALU_LUI] = inst_lui; + assign dec_alu_info_bus[`DECINFO_ALU_AUIPC] = inst_auipc; + assign dec_alu_info_bus[`DECINFO_ALU_ADD] = inst_add | inst_addi; + assign dec_alu_info_bus[`DECINFO_ALU_SUB] = inst_sub; + assign dec_alu_info_bus[`DECINFO_ALU_SLL] = inst_sll | inst_slli; + assign dec_alu_info_bus[`DECINFO_ALU_SLT] = inst_slt | inst_slti; + assign dec_alu_info_bus[`DECINFO_ALU_SLTU] = inst_sltu | inst_sltiu; + assign dec_alu_info_bus[`DECINFO_ALU_XOR] = inst_xor | inst_xori; + assign dec_alu_info_bus[`DECINFO_ALU_SRL] = inst_srl | inst_srli; + assign dec_alu_info_bus[`DECINFO_ALU_SRA] = inst_sra | inst_srai; + assign dec_alu_info_bus[`DECINFO_ALU_OR] = inst_or | inst_ori; + assign dec_alu_info_bus[`DECINFO_ALU_AND] = inst_and | inst_andi; + assign dec_alu_info_bus[`DECINFO_ALU_OP2IMM] = opcode_0010011 | inst_lui | inst_auipc; + assign dec_alu_info_bus[`DECINFO_ALU_OP1PC] = inst_auipc; + + wire[`DECINFO_BJP_BUS_WIDTH-1:0] dec_bjp_info_bus; + assign dec_bjp_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_BJP; + assign dec_bjp_info_bus[`DECINFO_BJP_JUMP] = inst_jal | inst_jalr; + assign dec_bjp_info_bus[`DECINFO_BJP_BEQ] = inst_beq; + assign dec_bjp_info_bus[`DECINFO_BJP_BNE] = inst_bne; + assign dec_bjp_info_bus[`DECINFO_BJP_BLT] = inst_blt; + assign dec_bjp_info_bus[`DECINFO_BJP_BGE] = inst_bge; + assign dec_bjp_info_bus[`DECINFO_BJP_BLTU] = inst_bltu; + assign dec_bjp_info_bus[`DECINFO_BJP_BGEU] = inst_bgeu; + assign dec_bjp_info_bus[`DECINFO_BJP_OP1RS1] = inst_jalr; + + wire[`DECINFO_MULDIV_BUS_WIDTH-1:0] dec_muldiv_info_bus; + assign dec_muldiv_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_MULDIV; + assign dec_muldiv_info_bus[`DECINFO_MULDIV_MUL] = inst_mul; + assign dec_muldiv_info_bus[`DECINFO_MULDIV_MULH] = inst_mulh; + assign dec_muldiv_info_bus[`DECINFO_MULDIV_MULHSU] = inst_mulhsu; + assign dec_muldiv_info_bus[`DECINFO_MULDIV_MULHU] = inst_mulhu; + assign dec_muldiv_info_bus[`DECINFO_MULDIV_DIV] = inst_div; + assign dec_muldiv_info_bus[`DECINFO_MULDIV_DIVU] = inst_divu; + assign dec_muldiv_info_bus[`DECINFO_MULDIV_REM] = inst_rem; + assign dec_muldiv_info_bus[`DECINFO_MULDIV_REMU] = inst_remu; + + wire[`DECINFO_CSR_BUS_WIDTH-1:0] dec_csr_info_bus; + assign dec_csr_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_CSR; + assign dec_csr_info_bus[`DECINFO_CSR_CSRRW] = inst_csrrw | inst_csrrwi; + assign dec_csr_info_bus[`DECINFO_CSR_CSRRS] = inst_csrrs | inst_csrrsi; + assign dec_csr_info_bus[`DECINFO_CSR_CSRRC] = inst_csrrc | inst_csrrci; + assign dec_csr_info_bus[`DECINFO_CSR_RS1IMM] = inst_csrrwi | inst_csrrsi | inst_csrrci; + assign dec_csr_info_bus[`DECINFO_CSR_CSRADDR] = inst_i[31:20]; + + wire[`DECINFO_MEM_BUS_WIDTH-1:0] dec_mem_info_bus; + assign dec_mem_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_MEM; + assign dec_mem_info_bus[`DECINFO_MEM_LB] = inst_lb; + assign dec_mem_info_bus[`DECINFO_MEM_LH] = inst_lh; + assign dec_mem_info_bus[`DECINFO_MEM_LW] = inst_lw; + assign dec_mem_info_bus[`DECINFO_MEM_LBU] = inst_lbu; + assign dec_mem_info_bus[`DECINFO_MEM_LHU] = inst_lhu; + assign dec_mem_info_bus[`DECINFO_MEM_SB] = inst_sb; + assign dec_mem_info_bus[`DECINFO_MEM_SH] = inst_sh; + assign dec_mem_info_bus[`DECINFO_MEM_SW] = inst_sw; + + wire[`DECINFO_SYS_BUS_WIDTH-1:0] dec_sys_info_bus; + assign dec_sys_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_SYS; + assign dec_sys_info_bus[`DECINFO_SYS_ECALL] = inst_ecall; + assign dec_sys_info_bus[`DECINFO_SYS_EBREAK] = inst_ebreak; + assign dec_sys_info_bus[`DECINFO_SYS_NOP] = inst_nop; + assign dec_sys_info_bus[`DECINFO_SYS_MRET] = inst_mret; + assign dec_sys_info_bus[`DECINFO_SYS_FENCE] = inst_fence | inst_fence_i; + + // 鎸囦护涓殑绔嬪嵆鏁 + wire[31:0] inst_u_type_imm = {inst_i[31:12], 12'b0}; + wire[31:0] inst_j_type_imm = {{12{inst_i[31]}}, inst_i[19:12], inst_i[20], inst_i[30:21], 1'b0}; + wire[31:0] inst_b_type_imm = {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0}; + wire[31:0] inst_s_type_imm = {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]}; + wire[31:0] inst_i_type_imm = {{20{inst_i[31]}}, inst_i[31:20]}; + wire[31:0] inst_csr_type_imm = {27'h0, inst_i[19:15]}; + wire[31:0] inst_shift_type_imm = {27'h0, inst_i[24:20]}; + + wire inst_sel_u_imm = inst_lui | inst_auipc; + wire inst_sel_j_imm = inst_jal; + wire inst_sel_b_imm = inst_type_branch; + wire inst_sel_s_imm = inst_type_store; + wire inst_sel_i_imm = inst_addi | inst_slti | inst_sltiu | inst_xori | inst_ori | inst_andi | inst_type_load | inst_jalr; + wire inst_sel_csr_imm = inst_csrrwi | inst_csrrsi | inst_csrrci; + wire inst_sel_shift_imm = inst_slli | inst_srli | inst_srai; + + assign dec_imm_o = ({32{inst_sel_u_imm}} & inst_u_type_imm) | + ({32{inst_sel_j_imm}} & inst_j_type_imm) | + ({32{inst_sel_b_imm}} & inst_b_type_imm) | + ({32{inst_sel_s_imm}} & inst_s_type_imm) | + ({32{inst_sel_i_imm}} & inst_i_type_imm) | + ({32{inst_sel_csr_imm}} & inst_csr_type_imm) | + ({32{inst_sel_shift_imm}} & inst_shift_type_imm); + + wire op_alu = inst_lui | inst_auipc | opcode_0010011 | (opcode_0110011 & (~inst_type_muldiv)); + wire op_bjp = inst_jal | inst_jalr | inst_type_branch; + wire op_muldiv = inst_type_muldiv; + wire op_csr = inst_csrrw | inst_csrrwi | inst_csrrs | inst_csrrsi | inst_csrrc | inst_csrrci; + wire op_sys = inst_ebreak | inst_ecall | inst_nop | inst_mret | inst_fence | inst_fence_i; + wire op_mem = inst_type_load | inst_type_store; + + assign dec_info_bus_o = ({`DECINFO_WIDTH{op_alu}} & {{`DECINFO_WIDTH-`DECINFO_ALU_BUS_WIDTH{1'b0}}, dec_alu_info_bus}) | + ({`DECINFO_WIDTH{op_bjp}} & {{`DECINFO_WIDTH-`DECINFO_BJP_BUS_WIDTH{1'b0}}, dec_bjp_info_bus}) | + ({`DECINFO_WIDTH{op_muldiv}} & {{`DECINFO_WIDTH-`DECINFO_MULDIV_BUS_WIDTH{1'b0}}, dec_muldiv_info_bus}) | + ({`DECINFO_WIDTH{op_csr}} & {{`DECINFO_WIDTH-`DECINFO_CSR_BUS_WIDTH{1'b0}}, dec_csr_info_bus}) | + ({`DECINFO_WIDTH{op_mem}} & {{`DECINFO_WIDTH-`DECINFO_MEM_BUS_WIDTH{1'b0}}, dec_mem_info_bus}) | + ({`DECINFO_WIDTH{op_sys}} & {{`DECINFO_WIDTH-`DECINFO_SYS_BUS_WIDTH{1'b0}}, dec_sys_info_bus}); + + assign dec_pc_o = inst_addr_i; + + // 鏄惁闇瑕佽闂畆s1瀵勫瓨鍣 + wire access_rs1 = (~inst_lui) & + (~inst_auipc) & + (~inst_jal) & + (~inst_ecall) & + (~inst_ebreak) & + (~inst_csrrwi) & + (~inst_csrrsi) & + (~inst_csrrci) & + (~inst_nop) & + (~inst_fence) & + (~inst_fence_i) & + (~inst_mret); + + assign rs1_raddr_o = access_rs1? rs1: 5'h0; + + // 鏄惁闇瑕佽闂畆s2瀵勫瓨鍣 + wire access_rs2 = opcode_0110011 | inst_type_store | inst_type_branch; + + assign rs2_raddr_o = access_rs2? rs2: 5'h0; + + // 鏄惁闇瑕佽闂畆d瀵勫瓨鍣 + wire access_rd = inst_lui | inst_auipc | inst_jal | inst_jalr | inst_type_load | opcode_0010011 | opcode_0110011 | op_csr; + + assign rd_waddr_o = access_rd? rd: 5'h0; + assign rd_we_o = access_rd; + + assign stall_o = 1'b0; + +endmodule diff --git a/rtl/core/idu_exu.sv b/rtl/core/idu_exu.sv index ae1c1d1..f59385c 100644 --- a/rtl/core/idu_exu.sv +++ b/rtl/core/idu_exu.sv @@ -1,90 +1,97 @@ - /* - Copyright 2020 Blue Liang, liangkangnan@163.com - - 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. - */ - -`include "defines.sv" - -// 灏嗚瘧鐮佺粨鏋滃悜鎵ц妯″潡浼犻 -module idu_exu( - - input wire clk, - input wire rst_n, - - input wire[`STALL_WIDTH-1:0] stall_i, // 娴佹按绾挎殏鍋 - input wire flush_i, // 娴佹按绾垮啿鍒 - - input wire[31:0] inst_i, - input wire[`DECINFO_WIDTH-1:0] dec_info_bus_i, - input wire[31:0] dec_imm_i, - input wire[31:0] dec_pc_i, - input wire[31:0] rs1_rdata_i, - input wire[31:0] rs2_rdata_i, - input wire[4:0] rd_waddr_i, - input wire rd_we_i, - - output wire[31:0] inst_o, - output wire[`DECINFO_WIDTH-1:0] dec_info_bus_o, - output wire[31:0] dec_imm_o, - output wire[31:0] dec_pc_o, - output wire[31:0] rs1_rdata_o, - output wire[31:0] rs2_rdata_o, - output wire[4:0] rd_waddr_o, - output wire rd_we_o - - ); - - wire en = !stall_i[`STALL_EX] | flush_i; - - wire[`DECINFO_WIDTH-1:0] i_dec_info_bus = flush_i? {`DECINFO_WIDTH{1'b0}}: dec_info_bus_i; - wire[`DECINFO_WIDTH-1:0] dec_info_bus; - gen_en_dff #(`DECINFO_WIDTH) info_bus_ff(clk, rst_n, en, i_dec_info_bus, dec_info_bus); - assign dec_info_bus_o = dec_info_bus; - - wire[31:0] i_dec_imm = flush_i? 32'h0: dec_imm_i; - wire[31:0] dec_imm; - gen_en_dff #(32) imm_ff(clk, rst_n, en, i_dec_imm, dec_imm); - assign dec_imm_o = dec_imm; - - wire[31:0] i_dec_pc = flush_i? 32'h0: dec_pc_i; - wire[31:0] dec_pc; - gen_en_dff #(32) pc_ff(clk, rst_n, en, i_dec_pc, dec_pc); - assign dec_pc_o = dec_pc; - - wire[31:0] i_rs1_rdata = flush_i? 32'h0: rs1_rdata_i; - wire[31:0] rs1_rdata; - gen_en_dff #(32) rs1_rdata_ff(clk, rst_n, en, i_rs1_rdata, rs1_rdata); - assign rs1_rdata_o = rs1_rdata; - - wire[31:0] i_rs2_rdata = flush_i? 32'h0: rs2_rdata_i; - wire[31:0] rs2_rdata; - gen_en_dff #(32) rs2_rdata_ff(clk, rst_n, en, i_rs2_rdata, rs2_rdata); - assign rs2_rdata_o = rs2_rdata; - - wire[4:0] i_rd_waddr = flush_i? 5'h0: rd_waddr_i; - wire[4:0] rd_waddr; - gen_en_dff #(5) rd_waddr_ff(clk, rst_n, en, i_rd_waddr, rd_waddr); - assign rd_waddr_o = rd_waddr; - - wire i_rd_we = flush_i? 1'b0: rd_we_i; - wire rd_we; - gen_en_dff #(1) rd_we_ff(clk, rst_n, en, i_rd_we, rd_we); - assign rd_we_o = rd_we; - - wire[31:0] i_inst = flush_i? 32'h0: inst_i; - wire[31:0] inst; - gen_en_dff #(32) inst_ff(clk, rst_n, en, i_inst, inst); - assign inst_o = inst; - -endmodule + /* + Copyright 2020 Blue Liang, liangkangnan@163.com + + 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. + */ + +`include "defines.sv" + +// 灏嗚瘧鐮佺粨鏋滃悜鎵ц妯″潡浼犻 +module idu_exu( + + input wire clk, + input wire rst_n, + + input wire[`STALL_WIDTH-1:0] stall_i, // 娴佹按绾挎殏鍋 + input wire flush_i, // 娴佹按绾垮啿鍒 + + input wire[31:0] inst_i, + input wire inst_valid_i, + input wire[`DECINFO_WIDTH-1:0] dec_info_bus_i, + input wire[31:0] dec_imm_i, + input wire[31:0] dec_pc_i, + input wire[31:0] rs1_rdata_i, + input wire[31:0] rs2_rdata_i, + input wire[4:0] rd_waddr_i, + input wire rd_we_i, + + output wire[31:0] inst_o, + output wire inst_valid_o, + output wire[`DECINFO_WIDTH-1:0] dec_info_bus_o, + output wire[31:0] dec_imm_o, + output wire[31:0] dec_pc_o, + output wire[31:0] rs1_rdata_o, + output wire[31:0] rs2_rdata_o, + output wire[4:0] rd_waddr_o, + output wire rd_we_o + + ); + + wire en = !stall_i[`STALL_EX] | flush_i; + + wire[`DECINFO_WIDTH-1:0] i_dec_info_bus = flush_i? {`DECINFO_WIDTH{1'b0}}: dec_info_bus_i; + wire[`DECINFO_WIDTH-1:0] dec_info_bus; + gen_en_dff #(`DECINFO_WIDTH) info_bus_ff(clk, rst_n, en, i_dec_info_bus, dec_info_bus); + assign dec_info_bus_o = dec_info_bus; + + wire[31:0] i_dec_imm = flush_i? 32'h0: dec_imm_i; + wire[31:0] dec_imm; + gen_en_dff #(32) imm_ff(clk, rst_n, en, i_dec_imm, dec_imm); + assign dec_imm_o = dec_imm; + + wire[31:0] i_dec_pc = flush_i? 32'h0: dec_pc_i; + wire[31:0] dec_pc; + gen_en_dff #(32) pc_ff(clk, rst_n, en, i_dec_pc, dec_pc); + assign dec_pc_o = dec_pc; + + wire[31:0] i_rs1_rdata = flush_i? 32'h0: rs1_rdata_i; + wire[31:0] rs1_rdata; + gen_en_dff #(32) rs1_rdata_ff(clk, rst_n, en, i_rs1_rdata, rs1_rdata); + assign rs1_rdata_o = rs1_rdata; + + wire[31:0] i_rs2_rdata = flush_i? 32'h0: rs2_rdata_i; + wire[31:0] rs2_rdata; + gen_en_dff #(32) rs2_rdata_ff(clk, rst_n, en, i_rs2_rdata, rs2_rdata); + assign rs2_rdata_o = rs2_rdata; + + wire[4:0] i_rd_waddr = flush_i? 5'h0: rd_waddr_i; + wire[4:0] rd_waddr; + gen_en_dff #(5) rd_waddr_ff(clk, rst_n, en, i_rd_waddr, rd_waddr); + assign rd_waddr_o = rd_waddr; + + wire i_rd_we = flush_i? 1'b0: rd_we_i; + wire rd_we; + gen_en_dff #(1) rd_we_ff(clk, rst_n, en, i_rd_we, rd_we); + assign rd_we_o = rd_we; + + wire[31:0] i_inst = flush_i? 32'h0: inst_i; + wire[31:0] inst; + gen_en_dff #(32) inst_ff(clk, rst_n, en, i_inst, inst); + assign inst_o = inst; + + wire i_inst_valid = flush_i? 1'b0: inst_valid_i; + wire inst_valid; + gen_en_dff #(1) inst_valid_ff(clk, rst_n, 1'b1, i_inst_valid, inst_valid); + assign inst_valid_o = inst_valid; + +endmodule diff --git a/rtl/core/ifu.sv b/rtl/core/ifu.sv index b2ad29c..eef34bd 100644 --- a/rtl/core/ifu.sv +++ b/rtl/core/ifu.sv @@ -1,125 +1,126 @@ - /* - Copyright 2020 Blue Liang, liangkangnan@163.com - - 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. - */ - -`include "defines.sv" - -// 鍙栨寚妯″潡 -module ifu( - - input wire clk, - input wire rst_n, - - input wire flush_i, - input wire[31:0] flush_addr_i, // 璺宠浆鍦板潃 - input wire[`STALL_WIDTH-1:0] stall_i, // 娴佹按绾挎殏鍋滄爣蹇 - input wire jtag_halt_i, - - output wire[31:0] inst_o, - output wire[31:0] pc_o, - output wire inst_valid_o, - - output wire[31:0] ibus_addr_o, - input wire[31:0] ibus_data_i, - output wire[31:0] ibus_data_o, - output wire[3:0] ibus_sel_o, - output wire ibus_we_o, - output wire req_valid_o, - input wire req_ready_i, - input wire rsp_valid_i, - output wire rsp_ready_o - - ); - - assign req_valid_o = (~rst_n)? 1'b0: - (flush_i)? 1'b0: - stall_i[`STALL_PC]? 1'b0: - jtag_halt_i? 1'b0: - 1'b1; - assign rsp_ready_o = (~rst_n)? 1'b0: 1'b1; - - wire ifu_req_hsked = (req_valid_o & req_ready_i); - wire ifu_rsp_hsked = (rsp_valid_i & rsp_ready_o); - - // 鍦ㄦ墽琛屽鍛ㄦ湡鎸囦护鎴栬呰姹備笉鍒版荤嚎鏃堕渶瑕佹殏鍋 - wire stall = stall_i[`STALL_PC] | (~ifu_req_hsked); - - reg[31:0] pc; - reg[31:0] pc_prev; - - always @ (posedge clk or negedge rst_n) begin - // 澶嶄綅 - if (!rst_n) begin - pc <= `CPU_RESET_ADDR; - pc_prev <= 32'h0; - // 鍐插埛 - end else if (flush_i) begin - pc <= flush_addr_i; - // 鏆傚仠锛屽彇涓婁竴鏉℃寚浠 - end else if (stall) begin - pc <= pc_prev; - // 鍙栦笅涓鏉℃寚浠 - end else begin - pc <= pc + 32'h4; - pc_prev <= pc; - end - end - - wire[31:0] pc_r; - // 灏哖C鎵撲竴鎷 - wire pc_ena = (~stall); - gen_en_dff #(32) pc_dff(clk, rst_n, pc_ena, pc, pc_r); - - reg req_hasked_r; - - always @ (posedge clk or negedge rst_n) begin - if (!rst_n) begin - req_hasked_r <= 1'b1; - end else begin - req_hasked_r <= ifu_req_hsked; - end - end - - wire req_switched = ifu_req_hsked & (~req_hasked_r); - - reg rsp_hasked_r; - - always @ (posedge clk or negedge rst_n) begin - if (!rst_n) begin - rsp_hasked_r <= 1'b1; - end else begin - rsp_hasked_r <= ifu_rsp_hsked; - end - end - - wire rsp_switched = ifu_rsp_hsked & (~rsp_hasked_r); - - // 鎬荤嚎鍒囨崲鏈変袱绉嶆儏鍐碉細 - // 1.璁垮瓨鍦板潃浣嶄簬鎸囦护瀛樺偍鍣細褰撹瀛樺畬鎴愬悗锛宨fu_req_hsked鍜宨fu_rsp_hsked淇″彿浼氬悓鏃朵粠0鍙樹负1 - // 2.璁垮瓨鍦板潃涓嶄綅浜庢寚浠ゅ瓨鍌ㄥ櫒锛氬綋璁垮瓨瀹屾垚鍚庯紝ifu_req_hsked鍏堜粠0鍙樹负1鍜宨fu_rsp_hsked鍚庝粠0鍙樹负1 - // 鍙湁绗2绉嶆儏鍐典笅鍙栧嚭鏉ョ殑鎸囦护鏄湁鏁堢殑锛岃繖閲岃鎶婅繖涓ょ鎯呭喌璇嗗埆鍑烘潵 - wire bus_switched = req_switched & rsp_switched; - - // 鍙栨寚鍦板潃 - assign ibus_addr_o = pc; - assign pc_o = pc_r; - wire inst_valid = ifu_rsp_hsked & (~flush_i) & (~bus_switched); - assign inst_o = inst_valid? ibus_data_i: `INST_NOP; - - assign ibus_sel_o = 4'b1111; - assign ibus_we_o = 1'b0; - assign ibus_data_o = 32'h0; - -endmodule + /* + Copyright 2020 Blue Liang, liangkangnan@163.com + + 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. + */ + +`include "defines.sv" + +// 鍙栨寚妯″潡 +module ifu( + + input wire clk, + input wire rst_n, + + input wire flush_i, + input wire[31:0] flush_addr_i, // 璺宠浆鍦板潃 + input wire[`STALL_WIDTH-1:0] stall_i, // 娴佹按绾挎殏鍋滄爣蹇 + input wire jtag_halt_i, + + output wire[31:0] inst_o, + output wire[31:0] pc_o, + output wire inst_valid_o, + + output wire[31:0] ibus_addr_o, + input wire[31:0] ibus_data_i, + output wire[31:0] ibus_data_o, + output wire[3:0] ibus_sel_o, + output wire ibus_we_o, + output wire req_valid_o, + input wire req_ready_i, + input wire rsp_valid_i, + output wire rsp_ready_o + + ); + + assign req_valid_o = (~rst_n)? 1'b0: + (flush_i)? 1'b0: + stall_i[`STALL_PC]? 1'b0: + jtag_halt_i? 1'b0: + 1'b1; + assign rsp_ready_o = (~rst_n)? 1'b0: 1'b1; + + wire ifu_req_hsked = (req_valid_o & req_ready_i); + wire ifu_rsp_hsked = (rsp_valid_i & rsp_ready_o); + + // 鍦ㄦ墽琛屽鍛ㄦ湡鎸囦护鎴栬呰姹備笉鍒版荤嚎鏃堕渶瑕佹殏鍋 + wire stall = stall_i[`STALL_PC] | (~ifu_req_hsked); + + reg[31:0] pc; + reg[31:0] pc_prev; + + always @ (posedge clk or negedge rst_n) begin + // 澶嶄綅 + if (!rst_n) begin + pc <= `CPU_RESET_ADDR; + pc_prev <= 32'h0; + // 鍐插埛 + end else if (flush_i) begin + pc <= flush_addr_i; + // 鏆傚仠锛屽彇涓婁竴鏉℃寚浠 + end else if (stall) begin + pc <= pc_prev; + // 鍙栦笅涓鏉℃寚浠 + end else begin + pc <= pc + 32'h4; + pc_prev <= pc; + end + end + + wire[31:0] pc_r; + // 灏哖C鎵撲竴鎷 + wire pc_ena = (~stall); + gen_en_dff #(32) pc_dff(clk, rst_n, pc_ena, pc, pc_r); + + reg req_hasked_r; + + always @ (posedge clk or negedge rst_n) begin + if (!rst_n) begin + req_hasked_r <= 1'b1; + end else begin + req_hasked_r <= ifu_req_hsked; + end + end + + wire req_switched = ifu_req_hsked & (~req_hasked_r); + + reg rsp_hasked_r; + + always @ (posedge clk or negedge rst_n) begin + if (!rst_n) begin + rsp_hasked_r <= 1'b1; + end else begin + rsp_hasked_r <= ifu_rsp_hsked; + end + end + + wire rsp_switched = ifu_rsp_hsked & (~rsp_hasked_r); + + // 鎬荤嚎鍒囨崲鏈変袱绉嶆儏鍐碉細 + // 1.璁垮瓨鍦板潃浣嶄簬鎸囦护瀛樺偍鍣細褰撹瀛樺畬鎴愬悗锛宨fu_req_hsked鍜宨fu_rsp_hsked淇″彿浼氬悓鏃朵粠0鍙樹负1 + // 2.璁垮瓨鍦板潃涓嶄綅浜庢寚浠ゅ瓨鍌ㄥ櫒锛氬綋璁垮瓨瀹屾垚鍚庯紝ifu_req_hsked鍏堜粠0鍙樹负1鍜宨fu_rsp_hsked鍚庝粠0鍙樹负1 + // 鍙湁绗2绉嶆儏鍐典笅鍙栧嚭鏉ョ殑鎸囦护鏄湁鏁堢殑锛岃繖閲岃鎶婅繖涓ょ鎯呭喌璇嗗埆鍑烘潵 + wire bus_switched = req_switched & rsp_switched; + + // 鍙栨寚鍦板潃 + assign ibus_addr_o = pc; + assign pc_o = pc_r; + wire inst_valid = ifu_rsp_hsked & (~flush_i) & (~bus_switched); + assign inst_valid_o = inst_valid; + assign inst_o = inst_valid? ibus_data_i: `INST_NOP; + + assign ibus_sel_o = 4'b1111; + assign ibus_we_o = 1'b0; + assign ibus_data_o = 32'h0; + +endmodule diff --git a/rtl/core/ifu_idu.sv b/rtl/core/ifu_idu.sv index 9d3e996..56a3d92 100644 --- a/rtl/core/ifu_idu.sv +++ b/rtl/core/ifu_idu.sv @@ -1,48 +1,54 @@ - /* - Copyright 2019 Blue Liang, liangkangnan@163.com - - 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. - */ - -`include "defines.sv" - -// 灏嗘寚浠ゅ悜璇戠爜妯″潡浼犻 -module ifu_idu( - - input wire clk, - input wire rst_n, - - input wire[31:0] inst_i, // 鎸囦护鍐呭 - input wire[31:0] inst_addr_i, // 鎸囦护鍦板潃 - input wire[`STALL_WIDTH-1:0] stall_i, // 娴佹按绾挎殏鍋 - input wire flush_i, // 娴佹按绾垮啿鍒 - input wire inst_valid_i, - - output wire[31:0] inst_o, // 鎸囦护鍐呭 - output wire[31:0] inst_addr_o // 鎸囦护鍦板潃 - - ); - - wire en = !stall_i[`STALL_ID] | flush_i; - - wire[31:0] i_inst = (flush_i)? `INST_NOP: inst_i; - wire[31:0] inst; - gen_en_dff #(32) inst_ff(clk, rst_n, en, i_inst, inst); - assign inst_o = inst; - - wire[31:0] i_inst_addr = flush_i? 32'h0: inst_addr_i; - wire[31:0] inst_addr; - gen_en_dff #(32) inst_addr_ff(clk, rst_n, en, i_inst_addr, inst_addr); - assign inst_addr_o = inst_addr; - -endmodule + /* + Copyright 2019 Blue Liang, liangkangnan@163.com + + 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. + */ + +`include "defines.sv" + +// 灏嗘寚浠ゅ悜璇戠爜妯″潡浼犻 +module ifu_idu( + + input wire clk, + input wire rst_n, + + input wire[31:0] inst_i, // 鎸囦护鍐呭 + input wire[31:0] inst_addr_i, // 鎸囦护鍦板潃 + input wire[`STALL_WIDTH-1:0] stall_i, // 娴佹按绾挎殏鍋 + input wire flush_i, // 娴佹按绾垮啿鍒 + input wire inst_valid_i, + + output wire inst_valid_o, + output wire[31:0] inst_o, // 鎸囦护鍐呭 + output wire[31:0] inst_addr_o // 鎸囦护鍦板潃 + + ); + + wire en = !stall_i[`STALL_ID] | flush_i; + + wire[31:0] i_inst = (flush_i)? `INST_NOP: inst_i; + wire[31:0] inst; + gen_en_dff #(32) inst_ff(clk, rst_n, en, i_inst, inst); + assign inst_o = inst; + + wire[31:0] i_inst_addr = flush_i? 32'h0: inst_addr_i; + wire[31:0] inst_addr; + gen_en_dff #(32) inst_addr_ff(clk, rst_n, en, i_inst_addr, inst_addr); + assign inst_addr_o = inst_addr; + + wire i_inst_valid = flush_i? 1'b0: inst_valid_i; + wire inst_valid; + gen_en_dff #(1) inst_valid_ff(clk, rst_n, 1'b1, i_inst_valid, inst_valid); + assign inst_valid_o = inst_valid; + +endmodule diff --git a/rtl/core/pipe_ctrl.sv b/rtl/core/pipe_ctrl.sv index 0be7f8e..6c6f742 100644 --- a/rtl/core/pipe_ctrl.sv +++ b/rtl/core/pipe_ctrl.sv @@ -1,65 +1,65 @@ - /* - Copyright 2019 Blue Liang, liangkangnan@163.com - - 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. - */ - -`include "defines.sv" - -// 娴佹按绾挎帶鍒舵ā鍧 -// 鍙戝嚭鏆傚仠銆佸啿鍒锋祦姘寸嚎淇″彿 -module pipe_ctrl( - - input wire clk, - input wire rst_n, - - input wire stall_from_id_i, - input wire stall_from_ex_i, - input wire stall_from_jtag_i, - input wire stall_from_clint_i, - input wire jump_assert_i, - input wire[31:0] jump_addr_i, - - output wire flush_o, - output wire[`STALL_WIDTH-1:0] stall_o, - output wire[31:0] flush_addr_o - - ); - - assign flush_addr_o = jump_addr_i; - assign flush_o = jump_assert_i | stall_from_clint_i; - - reg[`STALL_WIDTH-1:0] stall; - - always @ (*) begin - if (stall_from_ex_i | stall_from_clint_i) begin - stall[`STALL_EX] = 1'b1; - stall[`STALL_ID] = 1'b1; - stall[`STALL_IF] = 1'b1; - stall[`STALL_PC] = 1'b1; - end else if (stall_from_id_i) begin - stall[`STALL_EX] = 1'b0; - stall[`STALL_ID] = 1'b0; - stall[`STALL_IF] = 1'b1; - stall[`STALL_PC] = 1'b1; - end else begin - stall[`STALL_EX] = 1'b0; - stall[`STALL_ID] = 1'b0; - stall[`STALL_IF] = 1'b0; - stall[`STALL_PC] = 1'b0; - end - end - - assign stall_o = stall; - -endmodule + /* + Copyright 2019 Blue Liang, liangkangnan@163.com + + 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. + */ + +`include "defines.sv" + +// 娴佹按绾挎帶鍒舵ā鍧 +// 鍙戝嚭鏆傚仠銆佸啿鍒锋祦姘寸嚎淇″彿 +module pipe_ctrl( + + input wire clk, + input wire rst_n, + + input wire stall_from_id_i, + input wire stall_from_ex_i, + input wire stall_from_jtag_i, + input wire stall_from_clint_i, + input wire jump_assert_i, + input wire[31:0] jump_addr_i, + + output wire flush_o, + output wire[`STALL_WIDTH-1:0] stall_o, + output wire[31:0] flush_addr_o + + ); + + assign flush_addr_o = jump_addr_i; + assign flush_o = jump_assert_i | stall_from_clint_i; + + reg[`STALL_WIDTH-1:0] stall; + + always @ (*) begin + if (stall_from_ex_i | stall_from_clint_i) begin + stall[`STALL_EX] = 1'b1; + stall[`STALL_ID] = 1'b1; + stall[`STALL_IF] = 1'b1; + stall[`STALL_PC] = 1'b1; + end else if (stall_from_id_i) begin + stall[`STALL_EX] = 1'b0; + stall[`STALL_ID] = 1'b0; + stall[`STALL_IF] = 1'b1; + stall[`STALL_PC] = 1'b1; + end else begin + stall[`STALL_EX] = 1'b0; + stall[`STALL_ID] = 1'b0; + stall[`STALL_IF] = 1'b0; + stall[`STALL_PC] = 1'b0; + end + end + + assign stall_o = stall; + +endmodule diff --git a/rtl/core/rst_ctrl.sv b/rtl/core/rst_ctrl.sv index dc00ead..3124bdd 100644 --- a/rtl/core/rst_ctrl.sv +++ b/rtl/core/rst_ctrl.sv @@ -1,59 +1,59 @@ - /* - Copyright 2020 Blue Liang, liangkangnan@163.com - - 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. - */ - -`include "defines.sv" - -// 澶嶄綅鎺у埗妯″潡 -module rst_ctrl( - - input wire clk, - - input wire rst_ext_i, - input wire rst_jtag_i, - - output wire core_rst_n_o, - output wire jtag_rst_n_o - - ); - - wire ext_rst_r; - - gen_ticks_sync #( - .DP(2), - .DW(1) - ) ext_rst_sync( - .rst_n(rst_ext_i), - .clk(clk), - .din(1'b1), - .dout(ext_rst_r) - ); - - reg[`JTAG_RESET_FF_LEVELS-1:0] jtag_rst_r; - - always @ (posedge clk) begin - if (!rst_ext_i) begin - jtag_rst_r[`JTAG_RESET_FF_LEVELS-1:0] <= {`JTAG_RESET_FF_LEVELS{1'b1}}; - end if (rst_jtag_i) begin - jtag_rst_r[`JTAG_RESET_FF_LEVELS-1:0] <= {`JTAG_RESET_FF_LEVELS{1'b0}}; - end else begin - jtag_rst_r[`JTAG_RESET_FF_LEVELS-1:0] <= {jtag_rst_r[`JTAG_RESET_FF_LEVELS-2:0], 1'b1}; - end - end - - assign core_rst_n_o = ext_rst_r & jtag_rst_r[`JTAG_RESET_FF_LEVELS-1]; - assign jtag_rst_n_o = ext_rst_r; - -endmodule + /* + Copyright 2020 Blue Liang, liangkangnan@163.com + + 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. + */ + +`include "defines.sv" + +// 澶嶄綅鎺у埗妯″潡 +module rst_ctrl( + + input wire clk, + + input wire rst_ext_i, + input wire rst_jtag_i, + + output wire core_rst_n_o, + output wire jtag_rst_n_o + + ); + + wire ext_rst_r; + + gen_ticks_sync #( + .DP(2), + .DW(1) + ) ext_rst_sync( + .rst_n(rst_ext_i), + .clk(clk), + .din(1'b1), + .dout(ext_rst_r) + ); + + reg[`JTAG_RESET_FF_LEVELS-1:0] jtag_rst_r; + + always @ (posedge clk) begin + if (!rst_ext_i) begin + jtag_rst_r[`JTAG_RESET_FF_LEVELS-1:0] <= {`JTAG_RESET_FF_LEVELS{1'b1}}; + end if (rst_jtag_i) begin + jtag_rst_r[`JTAG_RESET_FF_LEVELS-1:0] <= {`JTAG_RESET_FF_LEVELS{1'b0}}; + end else begin + jtag_rst_r[`JTAG_RESET_FF_LEVELS-1:0] <= {jtag_rst_r[`JTAG_RESET_FF_LEVELS-2:0], 1'b1}; + end + end + + assign core_rst_n_o = ext_rst_r & jtag_rst_r[`JTAG_RESET_FF_LEVELS-1]; + assign jtag_rst_n_o = ext_rst_r; + +endmodule diff --git a/rtl/core/tinyriscv_core.sv b/rtl/core/tinyriscv_core.sv index 17fe970..ef7b43a 100644 --- a/rtl/core/tinyriscv_core.sv +++ b/rtl/core/tinyriscv_core.sv @@ -56,6 +56,7 @@ module tinyriscv_core( wire[31:0] if_inst_o; wire[31:0] if_inst_addr_o; wire[`INT_WIDTH-1:0] if_int_flag_o; + wire if_inst_valid_o; // idu妯″潡杈撳嚭淇″彿 wire[31:0] id_inst_o; @@ -81,6 +82,7 @@ module tinyriscv_core( wire[31:0] ie_rs2_rdata_o; wire[4:0] ie_rd_waddr_o; wire ie_rd_we_o; + wire ie_inst_valid_o; // exu妯″潡杈撳嚭淇″彿 wire[31:0] ex_mem_wdata_o; @@ -103,6 +105,7 @@ module tinyriscv_core( wire ex_inst_ecall_o; wire ex_inst_ebreak_o; wire ex_inst_mret_o; + wire ex_inst_valid_o; // gpr_reg妯″潡杈撳嚭淇″彿 wire[31:0] regs_rdata1_o; @@ -207,6 +210,7 @@ module tinyriscv_core( .stall_i(ctrl_stall_o), .flush_i(ctrl_flush_o), .inst_valid_i(ifetch_inst_valid_o), + .inst_valid_o(if_inst_valid_o), .inst_o(if_inst_o), .inst_addr_o(if_inst_addr_o) ); @@ -244,6 +248,8 @@ module tinyriscv_core( .rs2_rdata_i(id_rs2_rdata_o), .rd_waddr_i(id_rd_waddr_o), .rd_we_i(id_rd_we_o), + .inst_valid_i(if_inst_valid_o), + .inst_valid_o(ie_inst_valid_o), .inst_o(ie_inst_o), .dec_info_bus_o(ie_dec_info_bus_o), .dec_imm_o(ie_dec_imm_o), @@ -286,6 +292,9 @@ module tinyriscv_core( .csr_wdata_o(ex_csr_wdata_o), .csr_we_o(ex_csr_we_o), .csr_waddr_o(ex_csr_waddr_o), + .inst_valid_o(ex_inst_valid_o), + .inst_valid_i(ie_inst_valid_o), + .inst_i(ie_inst_o), .dec_info_bus_i(ie_dec_info_bus_o), .dec_imm_i(ie_dec_imm_o), .dec_pc_i(ie_dec_pc_o), @@ -317,7 +326,11 @@ module tinyriscv_core( `ifdef TRACE_ENABLED tracer u_tracer( - + .clk(clk), + .rst_n(rst_n), + .inst_i(ie_inst_o), + .pc_i(ie_dec_pc_o), + .inst_valid_i(ex_inst_valid_o) ); `endif diff --git a/rtl/core/tracer.sv b/rtl/core/tracer.sv index 570161d..7afc748 100644 --- a/rtl/core/tracer.sv +++ b/rtl/core/tracer.sv @@ -584,12 +584,14 @@ module tracer( $display("Writing execution trace to %s", file_name); file_handle = $fopen(file_name, "w"); - $fwrite(file_handle, "Time\tCycle\tPC\tInsn\tDecoded instruction\n"); + $fwrite(file_handle, "\t\t\tTime\tCycle\tPC\tInsn\tDecoded instruction\n"); end function automatic void printbuffer_dumpline(); - $fwrite(file_handle, "%15t\t%d\t%h\t%s\t%s", $time, cycle, pc_i, inst_i, decoded_str); + string insn_str = $sformatf("%h", inst_i); + + $fwrite(file_handle, "%15t\t%d\t%h\t%s\t%s", $time, cycle, pc_i, insn_str, decoded_str); $fwrite(file_handle, "\n"); endfunction