temp commit

Signed-off-by: liangkangnan <liangkangnan@163.com>
pull/4/head
liangkangnan 2021-03-31 18:00:19 +08:00
parent c070f0b49d
commit 9943d02600
19 changed files with 2704 additions and 2668 deletions

View File

@ -1,223 +1,223 @@
/* /*
Copyright 2020 Blue Liang, liangkangnan@163.com Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
`include "defines.sv" `include "defines.sv"
// core local interruptor module // core local interruptor module
// 核心中断管理、仲裁模块 // 核心中断管理、仲裁模块
module clint( module clint(
input wire clk, input wire clk,
input wire rst_n, input wire rst_n,
// from core // from core
input wire[`INT_WIDTH-1:0] int_flag_i, // 中断输入信号 input wire[`INT_WIDTH-1:0] int_flag_i, // 中断输入信号
// from exu // from exu
input wire inst_ecall_i, // ecall指令 input wire inst_ecall_i, // ecall指令
input wire inst_ebreak_i, // ebreak指令 input wire inst_ebreak_i, // ebreak指令
input wire inst_mret_i, // mret指令 input wire inst_mret_i, // mret指令
input wire[31:0] inst_addr_i, // 指令地址 input wire[31:0] inst_addr_i, // 指令地址
input wire jump_flag_i, input wire jump_flag_i,
input wire mem_access_misaligned_i, input wire mem_access_misaligned_i,
// from csr_reg // from csr_reg
input wire[31:0] csr_mtvec_i, // mtvec寄存器 input wire[31:0] csr_mtvec_i, // mtvec寄存器
input wire[31:0] csr_mepc_i, // mepc寄存器 input wire[31:0] csr_mepc_i, // mepc寄存器
input wire[31:0] csr_mstatus_i, // mstatus寄存器 input wire[31:0] csr_mstatus_i, // mstatus寄存器
// to csr_reg // to csr_reg
output reg csr_we_o, // 写CSR寄存器标志 output reg csr_we_o, // 写CSR寄存器标志
output reg[31:0] csr_waddr_o, // 写CSR寄存器地址 output reg[31:0] csr_waddr_o, // 写CSR寄存器地址
output reg[31:0] csr_wdata_o, // 写CSR寄存器数据 output reg[31:0] csr_wdata_o, // 写CSR寄存器数据
// to pipe_ctrl // to pipe_ctrl
output wire stall_flag_o, // 流水线暂停标志 output wire stall_flag_o, // 流水线暂停标志
output wire[31:0] int_addr_o, // 中断入口地址 output wire[31:0] int_addr_o, // 中断入口地址
output wire int_assert_o // 中断标志 output wire int_assert_o // 中断标志
); );
// 中断状态定义 // 中断状态定义
localparam S_INT_IDLE = 4'b0001; localparam S_INT_IDLE = 4'b0001;
localparam S_INT_SYNC_ASSERT = 4'b0010; localparam S_INT_SYNC_ASSERT = 4'b0010;
localparam S_INT_ASYNC_ASSERT = 4'b0100; localparam S_INT_ASYNC_ASSERT = 4'b0100;
localparam S_INT_MRET = 4'b1000; localparam S_INT_MRET = 4'b1000;
// 写CSR寄存器状态定义 // 写CSR寄存器状态定义
localparam S_CSR_IDLE = 5'b00001; localparam S_CSR_IDLE = 5'b00001;
localparam S_CSR_MSTATUS = 5'b00010; localparam S_CSR_MSTATUS = 5'b00010;
localparam S_CSR_MEPC = 5'b00100; localparam S_CSR_MEPC = 5'b00100;
localparam S_CSR_MSTATUS_MRET = 5'b01000; localparam S_CSR_MSTATUS_MRET = 5'b01000;
localparam S_CSR_MCAUSE = 5'b10000; localparam S_CSR_MCAUSE = 5'b10000;
reg[3:0] int_state; reg[3:0] int_state;
reg[4:0] csr_state; reg[4:0] csr_state;
reg[31:0] inst_addr; reg[31:0] inst_addr;
reg[31:0] cause; reg[31:0] cause;
wire global_int_en = csr_mstatus_i[3]; 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; assign stall_flag_o = ((int_state != S_INT_IDLE) | (csr_state != S_CSR_IDLE))? 1'b1: 1'b0;
// 将跳转标志放在流水线上传递 // 将跳转标志放在流水线上传递
wire pc_state_jump_flag; wire pc_state_jump_flag;
gen_rst_0_dff #(1) pc_state_dff(clk, rst_n, jump_flag_i, 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; wire if_state_jump_flag;
gen_rst_0_dff #(1) if_state_dff(clk, rst_n, pc_state_jump_flag, 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; wire id_state_jump_flag;
gen_rst_0_dff #(1) id_state_dff(clk, rst_n, if_state_jump_flag, 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; wire ex_state_jump_flag;
gen_rst_0_dff #(1) ex_state_dff(clk, rst_n, id_state_jump_flag, 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[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; wire inst_addr_valid = (~(|state_jump_flag)) | ex_state_jump_flag;
// 中断仲裁逻辑 // 中断仲裁逻辑
always @ (*) begin always @ (*) begin
// 同步中断 // 同步中断
if (inst_ecall_i | inst_ebreak_i | mem_access_misaligned_i) begin if (inst_ecall_i | inst_ebreak_i | mem_access_misaligned_i) begin
int_state = S_INT_SYNC_ASSERT; int_state = S_INT_SYNC_ASSERT;
// 异步中断 // 异步中断
end else if ((int_flag_i != `INT_NONE) & global_int_en & inst_addr_valid) begin end else if ((int_flag_i != `INT_NONE) & global_int_en & inst_addr_valid) begin
int_state = S_INT_ASYNC_ASSERT; int_state = S_INT_ASYNC_ASSERT;
// 中断返回 // 中断返回
end else if (inst_mret_i) begin end else if (inst_mret_i) begin
int_state = S_INT_MRET; int_state = S_INT_MRET;
// 无中断响应 // 无中断响应
end else begin end else begin
int_state = S_INT_IDLE; int_state = S_INT_IDLE;
end end
end end
// 写CSR寄存器状态切换 // 写CSR寄存器状态切换
always @ (posedge clk or negedge rst_n) begin always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin if (!rst_n) begin
csr_state <= S_CSR_IDLE; csr_state <= S_CSR_IDLE;
cause <= 32'h0; cause <= 32'h0;
inst_addr <= 32'h0; inst_addr <= 32'h0;
end else begin end else begin
case (csr_state) case (csr_state)
S_CSR_IDLE: begin S_CSR_IDLE: begin
case (int_state) case (int_state)
// 同步中断 // 同步中断
S_INT_SYNC_ASSERT: begin S_INT_SYNC_ASSERT: begin
csr_state <= S_CSR_MEPC; csr_state <= S_CSR_MEPC;
// 在中断处理函数里会将中断返回地址加4 // 在中断处理函数里会将中断返回地址加4
inst_addr <= inst_addr_i; inst_addr <= inst_addr_i;
cause <= inst_ebreak_i? 32'd3: cause <= inst_ebreak_i? 32'd3:
inst_ecall_i? 32'd11: inst_ecall_i? 32'd11:
mem_access_misaligned_i? 32'd4: mem_access_misaligned_i? 32'd4:
32'd10; 32'd10;
end end
// 异步中断 // 异步中断
S_INT_ASYNC_ASSERT: begin S_INT_ASYNC_ASSERT: begin
csr_state <= S_CSR_MEPC; csr_state <= S_CSR_MEPC;
inst_addr <= inst_addr_i; inst_addr <= inst_addr_i;
// 定时器中断 // 定时器中断
cause <= 32'h80000004; cause <= 32'h80000004;
end end
// 中断返回 // 中断返回
S_INT_MRET: begin S_INT_MRET: begin
csr_state <= S_CSR_MSTATUS_MRET; csr_state <= S_CSR_MSTATUS_MRET;
end end
endcase endcase
end end
S_CSR_MEPC: begin S_CSR_MEPC: begin
csr_state <= S_CSR_MSTATUS; csr_state <= S_CSR_MSTATUS;
end end
S_CSR_MSTATUS: begin S_CSR_MSTATUS: begin
csr_state <= S_CSR_MCAUSE; csr_state <= S_CSR_MCAUSE;
end end
S_CSR_MCAUSE: begin S_CSR_MCAUSE: begin
csr_state <= S_CSR_IDLE; csr_state <= S_CSR_IDLE;
end end
S_CSR_MSTATUS_MRET: begin S_CSR_MSTATUS_MRET: begin
csr_state <= S_CSR_IDLE; csr_state <= S_CSR_IDLE;
end end
default: begin default: begin
csr_state <= S_CSR_IDLE; csr_state <= S_CSR_IDLE;
end end
endcase endcase
end end
end end
// 发出中断信号前先写几个CSR寄存器 // 发出中断信号前先写几个CSR寄存器
always @ (posedge clk or negedge rst_n) begin always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin if (!rst_n) begin
csr_we_o <= 1'b0; csr_we_o <= 1'b0;
csr_waddr_o <= 32'h0; csr_waddr_o <= 32'h0;
csr_wdata_o <= 32'h0; csr_wdata_o <= 32'h0;
end else begin end else begin
case (csr_state) case (csr_state)
// 将mepc寄存器的值设为当前指令地址 // 将mepc寄存器的值设为当前指令地址
S_CSR_MEPC: begin S_CSR_MEPC: begin
csr_we_o <= 1'b1; csr_we_o <= 1'b1;
csr_waddr_o <= {20'h0, `CSR_MEPC}; csr_waddr_o <= {20'h0, `CSR_MEPC};
csr_wdata_o <= inst_addr; csr_wdata_o <= inst_addr;
end end
// 写中断产生的原因 // 写中断产生的原因
S_CSR_MCAUSE: begin S_CSR_MCAUSE: begin
csr_we_o <= 1'b1; csr_we_o <= 1'b1;
csr_waddr_o <= {20'h0, `CSR_MCAUSE}; csr_waddr_o <= {20'h0, `CSR_MCAUSE};
csr_wdata_o <= cause; csr_wdata_o <= cause;
end end
// 关闭全局中断 // 关闭全局中断
S_CSR_MSTATUS: begin S_CSR_MSTATUS: begin
csr_we_o <= 1'b1; csr_we_o <= 1'b1;
csr_waddr_o <= {20'h0, `CSR_MSTATUS}; csr_waddr_o <= {20'h0, `CSR_MSTATUS};
csr_wdata_o <= {csr_mstatus_i[31:4], 1'b0, csr_mstatus_i[2:0]}; csr_wdata_o <= {csr_mstatus_i[31:4], 1'b0, csr_mstatus_i[2:0]};
end end
// 中断返回 // 中断返回
S_CSR_MSTATUS_MRET: begin S_CSR_MSTATUS_MRET: begin
csr_we_o <= 1'b1; csr_we_o <= 1'b1;
csr_waddr_o <= {20'h0, `CSR_MSTATUS}; csr_waddr_o <= {20'h0, `CSR_MSTATUS};
csr_wdata_o <= {csr_mstatus_i[31:4], csr_mstatus_i[7], csr_mstatus_i[2:0]}; csr_wdata_o <= {csr_mstatus_i[31:4], csr_mstatus_i[7], csr_mstatus_i[2:0]};
end end
default: begin default: begin
csr_we_o <= 1'b0; csr_we_o <= 1'b0;
csr_waddr_o <= 32'h0; csr_waddr_o <= 32'h0;
csr_wdata_o <= 32'h0; csr_wdata_o <= 32'h0;
end end
endcase endcase
end end
end end
reg in_int_context; reg in_int_context;
always @ (posedge clk or negedge rst_n) begin always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin if (!rst_n) begin
in_int_context <= 1'b0; in_int_context <= 1'b0;
end else begin end else begin
if (csr_state == S_CSR_MSTATUS_MRET) begin if (csr_state == S_CSR_MSTATUS_MRET) begin
in_int_context <= 1'b0; in_int_context <= 1'b0;
end else if (csr_state != S_CSR_IDLE) begin end else if (csr_state != S_CSR_IDLE) begin
in_int_context <= 1'b1; in_int_context <= 1'b1;
end end
end end
end end
assign int_assert_o = (csr_state == S_CSR_MCAUSE) | (csr_state == S_CSR_MSTATUS_MRET); 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: assign int_addr_o = (csr_state == S_CSR_MCAUSE)? csr_mtvec_i:
(csr_state == S_CSR_MSTATUS_MRET)? csr_mepc_i: (csr_state == S_CSR_MSTATUS_MRET)? csr_mepc_i:
32'h0; 32'h0;
endmodule endmodule

View File

@ -1,140 +1,140 @@
/* /*
Copyright 2020 Blue Liang, liangkangnan@163.com Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
`include "defines.sv" `include "defines.sv"
// CSR寄存器模块 // CSR寄存器模块
module csr_reg( module csr_reg(
input wire clk, input wire clk,
input wire rst_n, input wire rst_n,
// exu // exu
input wire exu_we_i, // exu模块写寄存器标志 input wire exu_we_i, // exu模块写寄存器标志
input wire[31:0] exu_waddr_i, // exu模块写寄存器地址 input wire[31:0] exu_waddr_i, // exu模块写寄存器地址
input wire[31:0] exu_wdata_i, // exu模块写寄存器数据 input wire[31:0] exu_wdata_i, // exu模块写寄存器数据
input wire[31:0] exu_raddr_i, // exu模块读寄存器地址 input wire[31:0] exu_raddr_i, // exu模块读寄存器地址
output wire[31:0] exu_rdata_o, // exu模块读寄存器数据 output wire[31:0] exu_rdata_o, // exu模块读寄存器数据
// clint // clint
input wire clint_we_i, // clint模块写寄存器标志 input wire clint_we_i, // clint模块写寄存器标志
input wire[31:0] clint_waddr_i, // clint模块写寄存器地址 input wire[31:0] clint_waddr_i, // clint模块写寄存器地址
input wire[31:0] clint_wdata_i, // clint模块写寄存器数据 input wire[31:0] clint_wdata_i, // clint模块写寄存器数据
output wire[31:0] mtvec_o, // mtvec寄存器值 output wire[31:0] mtvec_o, // mtvec寄存器值
output wire[31:0] mepc_o, // mepc寄存器值 output wire[31:0] mepc_o, // mepc寄存器值
output wire[31:0] mstatus_o // mstatus寄存器值 output wire[31:0] mstatus_o // mstatus寄存器值
); );
reg[63:0] cycle; reg[63:0] cycle;
reg[31:0] mtvec; reg[31:0] mtvec;
reg[31:0] mcause; reg[31:0] mcause;
reg[31:0] mepc; reg[31:0] mepc;
reg[31:0] mie; reg[31:0] mie;
reg[31:0] mstatus; reg[31:0] mstatus;
reg[31:0] mscratch; reg[31:0] mscratch;
assign mtvec_o = mtvec; assign mtvec_o = mtvec;
assign mepc_o = mepc; assign mepc_o = mepc;
assign mstatus_o = mstatus; assign mstatus_o = mstatus;
// cycle counter // cycle counter
// 复位撤销后就一直计数 // 复位撤销后就一直计数
always @ (posedge clk or negedge rst_n) begin always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin if (!rst_n) begin
cycle <= {32'h0, 32'h0}; cycle <= {32'h0, 32'h0};
end else begin end else begin
cycle <= cycle + 1'b1; cycle <= cycle + 1'b1;
end end
end end
wire we = exu_we_i | clint_we_i; wire we = exu_we_i | clint_we_i;
wire[31:0] waddr = exu_we_i? exu_waddr_i: clint_waddr_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; wire[31:0] wdata = exu_we_i? exu_wdata_i: clint_wdata_i;
// 写寄存器 // 写寄存器
always @ (posedge clk or negedge rst_n) begin always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin if (!rst_n) begin
mtvec <= 32'h0; mtvec <= 32'h0;
mcause <= 32'h0; mcause <= 32'h0;
mepc <= 32'h0; mepc <= 32'h0;
mie <= 32'h0; mie <= 32'h0;
mstatus <= 32'h0; mstatus <= 32'h0;
mscratch <= 32'h0; mscratch <= 32'h0;
end else begin end else begin
if (we) begin if (we) begin
case (waddr[11:0]) case (waddr[11:0])
`CSR_MTVEC: begin `CSR_MTVEC: begin
mtvec <= wdata; mtvec <= wdata;
end end
`CSR_MCAUSE: begin `CSR_MCAUSE: begin
mcause <= wdata; mcause <= wdata;
end end
`CSR_MEPC: begin `CSR_MEPC: begin
mepc <= wdata; mepc <= wdata;
end end
`CSR_MIE: begin `CSR_MIE: begin
mie <= wdata; mie <= wdata;
end end
`CSR_MSTATUS: begin `CSR_MSTATUS: begin
mstatus <= wdata; mstatus <= wdata;
end end
`CSR_MSCRATCH: begin `CSR_MSCRATCH: begin
mscratch <= wdata; mscratch <= wdata;
end end
endcase endcase
end end
end end
end end
reg[31:0] exu_rdata; reg[31:0] exu_rdata;
// exu模块读CSR寄存器 // exu模块读CSR寄存器
always @ (*) begin always @ (*) begin
case (exu_raddr_i[11:0]) case (exu_raddr_i[11:0])
`CSR_CYCLE: begin `CSR_CYCLE: begin
exu_rdata = cycle[31:0]; exu_rdata = cycle[31:0];
end end
`CSR_CYCLEH: begin `CSR_CYCLEH: begin
exu_rdata = cycle[63:32]; exu_rdata = cycle[63:32];
end end
`CSR_MTVEC: begin `CSR_MTVEC: begin
exu_rdata = mtvec; exu_rdata = mtvec;
end end
`CSR_MCAUSE: begin `CSR_MCAUSE: begin
exu_rdata = mcause; exu_rdata = mcause;
end end
`CSR_MEPC: begin `CSR_MEPC: begin
exu_rdata = mepc; exu_rdata = mepc;
end end
`CSR_MIE: begin `CSR_MIE: begin
exu_rdata = mie; exu_rdata = mie;
end end
`CSR_MSTATUS: begin `CSR_MSTATUS: begin
exu_rdata = mstatus; exu_rdata = mstatus;
end end
`CSR_MSCRATCH: begin `CSR_MSCRATCH: begin
exu_rdata = mscratch; exu_rdata = mscratch;
end end
default: begin default: begin
exu_rdata = 32'h0; exu_rdata = 32'h0;
end end
endcase endcase
end end
assign exu_rdata_o = exu_rdata; assign exu_rdata_o = exu_rdata;
endmodule endmodule

View File

@ -1,122 +1,122 @@
/* /*
Copyright 2019 Blue Liang, liangkangnan@163.com Copyright 2019 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
`define CPU_RESET_ADDR 32'h0 // CPU复位地址 `define CPU_RESET_ADDR 32'h0 // CPU复位地址
`define CPU_CLOCK_HZ 50000000 // CPU时钟(50MHZ) `define CPU_CLOCK_HZ 50000000 // CPU时钟(50MHZ)
`define INST_MEM_START_ADDR 32'h0 // 指令存储器起始地址 `define INST_MEM_START_ADDR 32'h0 // 指令存储器起始地址
`define INST_MEM_END_ADDR 32'h0fffffff // 指令存储器结束地址 `define INST_MEM_END_ADDR 32'h0fffffff // 指令存储器结束地址
`define JTAG_RESET_FF_LEVELS 5 `define JTAG_RESET_FF_LEVELS 5
`define ROM_DEPTH 8192 // 指令存储器深度单位为word(4字节) `define ROM_DEPTH 8192 // 指令存储器深度单位为word(4字节)
`define RAM_DEPTH 4096 // 数据存储器深度单位为word(4字节) `define RAM_DEPTH 4096 // 数据存储器深度单位为word(4字节)
`define INT_WIDTH 8 `define INT_WIDTH 8
`define INT_NONE 8'h0 `define INT_NONE 8'h0
`define STALL_WIDTH 4 `define STALL_WIDTH 4
`define STALL_PC 2'd0 `define STALL_PC 2'd0
`define STALL_IF 2'd1 `define STALL_IF 2'd1
`define STALL_ID 2'd2 `define STALL_ID 2'd2
`define STALL_EX 2'd3 `define STALL_EX 2'd3
`define INST_NOP 32'h00000013 `define INST_NOP 32'h00000013
`define INST_MRET 32'h30200073 `define INST_MRET 32'h30200073
`define INST_ECALL 32'h00000073 `define INST_ECALL 32'h00000073
`define INST_EBREAK 32'h00100073 `define INST_EBREAK 32'h00100073
// 指令译码信息 // 指令译码信息
`define DECINFO_GRP_BUS 2:0 `define DECINFO_GRP_BUS 2:0
`define DECINFO_GRP_WIDTH 3 `define DECINFO_GRP_WIDTH 3
`define DECINFO_GRP_ALU `DECINFO_GRP_WIDTH'd1 `define DECINFO_GRP_ALU `DECINFO_GRP_WIDTH'd1
`define DECINFO_GRP_BJP `DECINFO_GRP_WIDTH'd2 `define DECINFO_GRP_BJP `DECINFO_GRP_WIDTH'd2
`define DECINFO_GRP_MULDIV `DECINFO_GRP_WIDTH'd3 `define DECINFO_GRP_MULDIV `DECINFO_GRP_WIDTH'd3
`define DECINFO_GRP_CSR `DECINFO_GRP_WIDTH'd4 `define DECINFO_GRP_CSR `DECINFO_GRP_WIDTH'd4
`define DECINFO_GRP_MEM `DECINFO_GRP_WIDTH'd5 `define DECINFO_GRP_MEM `DECINFO_GRP_WIDTH'd5
`define DECINFO_GRP_SYS `DECINFO_GRP_WIDTH'd6 `define DECINFO_GRP_SYS `DECINFO_GRP_WIDTH'd6
`define DECINFO_ALU_BUS_WIDTH (`DECINFO_GRP_WIDTH+14) `define DECINFO_ALU_BUS_WIDTH (`DECINFO_GRP_WIDTH+14)
`define DECINFO_ALU_LUI (`DECINFO_GRP_WIDTH+0) `define DECINFO_ALU_LUI (`DECINFO_GRP_WIDTH+0)
`define DECINFO_ALU_AUIPC (`DECINFO_GRP_WIDTH+1) `define DECINFO_ALU_AUIPC (`DECINFO_GRP_WIDTH+1)
`define DECINFO_ALU_ADD (`DECINFO_GRP_WIDTH+2) `define DECINFO_ALU_ADD (`DECINFO_GRP_WIDTH+2)
`define DECINFO_ALU_SUB (`DECINFO_GRP_WIDTH+3) `define DECINFO_ALU_SUB (`DECINFO_GRP_WIDTH+3)
`define DECINFO_ALU_SLL (`DECINFO_GRP_WIDTH+4) `define DECINFO_ALU_SLL (`DECINFO_GRP_WIDTH+4)
`define DECINFO_ALU_SLT (`DECINFO_GRP_WIDTH+5) `define DECINFO_ALU_SLT (`DECINFO_GRP_WIDTH+5)
`define DECINFO_ALU_SLTU (`DECINFO_GRP_WIDTH+6) `define DECINFO_ALU_SLTU (`DECINFO_GRP_WIDTH+6)
`define DECINFO_ALU_XOR (`DECINFO_GRP_WIDTH+7) `define DECINFO_ALU_XOR (`DECINFO_GRP_WIDTH+7)
`define DECINFO_ALU_SRL (`DECINFO_GRP_WIDTH+8) `define DECINFO_ALU_SRL (`DECINFO_GRP_WIDTH+8)
`define DECINFO_ALU_SRA (`DECINFO_GRP_WIDTH+9) `define DECINFO_ALU_SRA (`DECINFO_GRP_WIDTH+9)
`define DECINFO_ALU_OR (`DECINFO_GRP_WIDTH+10) `define DECINFO_ALU_OR (`DECINFO_GRP_WIDTH+10)
`define DECINFO_ALU_AND (`DECINFO_GRP_WIDTH+11) `define DECINFO_ALU_AND (`DECINFO_GRP_WIDTH+11)
`define DECINFO_ALU_OP2IMM (`DECINFO_GRP_WIDTH+12) `define DECINFO_ALU_OP2IMM (`DECINFO_GRP_WIDTH+12)
`define DECINFO_ALU_OP1PC (`DECINFO_GRP_WIDTH+13) `define DECINFO_ALU_OP1PC (`DECINFO_GRP_WIDTH+13)
`define DECINFO_BJP_BUS_WIDTH (`DECINFO_GRP_WIDTH+8) `define DECINFO_BJP_BUS_WIDTH (`DECINFO_GRP_WIDTH+8)
`define DECINFO_BJP_JUMP (`DECINFO_GRP_WIDTH+0) `define DECINFO_BJP_JUMP (`DECINFO_GRP_WIDTH+0)
`define DECINFO_BJP_BEQ (`DECINFO_GRP_WIDTH+1) `define DECINFO_BJP_BEQ (`DECINFO_GRP_WIDTH+1)
`define DECINFO_BJP_BNE (`DECINFO_GRP_WIDTH+2) `define DECINFO_BJP_BNE (`DECINFO_GRP_WIDTH+2)
`define DECINFO_BJP_BLT (`DECINFO_GRP_WIDTH+3) `define DECINFO_BJP_BLT (`DECINFO_GRP_WIDTH+3)
`define DECINFO_BJP_BGE (`DECINFO_GRP_WIDTH+4) `define DECINFO_BJP_BGE (`DECINFO_GRP_WIDTH+4)
`define DECINFO_BJP_BLTU (`DECINFO_GRP_WIDTH+5) `define DECINFO_BJP_BLTU (`DECINFO_GRP_WIDTH+5)
`define DECINFO_BJP_BGEU (`DECINFO_GRP_WIDTH+6) `define DECINFO_BJP_BGEU (`DECINFO_GRP_WIDTH+6)
`define DECINFO_BJP_OP1RS1 (`DECINFO_GRP_WIDTH+7) `define DECINFO_BJP_OP1RS1 (`DECINFO_GRP_WIDTH+7)
`define DECINFO_MULDIV_BUS_WIDTH (`DECINFO_GRP_WIDTH+8) `define DECINFO_MULDIV_BUS_WIDTH (`DECINFO_GRP_WIDTH+8)
`define DECINFO_MULDIV_MUL (`DECINFO_GRP_WIDTH+0) `define DECINFO_MULDIV_MUL (`DECINFO_GRP_WIDTH+0)
`define DECINFO_MULDIV_MULH (`DECINFO_GRP_WIDTH+1) `define DECINFO_MULDIV_MULH (`DECINFO_GRP_WIDTH+1)
`define DECINFO_MULDIV_MULHSU (`DECINFO_GRP_WIDTH+2) `define DECINFO_MULDIV_MULHSU (`DECINFO_GRP_WIDTH+2)
`define DECINFO_MULDIV_MULHU (`DECINFO_GRP_WIDTH+3) `define DECINFO_MULDIV_MULHU (`DECINFO_GRP_WIDTH+3)
`define DECINFO_MULDIV_DIV (`DECINFO_GRP_WIDTH+4) `define DECINFO_MULDIV_DIV (`DECINFO_GRP_WIDTH+4)
`define DECINFO_MULDIV_DIVU (`DECINFO_GRP_WIDTH+5) `define DECINFO_MULDIV_DIVU (`DECINFO_GRP_WIDTH+5)
`define DECINFO_MULDIV_REM (`DECINFO_GRP_WIDTH+6) `define DECINFO_MULDIV_REM (`DECINFO_GRP_WIDTH+6)
`define DECINFO_MULDIV_REMU (`DECINFO_GRP_WIDTH+7) `define DECINFO_MULDIV_REMU (`DECINFO_GRP_WIDTH+7)
`define DECINFO_CSR_BUS_WIDTH (`DECINFO_GRP_WIDTH+16) `define DECINFO_CSR_BUS_WIDTH (`DECINFO_GRP_WIDTH+16)
`define DECINFO_CSR_CSRRW (`DECINFO_GRP_WIDTH+0) `define DECINFO_CSR_CSRRW (`DECINFO_GRP_WIDTH+0)
`define DECINFO_CSR_CSRRS (`DECINFO_GRP_WIDTH+1) `define DECINFO_CSR_CSRRS (`DECINFO_GRP_WIDTH+1)
`define DECINFO_CSR_CSRRC (`DECINFO_GRP_WIDTH+2) `define DECINFO_CSR_CSRRC (`DECINFO_GRP_WIDTH+2)
`define DECINFO_CSR_RS1IMM (`DECINFO_GRP_WIDTH+3) `define DECINFO_CSR_RS1IMM (`DECINFO_GRP_WIDTH+3)
`define DECINFO_CSR_CSRADDR `DECINFO_GRP_WIDTH+4+12-1:`DECINFO_GRP_WIDTH+4 `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_BUS_WIDTH (`DECINFO_GRP_WIDTH+8)
`define DECINFO_MEM_LB (`DECINFO_GRP_WIDTH+0) `define DECINFO_MEM_LB (`DECINFO_GRP_WIDTH+0)
`define DECINFO_MEM_LH (`DECINFO_GRP_WIDTH+1) `define DECINFO_MEM_LH (`DECINFO_GRP_WIDTH+1)
`define DECINFO_MEM_LW (`DECINFO_GRP_WIDTH+2) `define DECINFO_MEM_LW (`DECINFO_GRP_WIDTH+2)
`define DECINFO_MEM_LBU (`DECINFO_GRP_WIDTH+3) `define DECINFO_MEM_LBU (`DECINFO_GRP_WIDTH+3)
`define DECINFO_MEM_LHU (`DECINFO_GRP_WIDTH+4) `define DECINFO_MEM_LHU (`DECINFO_GRP_WIDTH+4)
`define DECINFO_MEM_SB (`DECINFO_GRP_WIDTH+5) `define DECINFO_MEM_SB (`DECINFO_GRP_WIDTH+5)
`define DECINFO_MEM_SH (`DECINFO_GRP_WIDTH+6) `define DECINFO_MEM_SH (`DECINFO_GRP_WIDTH+6)
`define DECINFO_MEM_SW (`DECINFO_GRP_WIDTH+7) `define DECINFO_MEM_SW (`DECINFO_GRP_WIDTH+7)
`define DECINFO_SYS_BUS_WIDTH (`DECINFO_GRP_WIDTH+5) `define DECINFO_SYS_BUS_WIDTH (`DECINFO_GRP_WIDTH+5)
`define DECINFO_SYS_ECALL (`DECINFO_GRP_WIDTH+0) `define DECINFO_SYS_ECALL (`DECINFO_GRP_WIDTH+0)
`define DECINFO_SYS_EBREAK (`DECINFO_GRP_WIDTH+1) `define DECINFO_SYS_EBREAK (`DECINFO_GRP_WIDTH+1)
`define DECINFO_SYS_NOP (`DECINFO_GRP_WIDTH+2) `define DECINFO_SYS_NOP (`DECINFO_GRP_WIDTH+2)
`define DECINFO_SYS_MRET (`DECINFO_GRP_WIDTH+3) `define DECINFO_SYS_MRET (`DECINFO_GRP_WIDTH+3)
`define DECINFO_SYS_FENCE (`DECINFO_GRP_WIDTH+4) `define DECINFO_SYS_FENCE (`DECINFO_GRP_WIDTH+4)
// 最长的那组 // 最长的那组
`define DECINFO_WIDTH `DECINFO_CSR_BUS_WIDTH `define DECINFO_WIDTH `DECINFO_CSR_BUS_WIDTH
// CSR寄存器地址 // CSR寄存器地址
`define CSR_CYCLE 12'hc00 `define CSR_CYCLE 12'hc00
`define CSR_CYCLEH 12'hc80 `define CSR_CYCLEH 12'hc80
`define CSR_MTVEC 12'h305 `define CSR_MTVEC 12'h305
`define CSR_MCAUSE 12'h342 `define CSR_MCAUSE 12'h342
`define CSR_MEPC 12'h341 `define CSR_MEPC 12'h341
`define CSR_MIE 12'h304 `define CSR_MIE 12'h304
`define CSR_MSTATUS 12'h300 `define CSR_MSTATUS 12'h300
`define CSR_MSCRATCH 12'h340 `define CSR_MSCRATCH 12'h340

View File

@ -1,196 +1,196 @@
/* /*
Copyright 2019 Blue Liang, liangkangnan@163.com Copyright 2019 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
`include "defines.sv" `include "defines.sv"
// 除法模块 // 除法模块
// 试商法实现32位整数除法 // 试商法实现32位整数除法
// 每次除法运算至少需要33个时钟周期才能完成 // 每次除法运算至少需要33个时钟周期才能完成
module divider( module divider(
input wire clk, input wire clk,
input wire rst_n, input wire rst_n,
input wire[31:0] dividend_i, // 被除数 input wire[31:0] dividend_i, // 被除数
input wire[31:0] divisor_i, // 除数 input wire[31:0] divisor_i, // 除数
input wire start_i, // 开始信号,运算期间这个信号需要一直保持有效 input wire start_i, // 开始信号,运算期间这个信号需要一直保持有效
input wire[3:0] op_i, // 具体是哪一条指令 input wire[3:0] op_i, // 具体是哪一条指令
output reg[31:0] result_o, // 除法结果高32位是余数低32位是商 output reg[31:0] result_o, // 除法结果高32位是余数低32位是商
output reg ready_o // 运算结束信号 output reg ready_o // 运算结束信号
); );
// 状态定义 // 状态定义
localparam STATE_IDLE = 4'b0001; localparam STATE_IDLE = 4'b0001;
localparam STATE_START = 4'b0010; localparam STATE_START = 4'b0010;
localparam STATE_CALC = 4'b0100; localparam STATE_CALC = 4'b0100;
localparam STATE_END = 4'b1000; localparam STATE_END = 4'b1000;
reg[31:0] dividend_r; reg[31:0] dividend_r;
reg[31:0] divisor_r; reg[31:0] divisor_r;
reg[3:0] op_r; reg[3:0] op_r;
reg[3:0] state; reg[3:0] state;
reg[31:0] count; reg[31:0] count;
reg[31:0] div_result; reg[31:0] div_result;
reg[31:0] div_remain; reg[31:0] div_remain;
reg[31:0] minuend; reg[31:0] minuend;
reg invert_result; reg invert_result;
wire op_div = op_r[3]; wire op_div = op_r[3];
wire op_divu = op_r[2]; wire op_divu = op_r[2];
wire op_rem = op_r[1]; wire op_rem = op_r[1];
wire op_remu = op_r[0]; wire op_remu = op_r[0];
wire[31:0] dividend_invert = (-dividend_r); wire[31:0] dividend_invert = (-dividend_r);
wire[31:0] divisor_invert = (-divisor_r); wire[31:0] divisor_invert = (-divisor_r);
wire minuend_ge_divisor = minuend >= divisor_r; wire minuend_ge_divisor = minuend >= divisor_r;
wire[31:0] minuend_sub_res = 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] 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]; wire[31:0] minuend_tmp = minuend_ge_divisor? minuend_sub_res[30:0]: minuend[30:0];
// 状态机实现 // 状态机实现
always @ (posedge clk or negedge rst_n) begin always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin if (!rst_n) begin
state <= STATE_IDLE; state <= STATE_IDLE;
ready_o <= 1'b0; ready_o <= 1'b0;
result_o <= 32'h0; result_o <= 32'h0;
div_result <= 32'h0; div_result <= 32'h0;
div_remain <= 32'h0; div_remain <= 32'h0;
op_r <= 3'h0; op_r <= 3'h0;
dividend_r <= 32'h0; dividend_r <= 32'h0;
divisor_r <= 32'h0; divisor_r <= 32'h0;
minuend <= 32'h0; minuend <= 32'h0;
invert_result <= 1'b0; invert_result <= 1'b0;
count <= 32'h0; count <= 32'h0;
end else begin end else begin
case (state) case (state)
STATE_IDLE: begin STATE_IDLE: begin
if (start_i) begin if (start_i) begin
op_r <= op_i; op_r <= op_i;
dividend_r <= dividend_i; dividend_r <= dividend_i;
divisor_r <= divisor_i; divisor_r <= divisor_i;
state <= STATE_START; state <= STATE_START;
end else begin end else begin
op_r <= 3'h0; op_r <= 3'h0;
dividend_r <= 32'h0; dividend_r <= 32'h0;
divisor_r <= 32'h0; divisor_r <= 32'h0;
ready_o <= 1'b0; ready_o <= 1'b0;
result_o <= 32'h0; result_o <= 32'h0;
end end
end end
STATE_START: begin STATE_START: begin
if (start_i) begin if (start_i) begin
// 除数为0 // 除数为0
if (divisor_r == 32'h0) begin if (divisor_r == 32'h0) begin
if (op_div | op_divu) begin if (op_div | op_divu) begin
result_o <= 32'hffffffff; result_o <= 32'hffffffff;
end else begin end else begin
result_o <= dividend_r; result_o <= dividend_r;
end end
ready_o <= 1'b1; ready_o <= 1'b1;
state <= STATE_IDLE; state <= STATE_IDLE;
// 除数不为0 // 除数不为0
end else begin end else begin
count <= 32'h40000000; count <= 32'h40000000;
state <= STATE_CALC; state <= STATE_CALC;
div_result <= 32'h0; div_result <= 32'h0;
div_remain <= 32'h0; div_remain <= 32'h0;
// DIV和REM这两条指令是有符号数运算指令 // DIV和REM这两条指令是有符号数运算指令
if (op_div | op_rem) begin if (op_div | op_rem) begin
// 被除数求补码 // 被除数求补码
if (dividend_r[31] == 1'b1) begin if (dividend_r[31] == 1'b1) begin
dividend_r <= dividend_invert; dividend_r <= dividend_invert;
minuend <= dividend_invert[31]; minuend <= dividend_invert[31];
end else begin end else begin
minuend <= dividend_r[31]; minuend <= dividend_r[31];
end end
// 除数求补码 // 除数求补码
if (divisor_r[31] == 1'b1) begin if (divisor_r[31] == 1'b1) begin
divisor_r <= divisor_invert; divisor_r <= divisor_invert;
end end
end else begin end else begin
minuend <= dividend_r[31]; minuend <= dividend_r[31];
end end
// 运算结束后是否要对结果取补码 // 运算结束后是否要对结果取补码
if ((op_div && (dividend_r[31] ^ divisor_r[31] == 1'b1)) if ((op_div && (dividend_r[31] ^ divisor_r[31] == 1'b1))
|| (op_rem && (dividend_r[31] == 1'b1))) begin || (op_rem && (dividend_r[31] == 1'b1))) begin
invert_result <= 1'b1; invert_result <= 1'b1;
end else begin end else begin
invert_result <= 1'b0; invert_result <= 1'b0;
end end
end end
end else begin end else begin
state <= STATE_IDLE; state <= STATE_IDLE;
result_o <= 32'h0; result_o <= 32'h0;
ready_o <= 1'b0; ready_o <= 1'b0;
end end
end end
STATE_CALC: begin STATE_CALC: begin
if (start_i) begin if (start_i) begin
dividend_r <= {dividend_r[30:0], 1'b0}; dividend_r <= {dividend_r[30:0], 1'b0};
div_result <= div_result_tmp; div_result <= div_result_tmp;
count <= {1'b0, count[31:1]}; count <= {1'b0, count[31:1]};
if (|count) begin if (|count) begin
minuend <= {minuend_tmp[30:0], dividend_r[30]}; minuend <= {minuend_tmp[30:0], dividend_r[30]};
end else begin end else begin
state <= STATE_END; state <= STATE_END;
if (minuend_ge_divisor) begin if (minuend_ge_divisor) begin
div_remain <= minuend_sub_res; div_remain <= minuend_sub_res;
end else begin end else begin
div_remain <= minuend; div_remain <= minuend;
end end
end end
end else begin end else begin
state <= STATE_IDLE; state <= STATE_IDLE;
result_o <= 32'h0; result_o <= 32'h0;
ready_o <= 1'b0; ready_o <= 1'b0;
end end
end end
STATE_END: begin STATE_END: begin
if (start_i) begin if (start_i) begin
ready_o <= 1'b1; ready_o <= 1'b1;
state <= STATE_IDLE; state <= STATE_IDLE;
if (op_div | op_divu) begin if (op_div | op_divu) begin
if (invert_result) begin if (invert_result) begin
result_o <= (-div_result); result_o <= (-div_result);
end else begin end else begin
result_o <= div_result; result_o <= div_result;
end end
end else begin end else begin
if (invert_result) begin if (invert_result) begin
result_o <= (-div_remain); result_o <= (-div_remain);
end else begin end else begin
result_o <= div_remain; result_o <= div_remain;
end end
end end
end else begin end else begin
state <= STATE_IDLE; state <= STATE_IDLE;
result_o <= 32'h0; result_o <= 32'h0;
ready_o <= 1'b0; ready_o <= 1'b0;
end end
end end
endcase endcase
end end
end end
endmodule endmodule

View File

@ -1,378 +1,385 @@
/* /*
Copyright 2019 Blue Liang, liangkangnan@163.com Copyright 2019 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
`include "defines.sv" `include "defines.sv"
// 执行模块 // 执行模块
// 纯组合逻辑电路 // 纯组合逻辑电路
module exu( module exu(
input wire clk, input wire clk,
input wire rst_n, input wire rst_n,
// clint // clint
input wire int_assert_i, // 中断发生标志 input wire int_assert_i, // 中断发生标志
input wire[31:0] int_addr_i, // 中断跳转地址 input wire[31:0] int_addr_i, // 中断跳转地址
input wire int_stall_i, // 暂停标志 input wire int_stall_i, // 暂停标志
output wire inst_ecall_o, // ecall指令 output wire inst_ecall_o, // ecall指令
output wire inst_ebreak_o, // ebreak指令 output wire inst_ebreak_o, // ebreak指令
output wire inst_mret_o, // mret指令 output wire inst_mret_o, // mret指令
// mem // mem
input wire[31:0] mem_rdata_i, // 内存输入数据 input wire[31:0] mem_rdata_i, // 内存输入数据
input wire mem_req_ready_i, input wire mem_req_ready_i,
input wire mem_rsp_valid_i, input wire mem_rsp_valid_i,
output wire[31:0] mem_wdata_o, // 写内存数据 output wire[31:0] mem_wdata_o, // 写内存数据
output wire[31:0] mem_addr_o, // 读、写内存地址 output wire[31:0] mem_addr_o, // 读、写内存地址
output wire mem_we_o, // 是否要写内存 output wire mem_we_o, // 是否要写内存
output wire[3:0] mem_sel_o, // 字节位 output wire[3:0] mem_sel_o, // 字节位
output wire mem_req_valid_o, output wire mem_req_valid_o,
output wire mem_rsp_ready_o, output wire mem_rsp_ready_o,
output wire mem_access_misaligned_o, output wire mem_access_misaligned_o,
// gpr_reg // gpr_reg
output wire[31:0] reg_wdata_o, // 写寄存器数据 output wire[31:0] reg_wdata_o, // 写寄存器数据
output wire reg_we_o, // 是否要写通用寄存器 output wire reg_we_o, // 是否要写通用寄存器
output wire[4:0] reg_waddr_o, // 写通用寄存器地址 output wire[4:0] reg_waddr_o, // 写通用寄存器地址
// csr_reg // csr_reg
input wire[31:0] csr_rdata_i, input wire[31:0] csr_rdata_i,
output wire[31:0] csr_raddr_o, // 读CSR寄存器地址 output wire[31:0] csr_raddr_o, // 读CSR寄存器地址
output wire[31:0] csr_wdata_o, // 写CSR寄存器数据 output wire[31:0] csr_wdata_o, // 写CSR寄存器数据
output wire csr_we_o, // 是否要写CSR寄存器 output wire csr_we_o, // 是否要写CSR寄存器
output wire[31:0] csr_waddr_o, // 写CSR寄存器地址 output wire[31:0] csr_waddr_o, // 写CSR寄存器地址
// to pipe_ctrl // to pipe_ctrl
output wire hold_flag_o, // 是否暂停标志 output wire hold_flag_o, // 是否暂停标志
output wire jump_flag_o, // 是否跳转标志 output wire jump_flag_o, // 是否跳转标志
output wire[31:0] jump_addr_o, // 跳转目的地址 output wire[31:0] jump_addr_o, // 跳转目的地址
// from idu_exu //
input wire[`DECINFO_WIDTH-1:0] dec_info_bus_i, output wire inst_valid_o,
input wire[31:0] dec_imm_i,
input wire[31:0] dec_pc_i, // from idu_exu
input wire[31:0] next_pc_i, input wire inst_valid_i,
input wire[4:0] rd_waddr_i, input wire[31:0] inst_i,
input wire[31:0] reg1_rdata_i, // 通用寄存器1输入数据 input wire[`DECINFO_WIDTH-1:0] dec_info_bus_i,
input wire[31:0] reg2_rdata_i, // 通用寄存器2输入数据 input wire[31:0] dec_imm_i,
input wire rd_we_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输入数据
// dispatch to ALU input wire[31:0] reg2_rdata_i, // 通用寄存器2输入数据
wire[31:0] alu_op1_o; input wire rd_we_i
wire[31:0] alu_op2_o;
wire req_alu_o; );
wire alu_op_lui_o;
wire alu_op_auipc_o; // dispatch to ALU
wire alu_op_add_o; wire[31:0] alu_op1_o;
wire alu_op_sub_o; wire[31:0] alu_op2_o;
wire alu_op_sll_o; wire req_alu_o;
wire alu_op_slt_o; wire alu_op_lui_o;
wire alu_op_sltu_o; wire alu_op_auipc_o;
wire alu_op_xor_o; wire alu_op_add_o;
wire alu_op_srl_o; wire alu_op_sub_o;
wire alu_op_sra_o; wire alu_op_sll_o;
wire alu_op_or_o; wire alu_op_slt_o;
wire alu_op_and_o; wire alu_op_sltu_o;
// dispatch to BJP wire alu_op_xor_o;
wire[31:0] bjp_op1_o; wire alu_op_srl_o;
wire[31:0] bjp_op2_o; wire alu_op_sra_o;
wire[31:0] bjp_jump_op1_o; wire alu_op_or_o;
wire[31:0] bjp_jump_op2_o; wire alu_op_and_o;
wire req_bjp_o; // dispatch to BJP
wire bjp_op_jump_o; wire[31:0] bjp_op1_o;
wire bjp_op_beq_o; wire[31:0] bjp_op2_o;
wire bjp_op_bne_o; wire[31:0] bjp_jump_op1_o;
wire bjp_op_blt_o; wire[31:0] bjp_jump_op2_o;
wire bjp_op_bltu_o; wire req_bjp_o;
wire bjp_op_bge_o; wire bjp_op_jump_o;
wire bjp_op_bgeu_o; wire bjp_op_beq_o;
// dispatch to MULDIV wire bjp_op_bne_o;
wire req_muldiv_o; wire bjp_op_blt_o;
wire[31:0] muldiv_op1_o; wire bjp_op_bltu_o;
wire[31:0] muldiv_op2_o; wire bjp_op_bge_o;
wire muldiv_op_mul_o; wire bjp_op_bgeu_o;
wire muldiv_op_mulh_o; // dispatch to MULDIV
wire muldiv_op_mulhsu_o; wire req_muldiv_o;
wire muldiv_op_mulhu_o; wire[31:0] muldiv_op1_o;
wire muldiv_op_div_o; wire[31:0] muldiv_op2_o;
wire muldiv_op_divu_o; wire muldiv_op_mul_o;
wire muldiv_op_rem_o; wire muldiv_op_mulh_o;
wire muldiv_op_remu_o; wire muldiv_op_mulhsu_o;
// dispatch to CSR wire muldiv_op_mulhu_o;
wire req_csr_o; wire muldiv_op_div_o;
wire[31:0] csr_op1_o; wire muldiv_op_divu_o;
wire[31:0] csr_addr_o; wire muldiv_op_rem_o;
wire csr_csrrw_o; wire muldiv_op_remu_o;
wire csr_csrrs_o; // dispatch to CSR
wire csr_csrrc_o; wire req_csr_o;
// dispatch to MEM wire[31:0] csr_op1_o;
wire req_mem_o; wire[31:0] csr_addr_o;
wire[31:0] mem_op1_o; wire csr_csrrw_o;
wire[31:0] mem_op2_o; wire csr_csrrs_o;
wire[31:0] mem_rs2_data_o; wire csr_csrrc_o;
wire mem_op_lb_o; // dispatch to MEM
wire mem_op_lh_o; wire req_mem_o;
wire mem_op_lw_o; wire[31:0] mem_op1_o;
wire mem_op_lbu_o; wire[31:0] mem_op2_o;
wire mem_op_lhu_o; wire[31:0] mem_rs2_data_o;
wire mem_op_sb_o; wire mem_op_lb_o;
wire mem_op_sh_o; wire mem_op_lh_o;
wire mem_op_sw_o; wire mem_op_lw_o;
// dispatch to SYS wire mem_op_lbu_o;
wire sys_op_nop_o; wire mem_op_lhu_o;
wire sys_op_mret_o; wire mem_op_sb_o;
wire sys_op_ecall_o; wire mem_op_sh_o;
wire sys_op_ebreak_o; wire mem_op_sw_o;
wire sys_op_fence_o; // dispatch to SYS
wire sys_op_nop_o;
exu_dispatch u_exu_dispatch( wire sys_op_mret_o;
// input wire sys_op_ecall_o;
.clk(clk), wire sys_op_ebreak_o;
.rst_n(rst_n), wire sys_op_fence_o;
.dec_info_bus_i(dec_info_bus_i),
.dec_imm_i(dec_imm_i), exu_dispatch u_exu_dispatch(
.dec_pc_i(dec_pc_i), // input
.rs1_rdata_i(reg1_rdata_i), .clk(clk),
.rs2_rdata_i(reg2_rdata_i), .rst_n(rst_n),
// dispatch to ALU .dec_info_bus_i(dec_info_bus_i),
.alu_op1_o(alu_op1_o), .dec_imm_i(dec_imm_i),
.alu_op2_o(alu_op2_o), .dec_pc_i(dec_pc_i),
.req_alu_o(req_alu_o), .rs1_rdata_i(reg1_rdata_i),
.alu_op_lui_o(alu_op_lui_o), .rs2_rdata_i(reg2_rdata_i),
.alu_op_auipc_o(alu_op_auipc_o), // dispatch to ALU
.alu_op_add_o(alu_op_add_o), .alu_op1_o(alu_op1_o),
.alu_op_sub_o(alu_op_sub_o), .alu_op2_o(alu_op2_o),
.alu_op_sll_o(alu_op_sll_o), .req_alu_o(req_alu_o),
.alu_op_slt_o(alu_op_slt_o), .alu_op_lui_o(alu_op_lui_o),
.alu_op_sltu_o(alu_op_sltu_o), .alu_op_auipc_o(alu_op_auipc_o),
.alu_op_xor_o(alu_op_xor_o), .alu_op_add_o(alu_op_add_o),
.alu_op_srl_o(alu_op_srl_o), .alu_op_sub_o(alu_op_sub_o),
.alu_op_sra_o(alu_op_sra_o), .alu_op_sll_o(alu_op_sll_o),
.alu_op_or_o(alu_op_or_o), .alu_op_slt_o(alu_op_slt_o),
.alu_op_and_o(alu_op_and_o), .alu_op_sltu_o(alu_op_sltu_o),
// dispatch to BJP .alu_op_xor_o(alu_op_xor_o),
.bjp_op1_o(bjp_op1_o), .alu_op_srl_o(alu_op_srl_o),
.bjp_op2_o(bjp_op2_o), .alu_op_sra_o(alu_op_sra_o),
.bjp_jump_op1_o(bjp_jump_op1_o), .alu_op_or_o(alu_op_or_o),
.bjp_jump_op2_o(bjp_jump_op2_o), .alu_op_and_o(alu_op_and_o),
.req_bjp_o(req_bjp_o), // dispatch to BJP
.bjp_op_jump_o(bjp_op_jump_o), .bjp_op1_o(bjp_op1_o),
.bjp_op_beq_o(bjp_op_beq_o), .bjp_op2_o(bjp_op2_o),
.bjp_op_bne_o(bjp_op_bne_o), .bjp_jump_op1_o(bjp_jump_op1_o),
.bjp_op_blt_o(bjp_op_blt_o), .bjp_jump_op2_o(bjp_jump_op2_o),
.bjp_op_bltu_o(bjp_op_bltu_o), .req_bjp_o(req_bjp_o),
.bjp_op_bge_o(bjp_op_bge_o), .bjp_op_jump_o(bjp_op_jump_o),
.bjp_op_bgeu_o(bjp_op_bgeu_o), .bjp_op_beq_o(bjp_op_beq_o),
// dispatch to MULDIV .bjp_op_bne_o(bjp_op_bne_o),
.req_muldiv_o(req_muldiv_o), .bjp_op_blt_o(bjp_op_blt_o),
.muldiv_op1_o(muldiv_op1_o), .bjp_op_bltu_o(bjp_op_bltu_o),
.muldiv_op2_o(muldiv_op2_o), .bjp_op_bge_o(bjp_op_bge_o),
.muldiv_op_mul_o(muldiv_op_mul_o), .bjp_op_bgeu_o(bjp_op_bgeu_o),
.muldiv_op_mulh_o(muldiv_op_mulh_o), // dispatch to MULDIV
.muldiv_op_mulhsu_o(muldiv_op_mulhsu_o), .req_muldiv_o(req_muldiv_o),
.muldiv_op_mulhu_o(muldiv_op_mulhu_o), .muldiv_op1_o(muldiv_op1_o),
.muldiv_op_div_o(muldiv_op_div_o), .muldiv_op2_o(muldiv_op2_o),
.muldiv_op_divu_o(muldiv_op_divu_o), .muldiv_op_mul_o(muldiv_op_mul_o),
.muldiv_op_rem_o(muldiv_op_rem_o), .muldiv_op_mulh_o(muldiv_op_mulh_o),
.muldiv_op_remu_o(muldiv_op_remu_o), .muldiv_op_mulhsu_o(muldiv_op_mulhsu_o),
// dispatch to CSR .muldiv_op_mulhu_o(muldiv_op_mulhu_o),
.req_csr_o(req_csr_o), .muldiv_op_div_o(muldiv_op_div_o),
.csr_op1_o(csr_op1_o), .muldiv_op_divu_o(muldiv_op_divu_o),
.csr_addr_o(csr_addr_o), .muldiv_op_rem_o(muldiv_op_rem_o),
.csr_csrrw_o(csr_csrrw_o), .muldiv_op_remu_o(muldiv_op_remu_o),
.csr_csrrs_o(csr_csrrs_o), // dispatch to CSR
.csr_csrrc_o(csr_csrrc_o), .req_csr_o(req_csr_o),
// dispatch to MEM .csr_op1_o(csr_op1_o),
.req_mem_o(req_mem_o), .csr_addr_o(csr_addr_o),
.mem_op1_o(mem_op1_o), .csr_csrrw_o(csr_csrrw_o),
.mem_op2_o(mem_op2_o), .csr_csrrs_o(csr_csrrs_o),
.mem_rs2_data_o(mem_rs2_data_o), .csr_csrrc_o(csr_csrrc_o),
.mem_op_lb_o(mem_op_lb_o), // dispatch to MEM
.mem_op_lh_o(mem_op_lh_o), .req_mem_o(req_mem_o),
.mem_op_lw_o(mem_op_lw_o), .mem_op1_o(mem_op1_o),
.mem_op_lbu_o(mem_op_lbu_o), .mem_op2_o(mem_op2_o),
.mem_op_lhu_o(mem_op_lhu_o), .mem_rs2_data_o(mem_rs2_data_o),
.mem_op_sb_o(mem_op_sb_o), .mem_op_lb_o(mem_op_lb_o),
.mem_op_sh_o(mem_op_sh_o), .mem_op_lh_o(mem_op_lh_o),
.mem_op_sw_o(mem_op_sw_o), .mem_op_lw_o(mem_op_lw_o),
// dispatch to SYS .mem_op_lbu_o(mem_op_lbu_o),
.sys_op_nop_o(sys_op_nop_o), .mem_op_lhu_o(mem_op_lhu_o),
.sys_op_mret_o(sys_op_mret_o), .mem_op_sb_o(mem_op_sb_o),
.sys_op_ecall_o(sys_op_ecall_o), .mem_op_sh_o(mem_op_sh_o),
.sys_op_ebreak_o(sys_op_ebreak_o), .mem_op_sw_o(mem_op_sw_o),
.sys_op_fence_o(sys_op_fence_o) // dispatch to SYS
); .sys_op_nop_o(sys_op_nop_o),
.sys_op_mret_o(sys_op_mret_o),
assign inst_ecall_o = sys_op_ecall_o; .sys_op_ecall_o(sys_op_ecall_o),
assign inst_ebreak_o = sys_op_ebreak_o; .sys_op_ebreak_o(sys_op_ebreak_o),
assign inst_mret_o = sys_op_mret_o; .sys_op_fence_o(sys_op_fence_o)
);
wire[31:0] alu_res_o;
wire[31:0] bjp_res_o; assign inst_ecall_o = sys_op_ecall_o;
wire bjp_cmp_res_o; assign inst_ebreak_o = sys_op_ebreak_o;
wire[31:0] csr_op1 = csr_csrrc_o? (~csr_op1_o): csr_op1_o; assign inst_mret_o = sys_op_mret_o;
wire[31:0] csr_op2 = csr_csrrw_o? (32'h0): csr_rdata_i;
wire[31:0] alu_res_o;
exu_alu_datapath u_exu_alu_datapath( wire[31:0] bjp_res_o;
.clk(clk), wire bjp_cmp_res_o;
.rst_n(rst_n), wire[31:0] csr_op1 = csr_csrrc_o? (~csr_op1_o): csr_op1_o;
// ALU wire[31:0] csr_op2 = csr_csrrw_o? (32'h0): csr_rdata_i;
.req_alu_i(req_alu_o),
.alu_op1_i(alu_op1_o), exu_alu_datapath u_exu_alu_datapath(
.alu_op2_i(alu_op2_o), .clk(clk),
.alu_op_add_i(alu_op_add_o | alu_op_lui_o | alu_op_auipc_o), .rst_n(rst_n),
.alu_op_sub_i(alu_op_sub_o), // ALU
.alu_op_sll_i(alu_op_sll_o), .req_alu_i(req_alu_o),
.alu_op_slt_i(alu_op_slt_o), .alu_op1_i(alu_op1_o),
.alu_op_sltu_i(alu_op_sltu_o), .alu_op2_i(alu_op2_o),
.alu_op_xor_i(alu_op_xor_o), .alu_op_add_i(alu_op_add_o | alu_op_lui_o | alu_op_auipc_o),
.alu_op_srl_i(alu_op_srl_o), .alu_op_sub_i(alu_op_sub_o),
.alu_op_sra_i(alu_op_sra_o), .alu_op_sll_i(alu_op_sll_o),
.alu_op_or_i(alu_op_or_o), .alu_op_slt_i(alu_op_slt_o),
.alu_op_and_i(alu_op_and_o), .alu_op_sltu_i(alu_op_sltu_o),
// BJP .alu_op_xor_i(alu_op_xor_o),
.req_bjp_i(req_bjp_o), .alu_op_srl_i(alu_op_srl_o),
.bjp_op1_i(bjp_op1_o), .alu_op_sra_i(alu_op_sra_o),
.bjp_op2_i(bjp_op2_o), .alu_op_or_i(alu_op_or_o),
.bjp_op_beq_i(bjp_op_beq_o), .alu_op_and_i(alu_op_and_o),
.bjp_op_bne_i(bjp_op_bne_o), // BJP
.bjp_op_blt_i(bjp_op_blt_o), .req_bjp_i(req_bjp_o),
.bjp_op_bltu_i(bjp_op_bltu_o), .bjp_op1_i(bjp_op1_o),
.bjp_op_bge_i(bjp_op_bge_o), .bjp_op2_i(bjp_op2_o),
.bjp_op_bgeu_i(bjp_op_bgeu_o), .bjp_op_beq_i(bjp_op_beq_o),
.bjp_op_jump_i(bjp_op_jump_o), .bjp_op_bne_i(bjp_op_bne_o),
.bjp_jump_op1_i(bjp_jump_op1_o), .bjp_op_blt_i(bjp_op_blt_o),
.bjp_jump_op2_i(bjp_jump_op2_o), .bjp_op_bltu_i(bjp_op_bltu_o),
// MEM .bjp_op_bge_i(bjp_op_bge_o),
.req_mem_i(req_mem_o), .bjp_op_bgeu_i(bjp_op_bgeu_o),
.mem_op1_i(mem_op1_o), .bjp_op_jump_i(bjp_op_jump_o),
.mem_op2_i(mem_op2_o), .bjp_jump_op1_i(bjp_jump_op1_o),
// CSR .bjp_jump_op2_i(bjp_jump_op2_o),
.req_csr_i(req_csr_o), // MEM
.csr_op1_i(csr_op1), .req_mem_i(req_mem_o),
.csr_op2_i(csr_op2), .mem_op1_i(mem_op1_o),
.csr_csrrw_i(csr_csrrw_o), .mem_op2_i(mem_op2_o),
.csr_csrrs_i(csr_csrrs_o), // CSR
.csr_csrrc_i(csr_csrrc_o), .req_csr_i(req_csr_o),
.csr_op1_i(csr_op1),
.alu_res_o(alu_res_o), .csr_op2_i(csr_op2),
.bjp_res_o(bjp_res_o), .csr_csrrw_i(csr_csrrw_o),
.bjp_cmp_res_o(bjp_cmp_res_o) .csr_csrrs_i(csr_csrrs_o),
); .csr_csrrc_i(csr_csrrc_o),
wire mem_reg_we_o; .alu_res_o(alu_res_o),
wire mem_mem_we_o; .bjp_res_o(bjp_res_o),
wire[31:0] mem_wdata; .bjp_cmp_res_o(bjp_cmp_res_o)
wire mem_stall_o; );
exu_mem u_exu_mem( wire mem_reg_we_o;
.clk(clk), wire mem_mem_we_o;
.rst_n(rst_n), wire[31:0] mem_wdata;
.req_mem_i(req_mem_o), wire mem_stall_o;
.mem_addr_i(alu_res_o),
.mem_rs2_data_i(mem_rs2_data_o), exu_mem u_exu_mem(
.mem_req_ready_i(mem_req_ready_i), .clk(clk),
.mem_rsp_valid_i(mem_rsp_valid_i), .rst_n(rst_n),
.mem_rdata_i(mem_rdata_i), .req_mem_i(req_mem_o),
.mem_op_lb_i(mem_op_lb_o), .mem_addr_i(alu_res_o),
.mem_op_lh_i(mem_op_lh_o), .mem_rs2_data_i(mem_rs2_data_o),
.mem_op_lw_i(mem_op_lw_o), .mem_req_ready_i(mem_req_ready_i),
.mem_op_lbu_i(mem_op_lbu_o), .mem_rsp_valid_i(mem_rsp_valid_i),
.mem_op_lhu_i(mem_op_lhu_o), .mem_rdata_i(mem_rdata_i),
.mem_op_sb_i(mem_op_sb_o), .mem_op_lb_i(mem_op_lb_o),
.mem_op_sh_i(mem_op_sh_o), .mem_op_lh_i(mem_op_lh_o),
.mem_op_sw_i(mem_op_sw_o), .mem_op_lw_i(mem_op_lw_o),
.mem_access_misaligned_o(mem_access_misaligned_o), .mem_op_lbu_i(mem_op_lbu_o),
.mem_stall_o(mem_stall_o), .mem_op_lhu_i(mem_op_lhu_o),
.mem_addr_o(mem_addr_o), .mem_op_sb_i(mem_op_sb_o),
.mem_wdata_o(mem_wdata), .mem_op_sh_i(mem_op_sh_o),
.mem_reg_we_o(mem_reg_we_o), .mem_op_sw_i(mem_op_sw_o),
.mem_mem_we_o(mem_mem_we_o), .mem_access_misaligned_o(mem_access_misaligned_o),
.mem_sel_o(mem_sel_o), .mem_stall_o(mem_stall_o),
.mem_req_valid_o(mem_req_valid_o), .mem_addr_o(mem_addr_o),
.mem_rsp_ready_o(mem_rsp_ready_o) .mem_wdata_o(mem_wdata),
); .mem_reg_we_o(mem_reg_we_o),
.mem_mem_we_o(mem_mem_we_o),
wire[31:0] muldiv_reg_wdata_o; .mem_sel_o(mem_sel_o),
wire muldiv_reg_we_o; .mem_req_valid_o(mem_req_valid_o),
wire muldiv_stall_o; .mem_rsp_ready_o(mem_rsp_ready_o)
);
exu_muldiv u_exu_muldiv(
.clk(clk), wire[31:0] muldiv_reg_wdata_o;
.rst_n(rst_n), wire muldiv_reg_we_o;
.muldiv_op1_i(muldiv_op1_o), wire muldiv_stall_o;
.muldiv_op2_i(muldiv_op2_o),
.muldiv_op_mul_i(muldiv_op_mul_o), exu_muldiv u_exu_muldiv(
.muldiv_op_mulh_i(muldiv_op_mulh_o), .clk(clk),
.muldiv_op_mulhsu_i(muldiv_op_mulhsu_o), .rst_n(rst_n),
.muldiv_op_mulhu_i(muldiv_op_mulhu_o), .muldiv_op1_i(muldiv_op1_o),
.muldiv_op_div_i(muldiv_op_div_o), .muldiv_op2_i(muldiv_op2_o),
.muldiv_op_divu_i(muldiv_op_divu_o), .muldiv_op_mul_i(muldiv_op_mul_o),
.muldiv_op_rem_i(muldiv_op_rem_o), .muldiv_op_mulh_i(muldiv_op_mulh_o),
.muldiv_op_remu_i(muldiv_op_remu_o), .muldiv_op_mulhsu_i(muldiv_op_mulhsu_o),
.muldiv_reg_wdata_o(muldiv_reg_wdata_o), .muldiv_op_mulhu_i(muldiv_op_mulhu_o),
.muldiv_reg_we_o(muldiv_reg_we_o), .muldiv_op_div_i(muldiv_op_div_o),
.muldiv_stall_o(muldiv_stall_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),
wire commit_reg_we_o; .muldiv_reg_wdata_o(muldiv_reg_wdata_o),
.muldiv_reg_we_o(muldiv_reg_we_o),
exu_commit u_exu_commit( .muldiv_stall_o(muldiv_stall_o)
.clk(clk), );
.rst_n(rst_n),
.req_muldiv_i(req_muldiv_o), wire commit_reg_we_o;
.muldiv_reg_we_i(muldiv_reg_we_o),
.muldiv_reg_waddr_i(rd_waddr_i), exu_commit u_exu_commit(
.muldiv_reg_wdata_i(muldiv_reg_wdata_o), .clk(clk),
.req_mem_i(req_mem_o), .rst_n(rst_n),
.mem_reg_we_i(mem_reg_we_o), .req_muldiv_i(req_muldiv_o),
.mem_reg_waddr_i(rd_waddr_i), .muldiv_reg_we_i(muldiv_reg_we_o),
.mem_reg_wdata_i(mem_wdata), .muldiv_reg_waddr_i(rd_waddr_i),
.req_csr_i(req_csr_o), .muldiv_reg_wdata_i(muldiv_reg_wdata_o),
.csr_reg_we_i(req_csr_o), .req_mem_i(req_mem_o),
.csr_reg_waddr_i(rd_waddr_i), .mem_reg_we_i(mem_reg_we_o),
.csr_reg_wdata_i(csr_rdata_i), .mem_reg_waddr_i(rd_waddr_i),
.req_bjp_i(req_bjp_o), .mem_reg_wdata_i(mem_wdata),
.bjp_reg_we_i(bjp_op_jump_o), .req_csr_i(req_csr_o),
.bjp_reg_wdata_i(next_pc_i), .csr_reg_we_i(req_csr_o),
.bjp_reg_waddr_i(rd_waddr_i), .csr_reg_waddr_i(rd_waddr_i),
.rd_we_i(rd_we_i), .csr_reg_wdata_i(csr_rdata_i),
.rd_waddr_i(rd_waddr_i), .req_bjp_i(req_bjp_o),
.alu_reg_wdata_i(alu_res_o), .bjp_reg_we_i(bjp_op_jump_o),
.reg_we_o(commit_reg_we_o), .bjp_reg_wdata_i(next_pc_i),
.reg_waddr_o(reg_waddr_o), .bjp_reg_waddr_i(rd_waddr_i),
.reg_wdata_o(reg_wdata_o) .rd_we_i(rd_we_i),
); .rd_waddr_i(rd_waddr_i),
.alu_reg_wdata_i(alu_res_o),
assign reg_we_o = commit_reg_we_o; .reg_we_o(commit_reg_we_o),
.reg_waddr_o(reg_waddr_o),
assign jump_flag_o = bjp_cmp_res_o | bjp_op_jump_o | sys_op_fence_o | int_assert_i; .reg_wdata_o(reg_wdata_o)
assign jump_addr_o = int_assert_i? int_addr_i: );
sys_op_fence_o? next_pc_i:
bjp_res_o; assign reg_we_o = commit_reg_we_o;
assign hold_flag_o = muldiv_stall_o | mem_stall_o;
assign jump_flag_o = bjp_cmp_res_o | bjp_op_jump_o | sys_op_fence_o | int_assert_i;
assign csr_raddr_o = csr_addr_o; assign jump_addr_o = int_assert_i? int_addr_i:
assign csr_waddr_o = csr_addr_o; sys_op_fence_o? next_pc_i:
assign csr_we_o = req_csr_o; bjp_res_o;
assign csr_wdata_o = alu_res_o; assign hold_flag_o = muldiv_stall_o | mem_stall_o;
assign mem_we_o = mem_mem_we_o; assign csr_raddr_o = csr_addr_o;
assign mem_wdata_o = mem_wdata; assign csr_waddr_o = csr_addr_o;
assign csr_we_o = req_csr_o;
endmodule 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

View File

@ -1,254 +1,254 @@
/* /*
Copyright 2020 Blue Liang, liangkangnan@163.com Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
`include "defines.sv" `include "defines.sv"
`define DATAPATH_MUX_WIDTH (32+32+16) `define DATAPATH_MUX_WIDTH (32+32+16)
module exu_alu_datapath( module exu_alu_datapath(
input wire clk, input wire clk,
input wire rst_n, input wire rst_n,
// ALU // ALU
input wire req_alu_i, input wire req_alu_i,
input wire[31:0] alu_op1_i, input wire[31:0] alu_op1_i,
input wire[31:0] alu_op2_i, input wire[31:0] alu_op2_i,
input wire alu_op_add_i, input wire alu_op_add_i,
input wire alu_op_sub_i, input wire alu_op_sub_i,
input wire alu_op_sll_i, input wire alu_op_sll_i,
input wire alu_op_slt_i, input wire alu_op_slt_i,
input wire alu_op_sltu_i, input wire alu_op_sltu_i,
input wire alu_op_xor_i, input wire alu_op_xor_i,
input wire alu_op_srl_i, input wire alu_op_srl_i,
input wire alu_op_sra_i, input wire alu_op_sra_i,
input wire alu_op_or_i, input wire alu_op_or_i,
input wire alu_op_and_i, input wire alu_op_and_i,
// BJP // BJP
input wire req_bjp_i, input wire req_bjp_i,
input wire[31:0] bjp_op1_i, input wire[31:0] bjp_op1_i,
input wire[31:0] bjp_op2_i, input wire[31:0] bjp_op2_i,
input wire bjp_op_beq_i, input wire bjp_op_beq_i,
input wire bjp_op_bne_i, input wire bjp_op_bne_i,
input wire bjp_op_blt_i, input wire bjp_op_blt_i,
input wire bjp_op_bltu_i, input wire bjp_op_bltu_i,
input wire bjp_op_bge_i, input wire bjp_op_bge_i,
input wire bjp_op_bgeu_i, input wire bjp_op_bgeu_i,
input wire bjp_op_jump_i, input wire bjp_op_jump_i,
input wire[31:0] bjp_jump_op1_i, input wire[31:0] bjp_jump_op1_i,
input wire[31:0] bjp_jump_op2_i, input wire[31:0] bjp_jump_op2_i,
// MEM // MEM
input wire req_mem_i, input wire req_mem_i,
input wire[31:0] mem_op1_i, input wire[31:0] mem_op1_i,
input wire[31:0] mem_op2_i, input wire[31:0] mem_op2_i,
// CSR // CSR
input wire req_csr_i, input wire req_csr_i,
input wire[31:0] csr_op1_i, input wire[31:0] csr_op1_i,
input wire[31:0] csr_op2_i, input wire[31:0] csr_op2_i,
input wire csr_csrrw_i, input wire csr_csrrw_i,
input wire csr_csrrs_i, input wire csr_csrrs_i,
input wire csr_csrrc_i, input wire csr_csrrc_i,
output wire[31:0] alu_res_o, output wire[31:0] alu_res_o,
output wire[31:0] bjp_res_o, output wire[31:0] bjp_res_o,
output wire bjp_cmp_res_o output wire bjp_cmp_res_o
); );
wire[31:0] mux_op1; wire[31:0] mux_op1;
wire[31:0] mux_op2; wire[31:0] mux_op2;
wire op_add; wire op_add;
wire op_sub; wire op_sub;
wire op_sll; wire op_sll;
wire op_slt; wire op_slt;
wire op_sltu; wire op_sltu;
wire op_xor; wire op_xor;
wire op_srl; wire op_srl;
wire op_sra; wire op_sra;
wire op_or; wire op_or;
wire op_and; wire op_and;
wire op_beq; wire op_beq;
wire op_bne; wire op_bne;
wire op_blt; wire op_blt;
wire op_bltu; wire op_bltu;
wire op_bge; wire op_bge;
wire op_bgeu; wire op_bgeu;
// 异或 // 异或
wire[31:0] xor_res = mux_op1 ^ mux_op2; wire[31:0] xor_res = mux_op1 ^ mux_op2;
// 或 // 或
wire[31:0] or_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] and_res = mux_op1 & mux_op2;
// 加、减 // 加、减
wire[31:0] add_op1 = req_bjp_i? bjp_jump_op1_i: mux_op1; 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_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] 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] sll_res = mux_op1 << mux_op2[4:0];
// 逻辑右移 // 逻辑右移
wire[31:0] srl_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] 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[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_signed = ($signed(mux_op1) >= $signed(mux_op2));
// 无符号数比较 // 无符号数比较
wire op1_ge_op2_unsigned = (mux_op1 >= mux_op2); wire op1_ge_op2_unsigned = (mux_op1 >= mux_op2);
wire op1_neq_op2 = (|xor_res); wire op1_neq_op2 = (|xor_res);
wire op1_eq_op2 = (~op1_neq_op2); wire op1_eq_op2 = (~op1_neq_op2);
wire cmp_res_eq = op_beq & op1_eq_op2; wire cmp_res_eq = op_beq & op1_eq_op2;
wire cmp_res_neq = op_bne & op1_neq_op2; wire cmp_res_neq = op_bne & op1_neq_op2;
wire cmp_res_lt = op_blt & (~op1_ge_op2_signed); wire cmp_res_lt = op_blt & (~op1_ge_op2_signed);
wire cmp_res_ltu = op_bltu & (~op1_ge_op2_unsigned); wire cmp_res_ltu = op_bltu & (~op1_ge_op2_unsigned);
wire cmp_res_gt = op_bge & op1_ge_op2_signed; wire cmp_res_gt = op_bge & op1_ge_op2_signed;
wire cmp_res_gtu = op_bgeu & op1_ge_op2_unsigned; 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] slt_res = (~op1_ge_op2_signed)? 32'h1: 32'h0;
wire[31:0] sltu_res = (~op1_ge_op2_unsigned)? 32'h1: 32'h0; wire[31:0] sltu_res = (~op1_ge_op2_unsigned)? 32'h1: 32'h0;
reg[31:0] alu_datapath_res; reg[31:0] alu_datapath_res;
always @ (*) begin always @ (*) begin
alu_datapath_res = 32'h0; alu_datapath_res = 32'h0;
case (1'b1) case (1'b1)
op_xor: alu_datapath_res = xor_res; op_xor: alu_datapath_res = xor_res;
op_or: alu_datapath_res = or_res; op_or: alu_datapath_res = or_res;
op_and: alu_datapath_res = and_res; op_and: alu_datapath_res = and_res;
op_add: alu_datapath_res = add_sub_res; op_add: alu_datapath_res = add_sub_res;
op_sub: alu_datapath_res = add_sub_res; op_sub: alu_datapath_res = add_sub_res;
op_sll: alu_datapath_res = sll_res; op_sll: alu_datapath_res = sll_res;
op_srl: alu_datapath_res = srl_res; op_srl: alu_datapath_res = srl_res;
op_sra: alu_datapath_res = sra_res; op_sra: alu_datapath_res = sra_res;
op_slt: alu_datapath_res = slt_res; op_slt: alu_datapath_res = slt_res;
op_sltu: alu_datapath_res = sltu_res; op_sltu: alu_datapath_res = sltu_res;
endcase endcase
end end
assign alu_res_o = alu_datapath_res; assign alu_res_o = alu_datapath_res;
assign bjp_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 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, assign {mux_op1,
mux_op2, mux_op2,
op_add, op_add,
op_sub, op_sub,
op_sll, op_sll,
op_slt, op_slt,
op_sltu, op_sltu,
op_xor, op_xor,
op_srl, op_srl,
op_sra, op_sra,
op_or, op_or,
op_and, op_and,
op_beq, op_beq,
op_bne, op_bne,
op_blt, op_blt,
op_bltu, op_bltu,
op_bge, op_bge,
op_bgeu op_bgeu
} = ({`DATAPATH_MUX_WIDTH{req_alu_i}} & { } = ({`DATAPATH_MUX_WIDTH{req_alu_i}} & {
alu_op1_i, alu_op1_i,
alu_op2_i, alu_op2_i,
alu_op_add_i, alu_op_add_i,
alu_op_sub_i, alu_op_sub_i,
alu_op_sll_i, alu_op_sll_i,
alu_op_slt_i, alu_op_slt_i,
alu_op_sltu_i, alu_op_sltu_i,
alu_op_xor_i, alu_op_xor_i,
alu_op_srl_i, alu_op_srl_i,
alu_op_sra_i, alu_op_sra_i,
alu_op_or_i, alu_op_or_i,
alu_op_and_i, alu_op_and_i,
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_bjp_i}} & { ({`DATAPATH_MUX_WIDTH{req_bjp_i}} & {
bjp_op1_i, bjp_op1_i,
bjp_op2_i, bjp_op2_i,
1'b1, 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, 1'b0,
1'b0, 1'b0,
bjp_op_beq_i, bjp_op_beq_i,
bjp_op_bne_i, bjp_op_bne_i,
bjp_op_blt_i, bjp_op_blt_i,
bjp_op_bltu_i, bjp_op_bltu_i,
bjp_op_bge_i, bjp_op_bge_i,
bjp_op_bgeu_i bjp_op_bgeu_i
}) | }) |
({`DATAPATH_MUX_WIDTH{req_mem_i}} & { ({`DATAPATH_MUX_WIDTH{req_mem_i}} & {
mem_op1_i, mem_op1_i,
mem_op2_i, mem_op2_i,
1'b1, 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, 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}} & { ({`DATAPATH_MUX_WIDTH{req_csr_i}} & {
csr_op1_i, csr_op1_i,
csr_op2_i, csr_op2_i,
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, 1'b0,
csr_csrrw_i | csr_csrrs_i, csr_csrrw_i | csr_csrrs_i,
csr_csrrc_i, csr_csrrc_i,
1'b0, 1'b0,
1'b0, 1'b0,
1'b0, 1'b0,
1'b0, 1'b0,
1'b0, 1'b0,
1'b0 1'b0
}); });
endmodule endmodule

View File

@ -1,92 +1,92 @@
/* /*
Copyright 2020 Blue Liang, liangkangnan@163.com Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
`include "defines.sv" `include "defines.sv"
module exu_commit( module exu_commit(
input wire clk, input wire clk,
input wire rst_n, input wire rst_n,
input wire req_muldiv_i, input wire req_muldiv_i,
input wire muldiv_reg_we_i, input wire muldiv_reg_we_i,
input wire[4:0] muldiv_reg_waddr_i, input wire[4:0] muldiv_reg_waddr_i,
input wire[31:0] muldiv_reg_wdata_i, input wire[31:0] muldiv_reg_wdata_i,
input wire req_mem_i, input wire req_mem_i,
input wire mem_reg_we_i, input wire mem_reg_we_i,
input wire[4:0] mem_reg_waddr_i, input wire[4:0] mem_reg_waddr_i,
input wire[31:0] mem_reg_wdata_i, input wire[31:0] mem_reg_wdata_i,
input wire req_csr_i, input wire req_csr_i,
input wire csr_reg_we_i, input wire csr_reg_we_i,
input wire[4:0] csr_reg_waddr_i, input wire[4:0] csr_reg_waddr_i,
input wire[31:0] csr_reg_wdata_i, input wire[31:0] csr_reg_wdata_i,
input wire req_bjp_i, input wire req_bjp_i,
input wire bjp_reg_we_i, input wire bjp_reg_we_i,
input wire[31:0] bjp_reg_wdata_i, input wire[31:0] bjp_reg_wdata_i,
input wire[4:0] bjp_reg_waddr_i, input wire[4:0] bjp_reg_waddr_i,
input wire rd_we_i, input wire rd_we_i,
input wire[4:0] rd_waddr_i, input wire[4:0] rd_waddr_i,
input wire[31:0] alu_reg_wdata_i, input wire[31:0] alu_reg_wdata_i,
output wire reg_we_o, output wire reg_we_o,
output wire[4:0] reg_waddr_o, output wire[4:0] reg_waddr_o,
output wire[31:0] reg_wdata_o output wire[31:0] reg_wdata_o
); );
wire use_alu_res = (~req_muldiv_i) & wire use_alu_res = (~req_muldiv_i) &
(~req_mem_i) & (~req_mem_i) &
(~req_csr_i) & (~req_csr_i) &
(~req_bjp_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; 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; reg[4:0] reg_waddr;
always @ (*) begin always @ (*) begin
reg_waddr = 5'h0; reg_waddr = 5'h0;
case (1'b1) case (1'b1)
muldiv_reg_we_i: reg_waddr = muldiv_reg_waddr_i; muldiv_reg_we_i: reg_waddr = muldiv_reg_waddr_i;
mem_reg_we_i: reg_waddr = mem_reg_waddr_i; mem_reg_we_i: reg_waddr = mem_reg_waddr_i;
csr_reg_we_i: reg_waddr = csr_reg_waddr_i; csr_reg_we_i: reg_waddr = csr_reg_waddr_i;
bjp_reg_we_i: reg_waddr = bjp_reg_waddr_i; bjp_reg_we_i: reg_waddr = bjp_reg_waddr_i;
rd_we_i: reg_waddr = rd_waddr_i; rd_we_i: reg_waddr = rd_waddr_i;
endcase endcase
end end
assign reg_waddr_o = reg_waddr; assign reg_waddr_o = reg_waddr;
reg[31:0] reg_wdata; reg[31:0] reg_wdata;
always @ (*) begin always @ (*) begin
reg_wdata = 32'h0; reg_wdata = 32'h0;
case (1'b1) case (1'b1)
muldiv_reg_we_i: reg_wdata = muldiv_reg_wdata_i; muldiv_reg_we_i: reg_wdata = muldiv_reg_wdata_i;
mem_reg_we_i: reg_wdata = mem_reg_wdata_i; mem_reg_we_i: reg_wdata = mem_reg_wdata_i;
csr_reg_we_i: reg_wdata = csr_reg_wdata_i; csr_reg_we_i: reg_wdata = csr_reg_wdata_i;
bjp_reg_we_i: reg_wdata = bjp_reg_wdata_i; bjp_reg_we_i: reg_wdata = bjp_reg_wdata_i;
use_alu_res: reg_wdata = alu_reg_wdata_i; use_alu_res: reg_wdata = alu_reg_wdata_i;
endcase endcase
end end
assign reg_wdata_o = reg_wdata; assign reg_wdata_o = reg_wdata;
endmodule endmodule

View File

@ -1,210 +1,210 @@
/* /*
Copyright 2020 Blue Liang, liangkangnan@163.com Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
`include "defines.sv" `include "defines.sv"
module exu_dispatch( module exu_dispatch(
input wire clk, input wire clk,
input wire rst_n, input wire rst_n,
input wire[`DECINFO_WIDTH-1:0] dec_info_bus_i, input wire[`DECINFO_WIDTH-1:0] dec_info_bus_i,
input wire[31:0] dec_imm_i, input wire[31:0] dec_imm_i,
input wire[31:0] dec_pc_i, input wire[31:0] dec_pc_i,
input wire[31:0] rs1_rdata_i, input wire[31:0] rs1_rdata_i,
input wire[31:0] rs2_rdata_i, input wire[31:0] rs2_rdata_i,
// dispatch to ALU // dispatch to ALU
output wire req_alu_o, output wire req_alu_o,
output wire[31:0] alu_op1_o, output wire[31:0] alu_op1_o,
output wire[31:0] alu_op2_o, output wire[31:0] alu_op2_o,
output wire alu_op_lui_o, output wire alu_op_lui_o,
output wire alu_op_auipc_o, output wire alu_op_auipc_o,
output wire alu_op_add_o, output wire alu_op_add_o,
output wire alu_op_sub_o, output wire alu_op_sub_o,
output wire alu_op_sll_o, output wire alu_op_sll_o,
output wire alu_op_slt_o, output wire alu_op_slt_o,
output wire alu_op_sltu_o, output wire alu_op_sltu_o,
output wire alu_op_xor_o, output wire alu_op_xor_o,
output wire alu_op_srl_o, output wire alu_op_srl_o,
output wire alu_op_sra_o, output wire alu_op_sra_o,
output wire alu_op_or_o, output wire alu_op_or_o,
output wire alu_op_and_o, output wire alu_op_and_o,
// dispatch to BJP // dispatch to BJP
output wire req_bjp_o, output wire req_bjp_o,
output wire[31:0] bjp_op1_o, output wire[31:0] bjp_op1_o,
output wire[31:0] bjp_op2_o, output wire[31:0] bjp_op2_o,
output wire[31:0] bjp_jump_op1_o, output wire[31:0] bjp_jump_op1_o,
output wire[31:0] bjp_jump_op2_o, output wire[31:0] bjp_jump_op2_o,
output wire bjp_op_jump_o, output wire bjp_op_jump_o,
output wire bjp_op_beq_o, output wire bjp_op_beq_o,
output wire bjp_op_bne_o, output wire bjp_op_bne_o,
output wire bjp_op_blt_o, output wire bjp_op_blt_o,
output wire bjp_op_bltu_o, output wire bjp_op_bltu_o,
output wire bjp_op_bge_o, output wire bjp_op_bge_o,
output wire bjp_op_bgeu_o, output wire bjp_op_bgeu_o,
// dispatch to MULDIV // dispatch to MULDIV
output wire req_muldiv_o, output wire req_muldiv_o,
output wire[31:0] muldiv_op1_o, output wire[31:0] muldiv_op1_o,
output wire[31:0] muldiv_op2_o, output wire[31:0] muldiv_op2_o,
output wire muldiv_op_mul_o, output wire muldiv_op_mul_o,
output wire muldiv_op_mulh_o, output wire muldiv_op_mulh_o,
output wire muldiv_op_mulhsu_o, output wire muldiv_op_mulhsu_o,
output wire muldiv_op_mulhu_o, output wire muldiv_op_mulhu_o,
output wire muldiv_op_div_o, output wire muldiv_op_div_o,
output wire muldiv_op_divu_o, output wire muldiv_op_divu_o,
output wire muldiv_op_rem_o, output wire muldiv_op_rem_o,
output wire muldiv_op_remu_o, output wire muldiv_op_remu_o,
// dispatch to CSR // dispatch to CSR
output wire req_csr_o, output wire req_csr_o,
output wire[31:0] csr_op1_o, output wire[31:0] csr_op1_o,
output wire[31:0] csr_addr_o, output wire[31:0] csr_addr_o,
output wire csr_csrrw_o, output wire csr_csrrw_o,
output wire csr_csrrs_o, output wire csr_csrrs_o,
output wire csr_csrrc_o, output wire csr_csrrc_o,
// dispatch to MEM // dispatch to MEM
output wire req_mem_o, output wire req_mem_o,
output wire[31:0] mem_op1_o, output wire[31:0] mem_op1_o,
output wire[31:0] mem_op2_o, output wire[31:0] mem_op2_o,
output wire[31:0] mem_rs2_data_o, output wire[31:0] mem_rs2_data_o,
output wire mem_op_lb_o, output wire mem_op_lb_o,
output wire mem_op_lh_o, output wire mem_op_lh_o,
output wire mem_op_lw_o, output wire mem_op_lw_o,
output wire mem_op_lbu_o, output wire mem_op_lbu_o,
output wire mem_op_lhu_o, output wire mem_op_lhu_o,
output wire mem_op_sb_o, output wire mem_op_sb_o,
output wire mem_op_sh_o, output wire mem_op_sh_o,
output wire mem_op_sw_o, output wire mem_op_sw_o,
// dispatch to SYS // dispatch to SYS
output wire sys_op_nop_o, output wire sys_op_nop_o,
output wire sys_op_mret_o, output wire sys_op_mret_o,
output wire sys_op_ecall_o, output wire sys_op_ecall_o,
output wire sys_op_ebreak_o, output wire sys_op_ebreak_o,
output wire sys_op_fence_o output wire sys_op_fence_o
); );
wire[`DECINFO_GRP_WIDTH-1:0] disp_info_grp = dec_info_bus_i[`DECINFO_GRP_BUS]; wire[`DECINFO_GRP_WIDTH-1:0] disp_info_grp = dec_info_bus_i[`DECINFO_GRP_BUS];
// ALU info // ALU info
wire op_alu = (disp_info_grp == `DECINFO_GRP_ALU); wire op_alu = (disp_info_grp == `DECINFO_GRP_ALU);
wire[`DECINFO_WIDTH-1:0] alu_info = {`DECINFO_WIDTH{op_alu}} & dec_info_bus_i; wire[`DECINFO_WIDTH-1:0] alu_info = {`DECINFO_WIDTH{op_alu}} & dec_info_bus_i;
// ALU op1 // ALU op1
wire alu_op1_pc = alu_info[`DECINFO_ALU_OP1PC]; wire alu_op1_pc = alu_info[`DECINFO_ALU_OP1PC];
wire alu_op1_zero = alu_info[`DECINFO_ALU_LUI]; 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; 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; assign alu_op1_o = op_alu? alu_op1: 32'h0;
// ALU op2 // ALU op2
wire alu_op2_imm = alu_info[`DECINFO_ALU_OP2IMM]; wire alu_op2_imm = alu_info[`DECINFO_ALU_OP2IMM];
wire[31:0] alu_op2 = alu_op2_imm? dec_imm_i: rs2_rdata_i; 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_op2_o = op_alu? alu_op2: 32'h0;
assign alu_op_lui_o = alu_info[`DECINFO_ALU_LUI]; assign alu_op_lui_o = alu_info[`DECINFO_ALU_LUI];
assign alu_op_auipc_o = alu_info[`DECINFO_ALU_AUIPC]; assign alu_op_auipc_o = alu_info[`DECINFO_ALU_AUIPC];
assign alu_op_add_o = alu_info[`DECINFO_ALU_ADD]; assign alu_op_add_o = alu_info[`DECINFO_ALU_ADD];
assign alu_op_sub_o = alu_info[`DECINFO_ALU_SUB]; assign alu_op_sub_o = alu_info[`DECINFO_ALU_SUB];
assign alu_op_sll_o = alu_info[`DECINFO_ALU_SLL]; assign alu_op_sll_o = alu_info[`DECINFO_ALU_SLL];
assign alu_op_slt_o = alu_info[`DECINFO_ALU_SLT]; assign alu_op_slt_o = alu_info[`DECINFO_ALU_SLT];
assign alu_op_sltu_o = alu_info[`DECINFO_ALU_SLTU]; assign alu_op_sltu_o = alu_info[`DECINFO_ALU_SLTU];
assign alu_op_xor_o = alu_info[`DECINFO_ALU_XOR]; assign alu_op_xor_o = alu_info[`DECINFO_ALU_XOR];
assign alu_op_srl_o = alu_info[`DECINFO_ALU_SRL]; assign alu_op_srl_o = alu_info[`DECINFO_ALU_SRL];
assign alu_op_sra_o = alu_info[`DECINFO_ALU_SRA]; assign alu_op_sra_o = alu_info[`DECINFO_ALU_SRA];
assign alu_op_or_o = alu_info[`DECINFO_ALU_OR]; assign alu_op_or_o = alu_info[`DECINFO_ALU_OR];
assign alu_op_and_o = alu_info[`DECINFO_ALU_AND]; assign alu_op_and_o = alu_info[`DECINFO_ALU_AND];
assign req_alu_o = op_alu; assign req_alu_o = op_alu;
// BJP info // BJP info
wire op_bjp = (disp_info_grp == `DECINFO_GRP_BJP); wire op_bjp = (disp_info_grp == `DECINFO_GRP_BJP);
wire[`DECINFO_WIDTH-1:0] bjp_info = {`DECINFO_WIDTH{op_bjp}} & dec_info_bus_i; wire[`DECINFO_WIDTH-1:0] bjp_info = {`DECINFO_WIDTH{op_bjp}} & dec_info_bus_i;
// BJP op1 // BJP op1
wire bjp_op1_rs1 = bjp_info[`DECINFO_BJP_OP1RS1]; wire bjp_op1_rs1 = bjp_info[`DECINFO_BJP_OP1RS1];
wire[31:0] bjp_op1 = bjp_op1_rs1? rs1_rdata_i: dec_pc_i; 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; assign bjp_jump_op1_o = op_bjp? bjp_op1: 32'h0;
// BJP op2 // BJP op2
wire[31:0] bjp_op2 = dec_imm_i; wire[31:0] bjp_op2 = dec_imm_i;
assign bjp_jump_op2_o = op_bjp? bjp_op2: 32'h0; assign bjp_jump_op2_o = op_bjp? bjp_op2: 32'h0;
assign bjp_op1_o = op_bjp? rs1_rdata_i: 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_op2_o = op_bjp? rs2_rdata_i: 32'h0;
assign bjp_op_jump_o = bjp_info[`DECINFO_BJP_JUMP]; assign bjp_op_jump_o = bjp_info[`DECINFO_BJP_JUMP];
assign bjp_op_beq_o = bjp_info[`DECINFO_BJP_BEQ]; assign bjp_op_beq_o = bjp_info[`DECINFO_BJP_BEQ];
assign bjp_op_bne_o = bjp_info[`DECINFO_BJP_BNE]; assign bjp_op_bne_o = bjp_info[`DECINFO_BJP_BNE];
assign bjp_op_blt_o = bjp_info[`DECINFO_BJP_BLT]; assign bjp_op_blt_o = bjp_info[`DECINFO_BJP_BLT];
assign bjp_op_bltu_o = bjp_info[`DECINFO_BJP_BLTU]; assign bjp_op_bltu_o = bjp_info[`DECINFO_BJP_BLTU];
assign bjp_op_bge_o = bjp_info[`DECINFO_BJP_BGE]; assign bjp_op_bge_o = bjp_info[`DECINFO_BJP_BGE];
assign bjp_op_bgeu_o = bjp_info[`DECINFO_BJP_BGEU]; assign bjp_op_bgeu_o = bjp_info[`DECINFO_BJP_BGEU];
assign req_bjp_o = op_bjp; assign req_bjp_o = op_bjp;
// MULDIV info // MULDIV info
wire op_muldiv = (disp_info_grp == `DECINFO_GRP_MULDIV); wire op_muldiv = (disp_info_grp == `DECINFO_GRP_MULDIV);
wire[`DECINFO_WIDTH-1:0] muldiv_info = {`DECINFO_WIDTH{op_muldiv}} & dec_info_bus_i; wire[`DECINFO_WIDTH-1:0] muldiv_info = {`DECINFO_WIDTH{op_muldiv}} & dec_info_bus_i;
// MULDIV op1 // MULDIV op1
assign muldiv_op1_o = op_muldiv? rs1_rdata_i: 32'h0; assign muldiv_op1_o = op_muldiv? rs1_rdata_i: 32'h0;
// MULDIV op2 // MULDIV op2
assign muldiv_op2_o = op_muldiv? rs2_rdata_i: 32'h0; assign muldiv_op2_o = op_muldiv? rs2_rdata_i: 32'h0;
assign muldiv_op_mul_o = muldiv_info[`DECINFO_MULDIV_MUL]; assign muldiv_op_mul_o = muldiv_info[`DECINFO_MULDIV_MUL];
assign muldiv_op_mulh_o = muldiv_info[`DECINFO_MULDIV_MULH]; assign muldiv_op_mulh_o = muldiv_info[`DECINFO_MULDIV_MULH];
assign muldiv_op_mulhu_o = muldiv_info[`DECINFO_MULDIV_MULHU]; assign muldiv_op_mulhu_o = muldiv_info[`DECINFO_MULDIV_MULHU];
assign muldiv_op_mulhsu_o = muldiv_info[`DECINFO_MULDIV_MULHSU]; assign muldiv_op_mulhsu_o = muldiv_info[`DECINFO_MULDIV_MULHSU];
assign muldiv_op_div_o = muldiv_info[`DECINFO_MULDIV_DIV]; assign muldiv_op_div_o = muldiv_info[`DECINFO_MULDIV_DIV];
assign muldiv_op_divu_o = muldiv_info[`DECINFO_MULDIV_DIVU]; assign muldiv_op_divu_o = muldiv_info[`DECINFO_MULDIV_DIVU];
assign muldiv_op_rem_o = muldiv_info[`DECINFO_MULDIV_REM]; assign muldiv_op_rem_o = muldiv_info[`DECINFO_MULDIV_REM];
assign muldiv_op_remu_o = muldiv_info[`DECINFO_MULDIV_REMU]; assign muldiv_op_remu_o = muldiv_info[`DECINFO_MULDIV_REMU];
assign req_muldiv_o = op_muldiv; assign req_muldiv_o = op_muldiv;
// CSR info // CSR info
wire op_csr = (disp_info_grp == `DECINFO_GRP_CSR); wire op_csr = (disp_info_grp == `DECINFO_GRP_CSR);
wire[`DECINFO_WIDTH-1:0] csr_info = {`DECINFO_WIDTH{op_csr}} & dec_info_bus_i; wire[`DECINFO_WIDTH-1:0] csr_info = {`DECINFO_WIDTH{op_csr}} & dec_info_bus_i;
// CSR op1 // CSR op1
wire csr_rs1imm = csr_info[`DECINFO_CSR_RS1IMM]; wire csr_rs1imm = csr_info[`DECINFO_CSR_RS1IMM];
wire[31:0] csr_rs1 = csr_rs1imm? dec_imm_i: rs1_rdata_i; 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_op1_o = op_csr? csr_rs1: 32'h0;
assign csr_addr_o = {{20{1'b0}}, csr_info[`DECINFO_CSR_CSRADDR]}; assign csr_addr_o = {{20{1'b0}}, csr_info[`DECINFO_CSR_CSRADDR]};
assign csr_csrrw_o = csr_info[`DECINFO_CSR_CSRRW]; assign csr_csrrw_o = csr_info[`DECINFO_CSR_CSRRW];
assign csr_csrrs_o = csr_info[`DECINFO_CSR_CSRRS]; assign csr_csrrs_o = csr_info[`DECINFO_CSR_CSRRS];
assign csr_csrrc_o = csr_info[`DECINFO_CSR_CSRRC]; assign csr_csrrc_o = csr_info[`DECINFO_CSR_CSRRC];
assign req_csr_o = op_csr; assign req_csr_o = op_csr;
// MEM info // MEM info
wire op_mem = (disp_info_grp == `DECINFO_GRP_MEM); wire op_mem = (disp_info_grp == `DECINFO_GRP_MEM);
wire[`DECINFO_WIDTH-1:0] mem_info = {`DECINFO_WIDTH{op_mem}} & dec_info_bus_i; 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_lb_o = mem_info[`DECINFO_MEM_LB];
assign mem_op_lh_o = mem_info[`DECINFO_MEM_LH]; assign mem_op_lh_o = mem_info[`DECINFO_MEM_LH];
assign mem_op_lw_o = mem_info[`DECINFO_MEM_LW]; assign mem_op_lw_o = mem_info[`DECINFO_MEM_LW];
assign mem_op_lbu_o = mem_info[`DECINFO_MEM_LBU]; assign mem_op_lbu_o = mem_info[`DECINFO_MEM_LBU];
assign mem_op_lhu_o = mem_info[`DECINFO_MEM_LHU]; assign mem_op_lhu_o = mem_info[`DECINFO_MEM_LHU];
assign mem_op_sb_o = mem_info[`DECINFO_MEM_SB]; assign mem_op_sb_o = mem_info[`DECINFO_MEM_SB];
assign mem_op_sh_o = mem_info[`DECINFO_MEM_SH]; assign mem_op_sh_o = mem_info[`DECINFO_MEM_SH];
assign mem_op_sw_o = mem_info[`DECINFO_MEM_SW]; assign mem_op_sw_o = mem_info[`DECINFO_MEM_SW];
assign mem_op1_o = op_mem? rs1_rdata_i: 32'h0; assign mem_op1_o = op_mem? rs1_rdata_i: 32'h0;
assign mem_op2_o = op_mem? dec_imm_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 mem_rs2_data_o = op_mem? rs2_rdata_i: 32'h0;
assign req_mem_o = op_mem; assign req_mem_o = op_mem;
// SYS info // SYS info
wire op_sys = (disp_info_grp == `DECINFO_GRP_SYS); wire op_sys = (disp_info_grp == `DECINFO_GRP_SYS);
wire[`DECINFO_WIDTH-1:0] sys_info = {`DECINFO_WIDTH{op_sys}} & dec_info_bus_i; 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_nop_o = sys_info[`DECINFO_SYS_NOP];
assign sys_op_mret_o = sys_info[`DECINFO_SYS_MRET]; assign sys_op_mret_o = sys_info[`DECINFO_SYS_MRET];
assign sys_op_ecall_o = sys_info[`DECINFO_SYS_ECALL]; assign sys_op_ecall_o = sys_info[`DECINFO_SYS_ECALL];
assign sys_op_ebreak_o = sys_info[`DECINFO_SYS_EBREAK]; assign sys_op_ebreak_o = sys_info[`DECINFO_SYS_EBREAK];
assign sys_op_fence_o = sys_info[`DECINFO_SYS_FENCE]; assign sys_op_fence_o = sys_info[`DECINFO_SYS_FENCE];
endmodule endmodule

View File

@ -1,162 +1,162 @@
/* /*
Copyright 2020 Blue Liang, liangkangnan@163.com Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
`include "defines.sv" `include "defines.sv"
module exu_mem( module exu_mem(
input wire clk, input wire clk,
input wire rst_n, input wire rst_n,
input req_mem_i, input req_mem_i,
input wire[31:0] mem_addr_i, input wire[31:0] mem_addr_i,
input wire[31:0] mem_rs2_data_i, input wire[31:0] mem_rs2_data_i,
input wire[31:0] mem_rdata_i, input wire[31:0] mem_rdata_i,
input wire mem_req_ready_i, input wire mem_req_ready_i,
input wire mem_rsp_valid_i, input wire mem_rsp_valid_i,
input wire mem_op_lb_i, input wire mem_op_lb_i,
input wire mem_op_lh_i, input wire mem_op_lh_i,
input wire mem_op_lw_i, input wire mem_op_lw_i,
input wire mem_op_lbu_i, input wire mem_op_lbu_i,
input wire mem_op_lhu_i, input wire mem_op_lhu_i,
input wire mem_op_sb_i, input wire mem_op_sb_i,
input wire mem_op_sh_i, input wire mem_op_sh_i,
input wire mem_op_sw_i, input wire mem_op_sw_i,
output wire mem_access_misaligned_o, output wire mem_access_misaligned_o,
output wire mem_stall_o, output wire mem_stall_o,
output wire[31:0] mem_addr_o, output wire[31:0] mem_addr_o,
output wire[31:0] mem_wdata_o, output wire[31:0] mem_wdata_o,
output wire mem_reg_we_o, output wire mem_reg_we_o,
output wire mem_mem_we_o, output wire mem_mem_we_o,
output wire[3:0] mem_sel_o, output wire[3:0] mem_sel_o,
output wire mem_req_valid_o, output wire mem_req_valid_o,
output wire mem_rsp_ready_o output wire mem_rsp_ready_o
); );
wire[1:0] mem_addr_index = mem_addr_i[1:0]; wire[1:0] mem_addr_index = mem_addr_i[1:0];
wire mem_addr_index00 = (mem_addr_index == 2'b00); wire mem_addr_index00 = (mem_addr_index == 2'b00);
wire mem_addr_index01 = (mem_addr_index == 2'b01); wire mem_addr_index01 = (mem_addr_index == 2'b01);
wire mem_addr_index10 = (mem_addr_index == 2'b10); wire mem_addr_index10 = (mem_addr_index == 2'b10);
wire mem_addr_index11 = (mem_addr_index == 2'b11); 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[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[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[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; assign mem_sel_o[3] = mem_addr_index11 | (mem_op_sh_i & mem_addr_index10) | mem_op_sw_i;
reg[31:0] sb_res; reg[31:0] sb_res;
always @ (*) begin always @ (*) begin
sb_res = 32'h0; sb_res = 32'h0;
case (1'b1) case (1'b1)
mem_addr_index00: sb_res = {24'h0, mem_rs2_data_i[7:0]}; 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_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_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}; mem_addr_index11: sb_res = {mem_rs2_data_i[7:0], 24'h0};
endcase endcase
end end
reg[31:0] sh_res; reg[31:0] sh_res;
always @ (*) begin always @ (*) begin
sh_res = 32'h0; sh_res = 32'h0;
case (1'b1) case (1'b1)
mem_addr_index00: sh_res = {16'h0, mem_rs2_data_i[15:0]}; 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}; mem_addr_index10: sh_res = {mem_rs2_data_i[15:0], 16'h0};
endcase endcase
end end
wire[31:0] sw_res = mem_rs2_data_i; wire[31:0] sw_res = mem_rs2_data_i;
reg[31:0] lb_res; reg[31:0] lb_res;
always @ (*) begin always @ (*) begin
lb_res = 32'h0; lb_res = 32'h0;
case (1'b1) case (1'b1)
mem_addr_index00: lb_res = {{24{mem_op_lb_i & mem_rdata_i[7]}}, mem_rdata_i[7:0]}; 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_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_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]}; mem_addr_index11: lb_res = {{24{mem_op_lb_i & mem_rdata_i[31]}}, mem_rdata_i[31:24]};
endcase endcase
end end
reg[31:0] lh_res; reg[31:0] lh_res;
always @ (*) begin always @ (*) begin
lh_res = 32'h0; lh_res = 32'h0;
case (1'b1) case (1'b1)
mem_addr_index00: lh_res = {{24{mem_op_lh_i & mem_rdata_i[15]}}, mem_rdata_i[15:0]}; 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]}; mem_addr_index10: lh_res = {{24{mem_op_lh_i & mem_rdata_i[31]}}, mem_rdata_i[31:16]};
endcase endcase
end end
wire[31:0] lw_res = mem_rdata_i; wire[31:0] lw_res = mem_rdata_i;
reg[31:0] mem_wdata; reg[31:0] mem_wdata;
always @ (*) begin always @ (*) begin
mem_wdata = 32'h0; mem_wdata = 32'h0;
case (1'b1) case (1'b1)
mem_op_sb_i: mem_wdata = sb_res; mem_op_sb_i: mem_wdata = sb_res;
mem_op_sh_i: mem_wdata = sh_res; mem_op_sh_i: mem_wdata = sh_res;
mem_op_sw_i: mem_wdata = sw_res; mem_op_sw_i: mem_wdata = sw_res;
mem_op_lb_i: mem_wdata = lb_res; mem_op_lb_i: mem_wdata = lb_res;
mem_op_lbu_i: mem_wdata = lb_res; mem_op_lbu_i: mem_wdata = lb_res;
mem_op_lh_i: mem_wdata = lh_res; mem_op_lh_i: mem_wdata = lh_res;
mem_op_lhu_i: mem_wdata = lh_res; mem_op_lhu_i: mem_wdata = lh_res;
mem_op_lw_i: mem_wdata = lw_res; mem_op_lw_i: mem_wdata = lw_res;
endcase endcase
end end
assign mem_wdata_o = mem_wdata; assign mem_wdata_o = mem_wdata;
wire mem_req_hsked = (mem_req_valid_o & mem_req_ready_i); wire mem_req_hsked = (mem_req_valid_o & mem_req_ready_i);
wire mem_rsp_hsked = (mem_rsp_valid_i & mem_rsp_ready_o); wire mem_rsp_hsked = (mem_rsp_valid_i & mem_rsp_ready_o);
reg mem_rsp_hsked_r; reg mem_rsp_hsked_r;
always @ (posedge clk or negedge rst_n) begin always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin if (!rst_n) begin
mem_rsp_hsked_r <= 1'b0; mem_rsp_hsked_r <= 1'b0;
end else begin end else begin
mem_rsp_hsked_r <= mem_rsp_hsked & (~mem_rsp_hsked_r); mem_rsp_hsked_r <= mem_rsp_hsked & (~mem_rsp_hsked_r);
end end
end end
assign mem_rsp_ready_o = 1'b1; assign mem_rsp_ready_o = 1'b1;
// 请求访问总线 // 请求访问总线
assign mem_req_valid_o = req_mem_i; assign mem_req_valid_o = req_mem_i;
// 暂停流水线 // 暂停流水线
assign mem_stall_o = req_mem_i & (~mem_rsp_hsked_r); assign mem_stall_o = req_mem_i & (~mem_rsp_hsked_r);
// 读、写内存地址 // 读、写内存地址
assign mem_addr_o = mem_addr_i; assign mem_addr_o = mem_addr_i;
// 写寄存器使能收到ack时数据才有效 // 写寄存器使能收到ack时数据才有效
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_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_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]): 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]: (mem_op_sh_i | mem_op_lh_i | mem_op_lhu_i)? mem_addr_i[0]:
0; 0;
endmodule endmodule

View File

@ -1,106 +1,106 @@
/* /*
Copyright 2020 Blue Liang, liangkangnan@163.com Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
`include "defines.sv" `include "defines.sv"
module exu_muldiv( module exu_muldiv(
input wire clk, input wire clk,
input wire rst_n, input wire rst_n,
input wire[31:0] muldiv_op1_i, input wire[31:0] muldiv_op1_i,
input wire[31:0] muldiv_op2_i, input wire[31:0] muldiv_op2_i,
input wire muldiv_op_mul_i, input wire muldiv_op_mul_i,
input wire muldiv_op_mulh_i, input wire muldiv_op_mulh_i,
input wire muldiv_op_mulhsu_i, input wire muldiv_op_mulhsu_i,
input wire muldiv_op_mulhu_i, input wire muldiv_op_mulhu_i,
input wire muldiv_op_div_i, input wire muldiv_op_div_i,
input wire muldiv_op_divu_i, input wire muldiv_op_divu_i,
input wire muldiv_op_rem_i, input wire muldiv_op_rem_i,
input wire muldiv_op_remu_i, input wire muldiv_op_remu_i,
output wire[31:0] muldiv_reg_wdata_o, output wire[31:0] muldiv_reg_wdata_o,
output wire muldiv_reg_we_o, output wire muldiv_reg_we_o,
output wire muldiv_stall_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 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 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[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[31:0] div_result;
wire div_ready; wire div_ready;
divider u_divider( divider u_divider(
.clk(clk), .clk(clk),
.rst_n(rst_n), .rst_n(rst_n),
.dividend_i(muldiv_op1_i), .dividend_i(muldiv_op1_i),
.divisor_i(muldiv_op2_i), .divisor_i(muldiv_op2_i),
.start_i(div_start), .start_i(div_start),
.op_i(div_op), .op_i(div_op),
.result_o(div_result), .result_o(div_result),
.ready_o(div_ready) .ready_o(div_ready)
); );
// 乘法操作 // 乘法操作
wire op_mul = muldiv_op_mul_i | muldiv_op_mulh_i | muldiv_op_mulhsu_i | muldiv_op_mulhu_i; 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; wire[31:0] muldiv_op1_r;
gen_en_dff #(32) mul_op1_ff(clk, rst_n, op_mul, muldiv_op1_i, 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; wire[31:0] muldiv_op2_r;
gen_en_dff #(32) mul_op2_ff(clk, rst_n, op_mul, muldiv_op2_i, 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_r;
wire mul_ready = (~mul_ready_r) & op_mul; wire mul_ready = (~mul_ready_r) & op_mul;
gen_rst_0_dff #(1) mul_ready_ff(clk, rst_n, mul_ready, mul_ready_r); 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 mul_start = (~mul_ready_r) & op_mul;
wire op1_is_signed = muldiv_op1_r[31]; wire op1_is_signed = muldiv_op1_r[31];
wire op2_is_signed = muldiv_op2_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] 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] 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) | 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); ({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) | 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); ({32{(muldiv_op_mulh_i)}} & op2_complcode);
wire[63:0] mul_res_tmp = op1_mul * op2_mul; wire[63:0] mul_res_tmp = op1_mul * op2_mul;
wire[63:0] mul_res_tmp_complcode = -mul_res_tmp; wire[63:0] mul_res_tmp_complcode = -mul_res_tmp;
wire[31:0] mul_res = mul_res_tmp[31:0]; wire[31:0] mul_res = mul_res_tmp[31:0];
wire[31:0] mulhu_res = mul_res_tmp[63:32]; 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] 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]; 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; reg[31:0] mul_op_res;
always @ (*) begin always @ (*) begin
mul_op_res = 32'h0; mul_op_res = 32'h0;
case (1'b1) case (1'b1)
muldiv_op_mul_i: mul_op_res = mul_res; muldiv_op_mul_i: mul_op_res = mul_res;
muldiv_op_mulhu_i: mul_op_res = mulhu_res; muldiv_op_mulhu_i: mul_op_res = mulhu_res;
muldiv_op_mulh_i: mul_op_res = mulh_res; muldiv_op_mulh_i: mul_op_res = mulh_res;
muldiv_op_mulhsu_i: mul_op_res = mulhsu_res; muldiv_op_mulhsu_i: mul_op_res = mulhsu_res;
endcase endcase
end end
// 运算结果 // 运算结果
assign muldiv_reg_wdata_o = div_result | mul_op_res; assign muldiv_reg_wdata_o = div_result | mul_op_res;
assign muldiv_reg_we_o = div_ready | mul_ready_r; assign muldiv_reg_we_o = div_ready | mul_ready_r;
assign muldiv_stall_o = div_start | mul_start; assign muldiv_stall_o = div_start | mul_start;
endmodule endmodule

View File

@ -1,92 +1,92 @@
/* /*
Copyright 2019 Blue Liang, liangkangnan@163.com Copyright 2019 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
`include "defines.sv" `include "defines.sv"
// 通用寄存器模块 // 通用寄存器模块
module gpr_reg( module gpr_reg(
input wire clk, input wire clk,
input wire rst_n, input wire rst_n,
input wire we_i, // 写寄存器使能 input wire we_i, // 写寄存器使能
input wire[4:0] waddr_i, // 写寄存器地址 input wire[4:0] waddr_i, // 写寄存器地址
input wire[31:0] wdata_i, // 写寄存器数据 input wire[31:0] wdata_i, // 写寄存器数据
input wire[4:0] raddr1_i, // 读寄存器1地址 input wire[4:0] raddr1_i, // 读寄存器1地址
output wire[31:0] rdata1_o, // 读寄存器1数据 output wire[31:0] rdata1_o, // 读寄存器1数据
input wire[4:0] raddr2_i, // 读寄存器2地址 input wire[4:0] raddr2_i, // 读寄存器2地址
output wire[31:0] rdata2_o // 读寄存器2数据 output wire[31:0] rdata2_o // 读寄存器2数据
); );
wire[32-1:0] regs[32-1:0]; wire[32-1:0] regs[32-1:0];
wire[32-1:0] we; wire[32-1:0] we;
genvar i; genvar i;
generate generate
for (i = 0; i < 32; i = i + 1) begin: gpr_rw for (i = 0; i < 32; i = i + 1) begin: gpr_rw
// x0 cannot be wrote since it is constant-zeros // x0 cannot be wrote since it is constant-zeros
if (i == 0) begin: is_x0 if (i == 0) begin: is_x0
assign we[i] = 1'b0; assign we[i] = 1'b0;
assign regs[i] = 32'h0; assign regs[i] = 32'h0;
end else begin: not_x0 end else begin: not_x0
assign we[i] = we_i & (waddr_i == i); assign we[i] = we_i & (waddr_i == i);
gen_en_dffnr #(32) rf_dff(clk, we[i], wdata_i, regs[i]); gen_en_dffnr #(32) rf_dff(clk, we[i], wdata_i, regs[i]);
end end
end end
endgenerate endgenerate
assign rdata1_o = (|raddr1_i)? ((we_i & (waddr_i == raddr1_i))? wdata_i: regs[raddr1_i]): 32'h0; 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; assign rdata2_o = (|raddr2_i)? ((we_i & (waddr_i == raddr2_i))? wdata_i: regs[raddr2_i]): 32'h0;
// for debug // for debug
wire[31:0] ra = regs[1]; wire[31:0] ra = regs[1];
wire[31:0] sp = regs[2]; wire[31:0] sp = regs[2];
wire[31:0] gp = regs[3]; wire[31:0] gp = regs[3];
wire[31:0] tp = regs[4]; wire[31:0] tp = regs[4];
wire[31:0] t0 = regs[5]; wire[31:0] t0 = regs[5];
wire[31:0] t1 = regs[6]; wire[31:0] t1 = regs[6];
wire[31:0] t2 = regs[7]; wire[31:0] t2 = regs[7];
wire[31:0] s0 = regs[8]; wire[31:0] s0 = regs[8];
wire[31:0] fp = regs[8]; wire[31:0] fp = regs[8];
wire[31:0] s1 = regs[9]; wire[31:0] s1 = regs[9];
wire[31:0] a0 = regs[10]; wire[31:0] a0 = regs[10];
wire[31:0] a1 = regs[11]; wire[31:0] a1 = regs[11];
wire[31:0] a2 = regs[12]; wire[31:0] a2 = regs[12];
wire[31:0] a3 = regs[13]; wire[31:0] a3 = regs[13];
wire[31:0] a4 = regs[14]; wire[31:0] a4 = regs[14];
wire[31:0] a5 = regs[15]; wire[31:0] a5 = regs[15];
wire[31:0] a6 = regs[16]; wire[31:0] a6 = regs[16];
wire[31:0] a7 = regs[17]; wire[31:0] a7 = regs[17];
wire[31:0] s2 = regs[18]; wire[31:0] s2 = regs[18];
wire[31:0] s3 = regs[19]; wire[31:0] s3 = regs[19];
wire[31:0] s4 = regs[20]; wire[31:0] s4 = regs[20];
wire[31:0] s5 = regs[21]; wire[31:0] s5 = regs[21];
wire[31:0] s6 = regs[22]; wire[31:0] s6 = regs[22];
wire[31:0] s7 = regs[23]; wire[31:0] s7 = regs[23];
wire[31:0] s8 = regs[24]; wire[31:0] s8 = regs[24];
wire[31:0] s9 = regs[25]; wire[31:0] s9 = regs[25];
wire[31:0] s10 = regs[26]; wire[31:0] s10 = regs[26];
wire[31:0] s11 = regs[27]; wire[31:0] s11 = regs[27];
wire[31:0] t3 = regs[28]; wire[31:0] t3 = regs[28];
wire[31:0] t4 = regs[29]; wire[31:0] t4 = regs[29];
wire[31:0] t5 = regs[30]; wire[31:0] t5 = regs[30];
wire[31:0] t6 = regs[31]; wire[31:0] t6 = regs[31];
endmodule endmodule

View File

@ -1,303 +1,303 @@
/* /*
Copyright 2019 Blue Liang, liangkangnan@163.com Copyright 2019 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
`include "defines.sv" `include "defines.sv"
// 译码模块 // 译码模块
// 纯组合逻辑电路 // 纯组合逻辑电路
module idu( module idu(
input wire clk, input wire clk,
input wire rst_n, input wire rst_n,
// from if_id // from if_id
input wire[31:0] inst_i, // 指令内容 input wire[31:0] inst_i, // 指令内容
input wire[31:0] inst_addr_i, // 指令地址 input wire[31:0] inst_addr_i, // 指令地址
// from gpr_reg // from gpr_reg
input wire[31:0] rs1_rdata_i, // 通用寄存器1输入数据 input wire[31:0] rs1_rdata_i, // 通用寄存器1输入数据
input wire[31:0] rs2_rdata_i, // 通用寄存器2输入数据 input wire[31:0] rs2_rdata_i, // 通用寄存器2输入数据
output wire stall_o, output wire stall_o,
// to id_ex // to id_ex
output wire[31:0] inst_o, output wire[31:0] inst_o,
output wire[`DECINFO_WIDTH-1:0] dec_info_bus_o, output wire[`DECINFO_WIDTH-1:0] dec_info_bus_o,
output wire[31:0] dec_imm_o, output wire[31:0] dec_imm_o,
output wire[31:0] dec_pc_o, output wire[31:0] dec_pc_o,
output wire[4:0] rs1_raddr_o, output wire[4:0] rs1_raddr_o,
output wire[4:0] rs2_raddr_o, output wire[4:0] rs2_raddr_o,
output wire[31:0] rs1_rdata_o, output wire[31:0] rs1_rdata_o,
output wire[31:0] rs2_rdata_o, output wire[31:0] rs2_rdata_o,
output wire[4:0] rd_waddr_o, output wire[4:0] rd_waddr_o,
output wire rd_we_o output wire rd_we_o
); );
assign inst_o = inst_i; assign inst_o = inst_i;
assign rs1_rdata_o = rs1_rdata_i; assign rs1_rdata_o = rs1_rdata_i;
assign rs2_rdata_o = rs2_rdata_i; assign rs2_rdata_o = rs2_rdata_i;
// 取出指令中的每一个域 // 取出指令中的每一个域
wire[6:0] opcode = inst_i[6:0]; wire[6:0] opcode = inst_i[6:0];
wire[2:0] funct3 = inst_i[14:12]; wire[2:0] funct3 = inst_i[14:12];
wire[6:0] funct7 = inst_i[31:25]; wire[6:0] funct7 = inst_i[31:25];
wire[4:0] rd = inst_i[11:7]; wire[4:0] rd = inst_i[11:7];
wire[4:0] rs1 = inst_i[19:15]; wire[4:0] rs1 = inst_i[19:15];
wire[4:0] rs2 = inst_i[24:20]; wire[4:0] rs2 = inst_i[24:20];
wire[11:0] type_i_imm_11_0 = inst_i[31: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[6:0] type_s_imm_11_5 = inst_i[31:25];
wire[4:0] type_s_imm_4_0 = inst_i[11:7]; 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[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[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_u_imm_31_12 = inst_i[31:12];
wire[19:0] type_j_imm_31_12 = inst_i[31:12]; wire[19:0] type_j_imm_31_12 = inst_i[31:12];
// 指令opcode域的取值 // 指令opcode域的取值
wire opcode_0110111 = (opcode == 7'b0110111); wire opcode_0110111 = (opcode == 7'b0110111);
wire opcode_0010111 = (opcode == 7'b0010111); wire opcode_0010111 = (opcode == 7'b0010111);
wire opcode_1101111 = (opcode == 7'b1101111); wire opcode_1101111 = (opcode == 7'b1101111);
wire opcode_1100111 = (opcode == 7'b1100111); wire opcode_1100111 = (opcode == 7'b1100111);
wire opcode_1100011 = (opcode == 7'b1100011); wire opcode_1100011 = (opcode == 7'b1100011);
wire opcode_0000011 = (opcode == 7'b0000011); wire opcode_0000011 = (opcode == 7'b0000011);
wire opcode_0100011 = (opcode == 7'b0100011); wire opcode_0100011 = (opcode == 7'b0100011);
wire opcode_0010011 = (opcode == 7'b0010011); wire opcode_0010011 = (opcode == 7'b0010011);
wire opcode_0110011 = (opcode == 7'b0110011); wire opcode_0110011 = (opcode == 7'b0110011);
wire opcode_0001111 = (opcode == 7'b0001111); wire opcode_0001111 = (opcode == 7'b0001111);
wire opcode_1110011 = (opcode == 7'b1110011); wire opcode_1110011 = (opcode == 7'b1110011);
// 指令funct3域的取值 // 指令funct3域的取值
wire funct3_000 = (funct3 == 3'b000); wire funct3_000 = (funct3 == 3'b000);
wire funct3_001 = (funct3 == 3'b001); wire funct3_001 = (funct3 == 3'b001);
wire funct3_010 = (funct3 == 3'b010); wire funct3_010 = (funct3 == 3'b010);
wire funct3_011 = (funct3 == 3'b011); wire funct3_011 = (funct3 == 3'b011);
wire funct3_100 = (funct3 == 3'b100); wire funct3_100 = (funct3 == 3'b100);
wire funct3_101 = (funct3 == 3'b101); wire funct3_101 = (funct3 == 3'b101);
wire funct3_110 = (funct3 == 3'b110); wire funct3_110 = (funct3 == 3'b110);
wire funct3_111 = (funct3 == 3'b111); wire funct3_111 = (funct3 == 3'b111);
// 指令funct7域的取值 // 指令funct7域的取值
wire funct7_0000000 = (funct7 == 7'b0000000); wire funct7_0000000 = (funct7 == 7'b0000000);
wire funct7_0100000 = (funct7 == 7'b0100000); wire funct7_0100000 = (funct7 == 7'b0100000);
wire funct7_0000001 = (funct7 == 7'b0000001); wire funct7_0000001 = (funct7 == 7'b0000001);
// I类型指令imm域的取值 // I类型指令imm域的取值
wire type_i_imm_000000000000 = (type_i_imm_11_0 == 12'b000000000000); 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 type_i_imm_000000000001 = (type_i_imm_11_0 == 12'b000000000001);
// 译码出具体指令 // 译码出具体指令
wire inst_lui = opcode_0110111; wire inst_lui = opcode_0110111;
wire inst_auipc = opcode_0010111; wire inst_auipc = opcode_0010111;
wire inst_jal = opcode_1101111; wire inst_jal = opcode_1101111;
wire inst_jalr = opcode_1100111 & funct3_000; wire inst_jalr = opcode_1100111 & funct3_000;
wire inst_beq = opcode_1100011 & funct3_000; wire inst_beq = opcode_1100011 & funct3_000;
wire inst_bne = opcode_1100011 & funct3_001; wire inst_bne = opcode_1100011 & funct3_001;
wire inst_blt = opcode_1100011 & funct3_100; wire inst_blt = opcode_1100011 & funct3_100;
wire inst_bge = opcode_1100011 & funct3_101; wire inst_bge = opcode_1100011 & funct3_101;
wire inst_bltu = opcode_1100011 & funct3_110; wire inst_bltu = opcode_1100011 & funct3_110;
wire inst_bgeu = opcode_1100011 & funct3_111; wire inst_bgeu = opcode_1100011 & funct3_111;
wire inst_lb = opcode_0000011 & funct3_000; wire inst_lb = opcode_0000011 & funct3_000;
wire inst_lh = opcode_0000011 & funct3_001; wire inst_lh = opcode_0000011 & funct3_001;
wire inst_lw = opcode_0000011 & funct3_010; wire inst_lw = opcode_0000011 & funct3_010;
wire inst_lbu = opcode_0000011 & funct3_100; wire inst_lbu = opcode_0000011 & funct3_100;
wire inst_lhu = opcode_0000011 & funct3_101; wire inst_lhu = opcode_0000011 & funct3_101;
wire inst_sb = opcode_0100011 & funct3_000; wire inst_sb = opcode_0100011 & funct3_000;
wire inst_sh = opcode_0100011 & funct3_001; wire inst_sh = opcode_0100011 & funct3_001;
wire inst_sw = opcode_0100011 & funct3_010; wire inst_sw = opcode_0100011 & funct3_010;
wire inst_addi = opcode_0010011 & funct3_000; wire inst_addi = opcode_0010011 & funct3_000;
wire inst_slti = opcode_0010011 & funct3_010; wire inst_slti = opcode_0010011 & funct3_010;
wire inst_sltiu = opcode_0010011 & funct3_011; wire inst_sltiu = opcode_0010011 & funct3_011;
wire inst_xori = opcode_0010011 & funct3_100; wire inst_xori = opcode_0010011 & funct3_100;
wire inst_ori = opcode_0010011 & funct3_110; wire inst_ori = opcode_0010011 & funct3_110;
wire inst_andi = opcode_0010011 & funct3_111; wire inst_andi = opcode_0010011 & funct3_111;
wire inst_slli = opcode_0010011 & funct3_001 & funct7_0000000; wire inst_slli = opcode_0010011 & funct3_001 & funct7_0000000;
wire inst_srli = opcode_0010011 & funct3_101 & funct7_0000000; wire inst_srli = opcode_0010011 & funct3_101 & funct7_0000000;
wire inst_srai = opcode_0010011 & funct3_101 & funct7_0100000; wire inst_srai = opcode_0010011 & funct3_101 & funct7_0100000;
wire inst_add = opcode_0110011 & funct3_000 & funct7_0000000; wire inst_add = opcode_0110011 & funct3_000 & funct7_0000000;
wire inst_sub = opcode_0110011 & funct3_000 & funct7_0100000; wire inst_sub = opcode_0110011 & funct3_000 & funct7_0100000;
wire inst_sll = opcode_0110011 & funct3_001 & funct7_0000000; wire inst_sll = opcode_0110011 & funct3_001 & funct7_0000000;
wire inst_slt = opcode_0110011 & funct3_010 & funct7_0000000; wire inst_slt = opcode_0110011 & funct3_010 & funct7_0000000;
wire inst_sltu = opcode_0110011 & funct3_011 & funct7_0000000; wire inst_sltu = opcode_0110011 & funct3_011 & funct7_0000000;
wire inst_xor = opcode_0110011 & funct3_100 & funct7_0000000; wire inst_xor = opcode_0110011 & funct3_100 & funct7_0000000;
wire inst_srl = opcode_0110011 & funct3_101 & funct7_0000000; wire inst_srl = opcode_0110011 & funct3_101 & funct7_0000000;
wire inst_sra = opcode_0110011 & funct3_101 & funct7_0100000; wire inst_sra = opcode_0110011 & funct3_101 & funct7_0100000;
wire inst_or = opcode_0110011 & funct3_110 & funct7_0000000; wire inst_or = opcode_0110011 & funct3_110 & funct7_0000000;
wire inst_and = opcode_0110011 & funct3_111 & funct7_0000000; wire inst_and = opcode_0110011 & funct3_111 & funct7_0000000;
wire inst_fence = opcode_0001111 & funct3_000; wire inst_fence = opcode_0001111 & funct3_000;
wire inst_ecall = (inst_i == `INST_ECALL); wire inst_ecall = (inst_i == `INST_ECALL);
wire inst_ebreak = (inst_i == `INST_EBREAK); wire inst_ebreak = (inst_i == `INST_EBREAK);
wire inst_fence_i = opcode_0001111 & funct3_001; wire inst_fence_i = opcode_0001111 & funct3_001;
wire inst_csrrw = opcode_1110011 & funct3_001; wire inst_csrrw = opcode_1110011 & funct3_001;
wire inst_csrrs = opcode_1110011 & funct3_010; wire inst_csrrs = opcode_1110011 & funct3_010;
wire inst_csrrc = opcode_1110011 & funct3_011; wire inst_csrrc = opcode_1110011 & funct3_011;
wire inst_csrrwi = opcode_1110011 & funct3_101; wire inst_csrrwi = opcode_1110011 & funct3_101;
wire inst_csrrsi = opcode_1110011 & funct3_110; wire inst_csrrsi = opcode_1110011 & funct3_110;
wire inst_csrrci = opcode_1110011 & funct3_111; wire inst_csrrci = opcode_1110011 & funct3_111;
wire inst_mul = opcode_0110011 & funct3_000 & funct7_0000001; wire inst_mul = opcode_0110011 & funct3_000 & funct7_0000001;
wire inst_mulh = opcode_0110011 & funct3_001 & funct7_0000001; wire inst_mulh = opcode_0110011 & funct3_001 & funct7_0000001;
wire inst_mulhsu = opcode_0110011 & funct3_010 & funct7_0000001; wire inst_mulhsu = opcode_0110011 & funct3_010 & funct7_0000001;
wire inst_mulhu = opcode_0110011 & funct3_011 & funct7_0000001; wire inst_mulhu = opcode_0110011 & funct3_011 & funct7_0000001;
wire inst_div = opcode_0110011 & funct3_100 & funct7_0000001; wire inst_div = opcode_0110011 & funct3_100 & funct7_0000001;
wire inst_divu = opcode_0110011 & funct3_101 & funct7_0000001; wire inst_divu = opcode_0110011 & funct3_101 & funct7_0000001;
wire inst_rem = opcode_0110011 & funct3_110 & funct7_0000001; wire inst_rem = opcode_0110011 & funct3_110 & funct7_0000001;
wire inst_remu = opcode_0110011 & funct3_111 & funct7_0000001; wire inst_remu = opcode_0110011 & funct3_111 & funct7_0000001;
wire inst_nop = (inst_i == `INST_NOP); wire inst_nop = (inst_i == `INST_NOP);
wire inst_mret = (inst_i == `INST_MRET); wire inst_mret = (inst_i == `INST_MRET);
// 将指令分类 // 将指令分类
wire inst_type_load = opcode_0000011; wire inst_type_load = opcode_0000011;
wire inst_type_store = opcode_0100011; wire inst_type_store = opcode_0100011;
wire inst_type_branch = opcode_1100011; 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_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 inst_type_div = inst_div | inst_divu | inst_rem | inst_remu;
wire[`DECINFO_ALU_BUS_WIDTH-1:0] dec_alu_info_bus; 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_GRP_BUS] = `DECINFO_GRP_ALU;
assign dec_alu_info_bus[`DECINFO_ALU_LUI] = inst_lui; 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_AUIPC] = inst_auipc;
assign dec_alu_info_bus[`DECINFO_ALU_ADD] = inst_add | inst_addi; 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_SUB] = inst_sub;
assign dec_alu_info_bus[`DECINFO_ALU_SLL] = inst_sll | inst_slli; 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_SLT] = inst_slt | inst_slti;
assign dec_alu_info_bus[`DECINFO_ALU_SLTU] = inst_sltu | inst_sltiu; 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_XOR] = inst_xor | inst_xori;
assign dec_alu_info_bus[`DECINFO_ALU_SRL] = inst_srl | inst_srli; 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_SRA] = inst_sra | inst_srai;
assign dec_alu_info_bus[`DECINFO_ALU_OR] = inst_or | inst_ori; 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_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_OP2IMM] = opcode_0010011 | inst_lui | inst_auipc;
assign dec_alu_info_bus[`DECINFO_ALU_OP1PC] = inst_auipc; assign dec_alu_info_bus[`DECINFO_ALU_OP1PC] = inst_auipc;
wire[`DECINFO_BJP_BUS_WIDTH-1:0] dec_bjp_info_bus; 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_GRP_BUS] = `DECINFO_GRP_BJP;
assign dec_bjp_info_bus[`DECINFO_BJP_JUMP] = inst_jal | inst_jalr; 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_BEQ] = inst_beq;
assign dec_bjp_info_bus[`DECINFO_BJP_BNE] = inst_bne; 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_BLT] = inst_blt;
assign dec_bjp_info_bus[`DECINFO_BJP_BGE] = inst_bge; 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_BLTU] = inst_bltu;
assign dec_bjp_info_bus[`DECINFO_BJP_BGEU] = inst_bgeu; assign dec_bjp_info_bus[`DECINFO_BJP_BGEU] = inst_bgeu;
assign dec_bjp_info_bus[`DECINFO_BJP_OP1RS1] = inst_jalr; assign dec_bjp_info_bus[`DECINFO_BJP_OP1RS1] = inst_jalr;
wire[`DECINFO_MULDIV_BUS_WIDTH-1:0] dec_muldiv_info_bus; 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_GRP_BUS] = `DECINFO_GRP_MULDIV;
assign dec_muldiv_info_bus[`DECINFO_MULDIV_MUL] = inst_mul; 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_MULH] = inst_mulh;
assign dec_muldiv_info_bus[`DECINFO_MULDIV_MULHSU] = inst_mulhsu; 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_MULHU] = inst_mulhu;
assign dec_muldiv_info_bus[`DECINFO_MULDIV_DIV] = inst_div; 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_DIVU] = inst_divu;
assign dec_muldiv_info_bus[`DECINFO_MULDIV_REM] = inst_rem; assign dec_muldiv_info_bus[`DECINFO_MULDIV_REM] = inst_rem;
assign dec_muldiv_info_bus[`DECINFO_MULDIV_REMU] = inst_remu; assign dec_muldiv_info_bus[`DECINFO_MULDIV_REMU] = inst_remu;
wire[`DECINFO_CSR_BUS_WIDTH-1:0] dec_csr_info_bus; 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_GRP_BUS] = `DECINFO_GRP_CSR;
assign dec_csr_info_bus[`DECINFO_CSR_CSRRW] = inst_csrrw | inst_csrrwi; 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_CSRRS] = inst_csrrs | inst_csrrsi;
assign dec_csr_info_bus[`DECINFO_CSR_CSRRC] = inst_csrrc | inst_csrrci; 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_RS1IMM] = inst_csrrwi | inst_csrrsi | inst_csrrci;
assign dec_csr_info_bus[`DECINFO_CSR_CSRADDR] = inst_i[31:20]; assign dec_csr_info_bus[`DECINFO_CSR_CSRADDR] = inst_i[31:20];
wire[`DECINFO_MEM_BUS_WIDTH-1:0] dec_mem_info_bus; 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_GRP_BUS] = `DECINFO_GRP_MEM;
assign dec_mem_info_bus[`DECINFO_MEM_LB] = inst_lb; 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_LH] = inst_lh;
assign dec_mem_info_bus[`DECINFO_MEM_LW] = inst_lw; 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_LBU] = inst_lbu;
assign dec_mem_info_bus[`DECINFO_MEM_LHU] = inst_lhu; 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_SB] = inst_sb;
assign dec_mem_info_bus[`DECINFO_MEM_SH] = inst_sh; assign dec_mem_info_bus[`DECINFO_MEM_SH] = inst_sh;
assign dec_mem_info_bus[`DECINFO_MEM_SW] = inst_sw; assign dec_mem_info_bus[`DECINFO_MEM_SW] = inst_sw;
wire[`DECINFO_SYS_BUS_WIDTH-1:0] dec_sys_info_bus; 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_GRP_BUS] = `DECINFO_GRP_SYS;
assign dec_sys_info_bus[`DECINFO_SYS_ECALL] = inst_ecall; 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_EBREAK] = inst_ebreak;
assign dec_sys_info_bus[`DECINFO_SYS_NOP] = inst_nop; 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_MRET] = inst_mret;
assign dec_sys_info_bus[`DECINFO_SYS_FENCE] = inst_fence | inst_fence_i; 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_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_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_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_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_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_csr_type_imm = {27'h0, inst_i[19:15]};
wire[31:0] inst_shift_type_imm = {27'h0, inst_i[24:20]}; 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_u_imm = inst_lui | inst_auipc;
wire inst_sel_j_imm = inst_jal; wire inst_sel_j_imm = inst_jal;
wire inst_sel_b_imm = inst_type_branch; wire inst_sel_b_imm = inst_type_branch;
wire inst_sel_s_imm = inst_type_store; 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_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_csr_imm = inst_csrrwi | inst_csrrsi | inst_csrrci;
wire inst_sel_shift_imm = inst_slli | inst_srli | inst_srai; wire inst_sel_shift_imm = inst_slli | inst_srli | inst_srai;
assign dec_imm_o = ({32{inst_sel_u_imm}} & inst_u_type_imm) | 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_j_imm}} & inst_j_type_imm) |
({32{inst_sel_b_imm}} & inst_b_type_imm) | ({32{inst_sel_b_imm}} & inst_b_type_imm) |
({32{inst_sel_s_imm}} & inst_s_type_imm) | ({32{inst_sel_s_imm}} & inst_s_type_imm) |
({32{inst_sel_i_imm}} & inst_i_type_imm) | ({32{inst_sel_i_imm}} & inst_i_type_imm) |
({32{inst_sel_csr_imm}} & inst_csr_type_imm) | ({32{inst_sel_csr_imm}} & inst_csr_type_imm) |
({32{inst_sel_shift_imm}} & inst_shift_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_alu = inst_lui | inst_auipc | opcode_0010011 | (opcode_0110011 & (~inst_type_muldiv));
wire op_bjp = inst_jal | inst_jalr | inst_type_branch; wire op_bjp = inst_jal | inst_jalr | inst_type_branch;
wire op_muldiv = inst_type_muldiv; wire op_muldiv = inst_type_muldiv;
wire op_csr = inst_csrrw | inst_csrrwi | inst_csrrs | inst_csrrsi | inst_csrrc | inst_csrrci; 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_sys = inst_ebreak | inst_ecall | inst_nop | inst_mret | inst_fence | inst_fence_i;
wire op_mem = inst_type_load | inst_type_store; 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}) | 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_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_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_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_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}); ({`DECINFO_WIDTH{op_sys}} & {{`DECINFO_WIDTH-`DECINFO_SYS_BUS_WIDTH{1'b0}}, dec_sys_info_bus});
assign dec_pc_o = inst_addr_i; assign dec_pc_o = inst_addr_i;
// 是否需要访问rs1寄存器 // 是否需要访问rs1寄存器
wire access_rs1 = (~inst_lui) & wire access_rs1 = (~inst_lui) &
(~inst_auipc) & (~inst_auipc) &
(~inst_jal) & (~inst_jal) &
(~inst_ecall) & (~inst_ecall) &
(~inst_ebreak) & (~inst_ebreak) &
(~inst_csrrwi) & (~inst_csrrwi) &
(~inst_csrrsi) & (~inst_csrrsi) &
(~inst_csrrci) & (~inst_csrrci) &
(~inst_nop) & (~inst_nop) &
(~inst_fence) & (~inst_fence) &
(~inst_fence_i) & (~inst_fence_i) &
(~inst_mret); (~inst_mret);
assign rs1_raddr_o = access_rs1? rs1: 5'h0; assign rs1_raddr_o = access_rs1? rs1: 5'h0;
// 是否需要访问rs2寄存器 // 是否需要访问rs2寄存器
wire access_rs2 = opcode_0110011 | inst_type_store | inst_type_branch; wire access_rs2 = opcode_0110011 | inst_type_store | inst_type_branch;
assign rs2_raddr_o = access_rs2? rs2: 5'h0; assign rs2_raddr_o = access_rs2? rs2: 5'h0;
// 是否需要访问rd寄存器 // 是否需要访问rd寄存器
wire access_rd = inst_lui | inst_auipc | inst_jal | inst_jalr | inst_type_load | opcode_0010011 | opcode_0110011 | op_csr; 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_waddr_o = access_rd? rd: 5'h0;
assign rd_we_o = access_rd; assign rd_we_o = access_rd;
assign stall_o = 1'b0; assign stall_o = 1'b0;
endmodule endmodule

View File

@ -1,90 +1,97 @@
/* /*
Copyright 2020 Blue Liang, liangkangnan@163.com Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
`include "defines.sv" `include "defines.sv"
// 将译码结果向执行模块传递 // 将译码结果向执行模块传递
module idu_exu( module idu_exu(
input wire clk, input wire clk,
input wire rst_n, input wire rst_n,
input wire[`STALL_WIDTH-1:0] stall_i, // 流水线暂停 input wire[`STALL_WIDTH-1:0] stall_i, // 流水线暂停
input wire flush_i, // 流水线冲刷 input wire flush_i, // 流水线冲刷
input wire[31:0] inst_i, input wire[31:0] inst_i,
input wire[`DECINFO_WIDTH-1:0] dec_info_bus_i, input wire inst_valid_i,
input wire[31:0] dec_imm_i, input wire[`DECINFO_WIDTH-1:0] dec_info_bus_i,
input wire[31:0] dec_pc_i, input wire[31:0] dec_imm_i,
input wire[31:0] rs1_rdata_i, input wire[31:0] dec_pc_i,
input wire[31:0] rs2_rdata_i, input wire[31:0] rs1_rdata_i,
input wire[4:0] rd_waddr_i, input wire[31:0] rs2_rdata_i,
input wire rd_we_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] inst_o,
output wire[31:0] dec_imm_o, output wire inst_valid_o,
output wire[31:0] dec_pc_o, output wire[`DECINFO_WIDTH-1:0] dec_info_bus_o,
output wire[31:0] rs1_rdata_o, output wire[31:0] dec_imm_o,
output wire[31:0] rs2_rdata_o, output wire[31:0] dec_pc_o,
output wire[4:0] rd_waddr_o, output wire[31:0] rs1_rdata_o,
output wire rd_we_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 en = !stall_i[`STALL_EX] | flush_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); wire[`DECINFO_WIDTH-1:0] i_dec_info_bus = flush_i? {`DECINFO_WIDTH{1'b0}}: dec_info_bus_i;
assign dec_info_bus_o = dec_info_bus; 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);
wire[31:0] i_dec_imm = flush_i? 32'h0: dec_imm_i; assign dec_info_bus_o = dec_info_bus;
wire[31:0] dec_imm;
gen_en_dff #(32) imm_ff(clk, rst_n, en, i_dec_imm, dec_imm); wire[31:0] i_dec_imm = flush_i? 32'h0: dec_imm_i;
assign dec_imm_o = dec_imm; wire[31:0] dec_imm;
gen_en_dff #(32) imm_ff(clk, rst_n, en, i_dec_imm, dec_imm);
wire[31:0] i_dec_pc = flush_i? 32'h0: dec_pc_i; assign dec_imm_o = dec_imm;
wire[31:0] dec_pc;
gen_en_dff #(32) pc_ff(clk, rst_n, en, i_dec_pc, dec_pc); wire[31:0] i_dec_pc = flush_i? 32'h0: dec_pc_i;
assign dec_pc_o = dec_pc; wire[31:0] dec_pc;
gen_en_dff #(32) pc_ff(clk, rst_n, en, i_dec_pc, dec_pc);
wire[31:0] i_rs1_rdata = flush_i? 32'h0: rs1_rdata_i; assign dec_pc_o = dec_pc;
wire[31:0] rs1_rdata;
gen_en_dff #(32) rs1_rdata_ff(clk, rst_n, en, i_rs1_rdata, rs1_rdata); wire[31:0] i_rs1_rdata = flush_i? 32'h0: rs1_rdata_i;
assign rs1_rdata_o = rs1_rdata; wire[31:0] rs1_rdata;
gen_en_dff #(32) rs1_rdata_ff(clk, rst_n, en, i_rs1_rdata, rs1_rdata);
wire[31:0] i_rs2_rdata = flush_i? 32'h0: rs2_rdata_i; assign rs1_rdata_o = rs1_rdata;
wire[31:0] rs2_rdata;
gen_en_dff #(32) rs2_rdata_ff(clk, rst_n, en, i_rs2_rdata, rs2_rdata); wire[31:0] i_rs2_rdata = flush_i? 32'h0: rs2_rdata_i;
assign rs2_rdata_o = rs2_rdata; wire[31:0] rs2_rdata;
gen_en_dff #(32) rs2_rdata_ff(clk, rst_n, en, i_rs2_rdata, rs2_rdata);
wire[4:0] i_rd_waddr = flush_i? 5'h0: rd_waddr_i; assign rs2_rdata_o = rs2_rdata;
wire[4:0] rd_waddr;
gen_en_dff #(5) rd_waddr_ff(clk, rst_n, en, i_rd_waddr, rd_waddr); wire[4:0] i_rd_waddr = flush_i? 5'h0: rd_waddr_i;
assign rd_waddr_o = rd_waddr; wire[4:0] rd_waddr;
gen_en_dff #(5) rd_waddr_ff(clk, rst_n, en, i_rd_waddr, rd_waddr);
wire i_rd_we = flush_i? 1'b0: rd_we_i; assign rd_waddr_o = rd_waddr;
wire rd_we;
gen_en_dff #(1) rd_we_ff(clk, rst_n, en, i_rd_we, rd_we); wire i_rd_we = flush_i? 1'b0: rd_we_i;
assign rd_we_o = rd_we; wire rd_we;
gen_en_dff #(1) rd_we_ff(clk, rst_n, en, i_rd_we, rd_we);
wire[31:0] i_inst = flush_i? 32'h0: inst_i; assign rd_we_o = rd_we;
wire[31:0] inst;
gen_en_dff #(32) inst_ff(clk, rst_n, en, i_inst, inst); wire[31:0] i_inst = flush_i? 32'h0: inst_i;
assign inst_o = inst; wire[31:0] inst;
gen_en_dff #(32) inst_ff(clk, rst_n, en, i_inst, inst);
endmodule 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

View File

@ -1,125 +1,126 @@
/* /*
Copyright 2020 Blue Liang, liangkangnan@163.com Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
`include "defines.sv" `include "defines.sv"
// 取指模块 // 取指模块
module ifu( module ifu(
input wire clk, input wire clk,
input wire rst_n, input wire rst_n,
input wire flush_i, input wire flush_i,
input wire[31:0] flush_addr_i, // 跳转地址 input wire[31:0] flush_addr_i, // 跳转地址
input wire[`STALL_WIDTH-1:0] stall_i, // 流水线暂停标志 input wire[`STALL_WIDTH-1:0] stall_i, // 流水线暂停标志
input wire jtag_halt_i, input wire jtag_halt_i,
output wire[31:0] inst_o, output wire[31:0] inst_o,
output wire[31:0] pc_o, output wire[31:0] pc_o,
output wire inst_valid_o, output wire inst_valid_o,
output wire[31:0] ibus_addr_o, output wire[31:0] ibus_addr_o,
input wire[31:0] ibus_data_i, input wire[31:0] ibus_data_i,
output wire[31:0] ibus_data_o, output wire[31:0] ibus_data_o,
output wire[3:0] ibus_sel_o, output wire[3:0] ibus_sel_o,
output wire ibus_we_o, output wire ibus_we_o,
output wire req_valid_o, output wire req_valid_o,
input wire req_ready_i, input wire req_ready_i,
input wire rsp_valid_i, input wire rsp_valid_i,
output wire rsp_ready_o output wire rsp_ready_o
); );
assign req_valid_o = (~rst_n)? 1'b0: assign req_valid_o = (~rst_n)? 1'b0:
(flush_i)? 1'b0: (flush_i)? 1'b0:
stall_i[`STALL_PC]? 1'b0: stall_i[`STALL_PC]? 1'b0:
jtag_halt_i? 1'b0: jtag_halt_i? 1'b0:
1'b1; 1'b1;
assign rsp_ready_o = (~rst_n)? 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_req_hsked = (req_valid_o & req_ready_i);
wire ifu_rsp_hsked = (rsp_valid_i & rsp_ready_o); wire ifu_rsp_hsked = (rsp_valid_i & rsp_ready_o);
// 在执行多周期指令或者请求不到总线时需要暂停 // 在执行多周期指令或者请求不到总线时需要暂停
wire stall = stall_i[`STALL_PC] | (~ifu_req_hsked); wire stall = stall_i[`STALL_PC] | (~ifu_req_hsked);
reg[31:0] pc; reg[31:0] pc;
reg[31:0] pc_prev; reg[31:0] pc_prev;
always @ (posedge clk or negedge rst_n) begin always @ (posedge clk or negedge rst_n) begin
// 复位 // 复位
if (!rst_n) begin if (!rst_n) begin
pc <= `CPU_RESET_ADDR; pc <= `CPU_RESET_ADDR;
pc_prev <= 32'h0; pc_prev <= 32'h0;
// 冲刷 // 冲刷
end else if (flush_i) begin end else if (flush_i) begin
pc <= flush_addr_i; pc <= flush_addr_i;
// 暂停,取上一条指令 // 暂停,取上一条指令
end else if (stall) begin end else if (stall) begin
pc <= pc_prev; pc <= pc_prev;
// 取下一条指令 // 取下一条指令
end else begin end else begin
pc <= pc + 32'h4; pc <= pc + 32'h4;
pc_prev <= pc; pc_prev <= pc;
end end
end end
wire[31:0] pc_r; wire[31:0] pc_r;
// 将PC打一拍 // 将PC打一拍
wire pc_ena = (~stall); wire pc_ena = (~stall);
gen_en_dff #(32) pc_dff(clk, rst_n, pc_ena, pc, pc_r); gen_en_dff #(32) pc_dff(clk, rst_n, pc_ena, pc, pc_r);
reg req_hasked_r; reg req_hasked_r;
always @ (posedge clk or negedge rst_n) begin always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin if (!rst_n) begin
req_hasked_r <= 1'b1; req_hasked_r <= 1'b1;
end else begin end else begin
req_hasked_r <= ifu_req_hsked; req_hasked_r <= ifu_req_hsked;
end end
end end
wire req_switched = ifu_req_hsked & (~req_hasked_r); wire req_switched = ifu_req_hsked & (~req_hasked_r);
reg rsp_hasked_r; reg rsp_hasked_r;
always @ (posedge clk or negedge rst_n) begin always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin if (!rst_n) begin
rsp_hasked_r <= 1'b1; rsp_hasked_r <= 1'b1;
end else begin end else begin
rsp_hasked_r <= ifu_rsp_hsked; rsp_hasked_r <= ifu_rsp_hsked;
end end
end end
wire rsp_switched = ifu_rsp_hsked & (~rsp_hasked_r); wire rsp_switched = ifu_rsp_hsked & (~rsp_hasked_r);
// 总线切换有两种情况: // 总线切换有两种情况:
// 1.访存地址位于指令存储器当访存完成后ifu_req_hsked和ifu_rsp_hsked信号会同时从0变为1 // 1.访存地址位于指令存储器当访存完成后ifu_req_hsked和ifu_rsp_hsked信号会同时从0变为1
// 2.访存地址不位于指令存储器当访存完成后ifu_req_hsked先从0变为1和ifu_rsp_hsked后从0变为1 // 2.访存地址不位于指令存储器当访存完成后ifu_req_hsked先从0变为1和ifu_rsp_hsked后从0变为1
// 只有第2种情况下取出来的指令是有效的这里要把这两种情况识别出来 // 只有第2种情况下取出来的指令是有效的这里要把这两种情况识别出来
wire bus_switched = req_switched & rsp_switched; wire bus_switched = req_switched & rsp_switched;
// 取指地址 // 取指地址
assign ibus_addr_o = pc; assign ibus_addr_o = pc;
assign pc_o = pc_r; assign pc_o = pc_r;
wire inst_valid = ifu_rsp_hsked & (~flush_i) & (~bus_switched); wire inst_valid = ifu_rsp_hsked & (~flush_i) & (~bus_switched);
assign inst_o = inst_valid? ibus_data_i: `INST_NOP; 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_sel_o = 4'b1111;
assign ibus_data_o = 32'h0; assign ibus_we_o = 1'b0;
assign ibus_data_o = 32'h0;
endmodule
endmodule

View File

@ -1,48 +1,54 @@
/* /*
Copyright 2019 Blue Liang, liangkangnan@163.com Copyright 2019 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
`include "defines.sv" `include "defines.sv"
// 将指令向译码模块传递 // 将指令向译码模块传递
module ifu_idu( module ifu_idu(
input wire clk, input wire clk,
input wire rst_n, input wire rst_n,
input wire[31:0] inst_i, // 指令内容 input wire[31:0] inst_i, // 指令内容
input wire[31:0] inst_addr_i, // 指令地址 input wire[31:0] inst_addr_i, // 指令地址
input wire[`STALL_WIDTH-1:0] stall_i, // 流水线暂停 input wire[`STALL_WIDTH-1:0] stall_i, // 流水线暂停
input wire flush_i, // 流水线冲刷 input wire flush_i, // 流水线冲刷
input wire inst_valid_i, input wire inst_valid_i,
output wire[31:0] inst_o, // 指令内容 output wire inst_valid_o,
output wire[31:0] inst_addr_o // 指令地址 output wire[31:0] inst_o, // 指令内容
output wire[31:0] inst_addr_o // 指令地址
);
);
wire en = !stall_i[`STALL_ID] | flush_i;
wire en = !stall_i[`STALL_ID] | flush_i;
wire[31:0] i_inst = (flush_i)? `INST_NOP: inst_i;
wire[31:0] inst; wire[31:0] i_inst = (flush_i)? `INST_NOP: inst_i;
gen_en_dff #(32) inst_ff(clk, rst_n, en, i_inst, inst); wire[31:0] inst;
assign inst_o = 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; wire[31:0] i_inst_addr = flush_i? 32'h0: inst_addr_i;
gen_en_dff #(32) inst_addr_ff(clk, rst_n, en, i_inst_addr, inst_addr); wire[31:0] inst_addr;
assign inst_addr_o = 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
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

View File

@ -1,65 +1,65 @@
/* /*
Copyright 2019 Blue Liang, liangkangnan@163.com Copyright 2019 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
`include "defines.sv" `include "defines.sv"
// 流水线控制模块 // 流水线控制模块
// 发出暂停、冲刷流水线信号 // 发出暂停、冲刷流水线信号
module pipe_ctrl( module pipe_ctrl(
input wire clk, input wire clk,
input wire rst_n, input wire rst_n,
input wire stall_from_id_i, input wire stall_from_id_i,
input wire stall_from_ex_i, input wire stall_from_ex_i,
input wire stall_from_jtag_i, input wire stall_from_jtag_i,
input wire stall_from_clint_i, input wire stall_from_clint_i,
input wire jump_assert_i, input wire jump_assert_i,
input wire[31:0] jump_addr_i, input wire[31:0] jump_addr_i,
output wire flush_o, output wire flush_o,
output wire[`STALL_WIDTH-1:0] stall_o, output wire[`STALL_WIDTH-1:0] stall_o,
output wire[31:0] flush_addr_o output wire[31:0] flush_addr_o
); );
assign flush_addr_o = jump_addr_i; assign flush_addr_o = jump_addr_i;
assign flush_o = jump_assert_i | stall_from_clint_i; assign flush_o = jump_assert_i | stall_from_clint_i;
reg[`STALL_WIDTH-1:0] stall; reg[`STALL_WIDTH-1:0] stall;
always @ (*) begin always @ (*) begin
if (stall_from_ex_i | stall_from_clint_i) begin if (stall_from_ex_i | stall_from_clint_i) begin
stall[`STALL_EX] = 1'b1; stall[`STALL_EX] = 1'b1;
stall[`STALL_ID] = 1'b1; stall[`STALL_ID] = 1'b1;
stall[`STALL_IF] = 1'b1; stall[`STALL_IF] = 1'b1;
stall[`STALL_PC] = 1'b1; stall[`STALL_PC] = 1'b1;
end else if (stall_from_id_i) begin end else if (stall_from_id_i) begin
stall[`STALL_EX] = 1'b0; stall[`STALL_EX] = 1'b0;
stall[`STALL_ID] = 1'b0; stall[`STALL_ID] = 1'b0;
stall[`STALL_IF] = 1'b1; stall[`STALL_IF] = 1'b1;
stall[`STALL_PC] = 1'b1; stall[`STALL_PC] = 1'b1;
end else begin end else begin
stall[`STALL_EX] = 1'b0; stall[`STALL_EX] = 1'b0;
stall[`STALL_ID] = 1'b0; stall[`STALL_ID] = 1'b0;
stall[`STALL_IF] = 1'b0; stall[`STALL_IF] = 1'b0;
stall[`STALL_PC] = 1'b0; stall[`STALL_PC] = 1'b0;
end end
end end
assign stall_o = stall; assign stall_o = stall;
endmodule endmodule

View File

@ -1,59 +1,59 @@
/* /*
Copyright 2020 Blue Liang, liangkangnan@163.com Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
`include "defines.sv" `include "defines.sv"
// 复位控制模块 // 复位控制模块
module rst_ctrl( module rst_ctrl(
input wire clk, input wire clk,
input wire rst_ext_i, input wire rst_ext_i,
input wire rst_jtag_i, input wire rst_jtag_i,
output wire core_rst_n_o, output wire core_rst_n_o,
output wire jtag_rst_n_o output wire jtag_rst_n_o
); );
wire ext_rst_r; wire ext_rst_r;
gen_ticks_sync #( gen_ticks_sync #(
.DP(2), .DP(2),
.DW(1) .DW(1)
) ext_rst_sync( ) ext_rst_sync(
.rst_n(rst_ext_i), .rst_n(rst_ext_i),
.clk(clk), .clk(clk),
.din(1'b1), .din(1'b1),
.dout(ext_rst_r) .dout(ext_rst_r)
); );
reg[`JTAG_RESET_FF_LEVELS-1:0] jtag_rst_r; reg[`JTAG_RESET_FF_LEVELS-1:0] jtag_rst_r;
always @ (posedge clk) begin always @ (posedge clk) begin
if (!rst_ext_i) begin if (!rst_ext_i) begin
jtag_rst_r[`JTAG_RESET_FF_LEVELS-1:0] <= {`JTAG_RESET_FF_LEVELS{1'b1}}; jtag_rst_r[`JTAG_RESET_FF_LEVELS-1:0] <= {`JTAG_RESET_FF_LEVELS{1'b1}};
end if (rst_jtag_i) begin end if (rst_jtag_i) begin
jtag_rst_r[`JTAG_RESET_FF_LEVELS-1:0] <= {`JTAG_RESET_FF_LEVELS{1'b0}}; jtag_rst_r[`JTAG_RESET_FF_LEVELS-1:0] <= {`JTAG_RESET_FF_LEVELS{1'b0}};
end else begin end else begin
jtag_rst_r[`JTAG_RESET_FF_LEVELS-1:0] <= {jtag_rst_r[`JTAG_RESET_FF_LEVELS-2:0], 1'b1}; jtag_rst_r[`JTAG_RESET_FF_LEVELS-1:0] <= {jtag_rst_r[`JTAG_RESET_FF_LEVELS-2:0], 1'b1};
end end
end end
assign core_rst_n_o = ext_rst_r & jtag_rst_r[`JTAG_RESET_FF_LEVELS-1]; assign core_rst_n_o = ext_rst_r & jtag_rst_r[`JTAG_RESET_FF_LEVELS-1];
assign jtag_rst_n_o = ext_rst_r; assign jtag_rst_n_o = ext_rst_r;
endmodule endmodule

View File

@ -56,6 +56,7 @@ module tinyriscv_core(
wire[31:0] if_inst_o; wire[31:0] if_inst_o;
wire[31:0] if_inst_addr_o; wire[31:0] if_inst_addr_o;
wire[`INT_WIDTH-1:0] if_int_flag_o; wire[`INT_WIDTH-1:0] if_int_flag_o;
wire if_inst_valid_o;
// idu模块输出信号 // idu模块输出信号
wire[31:0] id_inst_o; wire[31:0] id_inst_o;
@ -81,6 +82,7 @@ module tinyriscv_core(
wire[31:0] ie_rs2_rdata_o; wire[31:0] ie_rs2_rdata_o;
wire[4:0] ie_rd_waddr_o; wire[4:0] ie_rd_waddr_o;
wire ie_rd_we_o; wire ie_rd_we_o;
wire ie_inst_valid_o;
// exu模块输出信号 // exu模块输出信号
wire[31:0] ex_mem_wdata_o; wire[31:0] ex_mem_wdata_o;
@ -103,6 +105,7 @@ module tinyriscv_core(
wire ex_inst_ecall_o; wire ex_inst_ecall_o;
wire ex_inst_ebreak_o; wire ex_inst_ebreak_o;
wire ex_inst_mret_o; wire ex_inst_mret_o;
wire ex_inst_valid_o;
// gpr_reg模块输出信号 // gpr_reg模块输出信号
wire[31:0] regs_rdata1_o; wire[31:0] regs_rdata1_o;
@ -207,6 +210,7 @@ module tinyriscv_core(
.stall_i(ctrl_stall_o), .stall_i(ctrl_stall_o),
.flush_i(ctrl_flush_o), .flush_i(ctrl_flush_o),
.inst_valid_i(ifetch_inst_valid_o), .inst_valid_i(ifetch_inst_valid_o),
.inst_valid_o(if_inst_valid_o),
.inst_o(if_inst_o), .inst_o(if_inst_o),
.inst_addr_o(if_inst_addr_o) .inst_addr_o(if_inst_addr_o)
); );
@ -244,6 +248,8 @@ module tinyriscv_core(
.rs2_rdata_i(id_rs2_rdata_o), .rs2_rdata_i(id_rs2_rdata_o),
.rd_waddr_i(id_rd_waddr_o), .rd_waddr_i(id_rd_waddr_o),
.rd_we_i(id_rd_we_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), .inst_o(ie_inst_o),
.dec_info_bus_o(ie_dec_info_bus_o), .dec_info_bus_o(ie_dec_info_bus_o),
.dec_imm_o(ie_dec_imm_o), .dec_imm_o(ie_dec_imm_o),
@ -286,6 +292,9 @@ module tinyriscv_core(
.csr_wdata_o(ex_csr_wdata_o), .csr_wdata_o(ex_csr_wdata_o),
.csr_we_o(ex_csr_we_o), .csr_we_o(ex_csr_we_o),
.csr_waddr_o(ex_csr_waddr_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_info_bus_i(ie_dec_info_bus_o),
.dec_imm_i(ie_dec_imm_o), .dec_imm_i(ie_dec_imm_o),
.dec_pc_i(ie_dec_pc_o), .dec_pc_i(ie_dec_pc_o),
@ -317,7 +326,11 @@ module tinyriscv_core(
`ifdef TRACE_ENABLED `ifdef TRACE_ENABLED
tracer u_tracer( 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 `endif

View File

@ -584,12 +584,14 @@ module tracer(
$display("Writing execution trace to %s", file_name); $display("Writing execution trace to %s", file_name);
file_handle = $fopen(file_name, "w"); 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 end
function automatic void printbuffer_dumpline(); 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"); $fwrite(file_handle, "\n");
endfunction endfunction