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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -584,12 +584,14 @@ module tracer(
$display("Writing execution trace to %s", file_name);
file_handle = $fopen(file_name, "w");
$fwrite(file_handle, "Time\tCycle\tPC\tInsn\tDecoded instruction\n");
$fwrite(file_handle, "\t\t\tTime\tCycle\tPC\tInsn\tDecoded instruction\n");
end
function automatic void printbuffer_dumpline();
$fwrite(file_handle, "%15t\t%d\t%h\t%s\t%s", $time, cycle, pc_i, inst_i, decoded_str);
string insn_str = $sformatf("%h", inst_i);
$fwrite(file_handle, "%15t\t%d\t%h\t%s\t%s", $time, cycle, pc_i, insn_str, decoded_str);
$fwrite(file_handle, "\n");
endfunction