parent
c070f0b49d
commit
9943d02600
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
763
rtl/core/exu.sv
763
rtl/core/exu.sv
|
@ -1,378 +1,385 @@
|
|||
/*
|
||||
Copyright 2019 Blue Liang, liangkangnan@163.com
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "defines.sv"
|
||||
|
||||
// 执行模块
|
||||
// 纯组合逻辑电路
|
||||
module exu(
|
||||
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
|
||||
// clint
|
||||
input wire int_assert_i, // 中断发生标志
|
||||
input wire[31:0] int_addr_i, // 中断跳转地址
|
||||
input wire int_stall_i, // 暂停标志
|
||||
output wire inst_ecall_o, // ecall指令
|
||||
output wire inst_ebreak_o, // ebreak指令
|
||||
output wire inst_mret_o, // mret指令
|
||||
|
||||
// mem
|
||||
input wire[31:0] mem_rdata_i, // 内存输入数据
|
||||
input wire mem_req_ready_i,
|
||||
input wire mem_rsp_valid_i,
|
||||
output wire[31:0] mem_wdata_o, // 写内存数据
|
||||
output wire[31:0] mem_addr_o, // 读、写内存地址
|
||||
output wire mem_we_o, // 是否要写内存
|
||||
output wire[3:0] mem_sel_o, // 字节位
|
||||
output wire mem_req_valid_o,
|
||||
output wire mem_rsp_ready_o,
|
||||
output wire mem_access_misaligned_o,
|
||||
|
||||
// gpr_reg
|
||||
output wire[31:0] reg_wdata_o, // 写寄存器数据
|
||||
output wire reg_we_o, // 是否要写通用寄存器
|
||||
output wire[4:0] reg_waddr_o, // 写通用寄存器地址
|
||||
|
||||
// csr_reg
|
||||
input wire[31:0] csr_rdata_i,
|
||||
output wire[31:0] csr_raddr_o, // 读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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
606
rtl/core/idu.sv
606
rtl/core/idu.sv
|
@ -1,303 +1,303 @@
|
|||
/*
|
||||
Copyright 2019 Blue Liang, liangkangnan@163.com
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "defines.sv"
|
||||
|
||||
// 译码模块
|
||||
// 纯组合逻辑电路
|
||||
module idu(
|
||||
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
|
||||
// from if_id
|
||||
input wire[31:0] inst_i, // 指令内容
|
||||
input wire[31:0] inst_addr_i, // 指令地址
|
||||
|
||||
// from gpr_reg
|
||||
input wire[31:0] rs1_rdata_i, // 通用寄存器1输入数据
|
||||
input wire[31:0] rs2_rdata_i, // 通用寄存器2输入数据
|
||||
|
||||
output wire stall_o,
|
||||
|
||||
// to id_ex
|
||||
output wire[31:0] inst_o,
|
||||
output wire[`DECINFO_WIDTH-1:0] dec_info_bus_o,
|
||||
output wire[31:0] dec_imm_o,
|
||||
output wire[31:0] dec_pc_o,
|
||||
output wire[4:0] rs1_raddr_o,
|
||||
output wire[4:0] rs2_raddr_o,
|
||||
output wire[31:0] rs1_rdata_o,
|
||||
output wire[31:0] rs2_rdata_o,
|
||||
output wire[4:0] rd_waddr_o,
|
||||
output wire rd_we_o
|
||||
|
||||
);
|
||||
|
||||
assign inst_o = inst_i;
|
||||
assign rs1_rdata_o = rs1_rdata_i;
|
||||
assign rs2_rdata_o = rs2_rdata_i;
|
||||
|
||||
// 取出指令中的每一个域
|
||||
wire[6:0] opcode = inst_i[6:0];
|
||||
wire[2:0] funct3 = inst_i[14:12];
|
||||
wire[6:0] funct7 = inst_i[31:25];
|
||||
wire[4:0] rd = inst_i[11:7];
|
||||
wire[4:0] rs1 = inst_i[19:15];
|
||||
wire[4:0] rs2 = inst_i[24:20];
|
||||
wire[11:0] type_i_imm_11_0 = inst_i[31:20];
|
||||
wire[6:0] type_s_imm_11_5 = inst_i[31:25];
|
||||
wire[4:0] type_s_imm_4_0 = inst_i[11:7];
|
||||
wire[6:0] type_b_imm_12_10_5 = inst_i[31:25];
|
||||
wire[4:0] type_b_imm_4_1_11 = inst_i[11:7];
|
||||
wire[19:0] type_u_imm_31_12 = inst_i[31:12];
|
||||
wire[19:0] type_j_imm_31_12 = inst_i[31:12];
|
||||
|
||||
// 指令opcode域的取值
|
||||
wire opcode_0110111 = (opcode == 7'b0110111);
|
||||
wire opcode_0010111 = (opcode == 7'b0010111);
|
||||
wire opcode_1101111 = (opcode == 7'b1101111);
|
||||
wire opcode_1100111 = (opcode == 7'b1100111);
|
||||
wire opcode_1100011 = (opcode == 7'b1100011);
|
||||
wire opcode_0000011 = (opcode == 7'b0000011);
|
||||
wire opcode_0100011 = (opcode == 7'b0100011);
|
||||
wire opcode_0010011 = (opcode == 7'b0010011);
|
||||
wire opcode_0110011 = (opcode == 7'b0110011);
|
||||
wire opcode_0001111 = (opcode == 7'b0001111);
|
||||
wire opcode_1110011 = (opcode == 7'b1110011);
|
||||
|
||||
// 指令funct3域的取值
|
||||
wire funct3_000 = (funct3 == 3'b000);
|
||||
wire funct3_001 = (funct3 == 3'b001);
|
||||
wire funct3_010 = (funct3 == 3'b010);
|
||||
wire funct3_011 = (funct3 == 3'b011);
|
||||
wire funct3_100 = (funct3 == 3'b100);
|
||||
wire funct3_101 = (funct3 == 3'b101);
|
||||
wire funct3_110 = (funct3 == 3'b110);
|
||||
wire funct3_111 = (funct3 == 3'b111);
|
||||
|
||||
// 指令funct7域的取值
|
||||
wire funct7_0000000 = (funct7 == 7'b0000000);
|
||||
wire funct7_0100000 = (funct7 == 7'b0100000);
|
||||
wire funct7_0000001 = (funct7 == 7'b0000001);
|
||||
|
||||
// I类型指令imm域的取值
|
||||
wire type_i_imm_000000000000 = (type_i_imm_11_0 == 12'b000000000000);
|
||||
wire type_i_imm_000000000001 = (type_i_imm_11_0 == 12'b000000000001);
|
||||
|
||||
// 译码出具体指令
|
||||
wire inst_lui = opcode_0110111;
|
||||
wire inst_auipc = opcode_0010111;
|
||||
wire inst_jal = opcode_1101111;
|
||||
wire inst_jalr = opcode_1100111 & funct3_000;
|
||||
wire inst_beq = opcode_1100011 & funct3_000;
|
||||
wire inst_bne = opcode_1100011 & funct3_001;
|
||||
wire inst_blt = opcode_1100011 & funct3_100;
|
||||
wire inst_bge = opcode_1100011 & funct3_101;
|
||||
wire inst_bltu = opcode_1100011 & funct3_110;
|
||||
wire inst_bgeu = opcode_1100011 & funct3_111;
|
||||
wire inst_lb = opcode_0000011 & funct3_000;
|
||||
wire inst_lh = opcode_0000011 & funct3_001;
|
||||
wire inst_lw = opcode_0000011 & funct3_010;
|
||||
wire inst_lbu = opcode_0000011 & funct3_100;
|
||||
wire inst_lhu = opcode_0000011 & funct3_101;
|
||||
wire inst_sb = opcode_0100011 & funct3_000;
|
||||
wire inst_sh = opcode_0100011 & funct3_001;
|
||||
wire inst_sw = opcode_0100011 & funct3_010;
|
||||
wire inst_addi = opcode_0010011 & funct3_000;
|
||||
wire inst_slti = opcode_0010011 & funct3_010;
|
||||
wire inst_sltiu = opcode_0010011 & funct3_011;
|
||||
wire inst_xori = opcode_0010011 & funct3_100;
|
||||
wire inst_ori = opcode_0010011 & funct3_110;
|
||||
wire inst_andi = opcode_0010011 & funct3_111;
|
||||
wire inst_slli = opcode_0010011 & funct3_001 & funct7_0000000;
|
||||
wire inst_srli = opcode_0010011 & funct3_101 & funct7_0000000;
|
||||
wire inst_srai = opcode_0010011 & funct3_101 & funct7_0100000;
|
||||
wire inst_add = opcode_0110011 & funct3_000 & funct7_0000000;
|
||||
wire inst_sub = opcode_0110011 & funct3_000 & funct7_0100000;
|
||||
wire inst_sll = opcode_0110011 & funct3_001 & funct7_0000000;
|
||||
wire inst_slt = opcode_0110011 & funct3_010 & funct7_0000000;
|
||||
wire inst_sltu = opcode_0110011 & funct3_011 & funct7_0000000;
|
||||
wire inst_xor = opcode_0110011 & funct3_100 & funct7_0000000;
|
||||
wire inst_srl = opcode_0110011 & funct3_101 & funct7_0000000;
|
||||
wire inst_sra = opcode_0110011 & funct3_101 & funct7_0100000;
|
||||
wire inst_or = opcode_0110011 & funct3_110 & funct7_0000000;
|
||||
wire inst_and = opcode_0110011 & funct3_111 & funct7_0000000;
|
||||
wire inst_fence = opcode_0001111 & funct3_000;
|
||||
wire inst_ecall = (inst_i == `INST_ECALL);
|
||||
wire inst_ebreak = (inst_i == `INST_EBREAK);
|
||||
wire inst_fence_i = opcode_0001111 & funct3_001;
|
||||
wire inst_csrrw = opcode_1110011 & funct3_001;
|
||||
wire inst_csrrs = opcode_1110011 & funct3_010;
|
||||
wire inst_csrrc = opcode_1110011 & funct3_011;
|
||||
wire inst_csrrwi = opcode_1110011 & funct3_101;
|
||||
wire inst_csrrsi = opcode_1110011 & funct3_110;
|
||||
wire inst_csrrci = opcode_1110011 & funct3_111;
|
||||
wire inst_mul = opcode_0110011 & funct3_000 & funct7_0000001;
|
||||
wire inst_mulh = opcode_0110011 & funct3_001 & funct7_0000001;
|
||||
wire inst_mulhsu = opcode_0110011 & funct3_010 & funct7_0000001;
|
||||
wire inst_mulhu = opcode_0110011 & funct3_011 & funct7_0000001;
|
||||
wire inst_div = opcode_0110011 & funct3_100 & funct7_0000001;
|
||||
wire inst_divu = opcode_0110011 & funct3_101 & funct7_0000001;
|
||||
wire inst_rem = opcode_0110011 & funct3_110 & funct7_0000001;
|
||||
wire inst_remu = opcode_0110011 & funct3_111 & funct7_0000001;
|
||||
wire inst_nop = (inst_i == `INST_NOP);
|
||||
wire inst_mret = (inst_i == `INST_MRET);
|
||||
|
||||
// 将指令分类
|
||||
wire inst_type_load = opcode_0000011;
|
||||
wire inst_type_store = opcode_0100011;
|
||||
wire inst_type_branch = opcode_1100011;
|
||||
wire inst_type_muldiv = inst_mul | inst_mulh | inst_mulhsu | inst_mulhu | inst_div | inst_divu | inst_rem | inst_remu;
|
||||
wire inst_type_div = inst_div | inst_divu | inst_rem | inst_remu;
|
||||
|
||||
wire[`DECINFO_ALU_BUS_WIDTH-1:0] dec_alu_info_bus;
|
||||
assign dec_alu_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_ALU;
|
||||
assign dec_alu_info_bus[`DECINFO_ALU_LUI] = inst_lui;
|
||||
assign dec_alu_info_bus[`DECINFO_ALU_AUIPC] = inst_auipc;
|
||||
assign dec_alu_info_bus[`DECINFO_ALU_ADD] = inst_add | inst_addi;
|
||||
assign dec_alu_info_bus[`DECINFO_ALU_SUB] = inst_sub;
|
||||
assign dec_alu_info_bus[`DECINFO_ALU_SLL] = inst_sll | inst_slli;
|
||||
assign dec_alu_info_bus[`DECINFO_ALU_SLT] = inst_slt | inst_slti;
|
||||
assign dec_alu_info_bus[`DECINFO_ALU_SLTU] = inst_sltu | inst_sltiu;
|
||||
assign dec_alu_info_bus[`DECINFO_ALU_XOR] = inst_xor | inst_xori;
|
||||
assign dec_alu_info_bus[`DECINFO_ALU_SRL] = inst_srl | inst_srli;
|
||||
assign dec_alu_info_bus[`DECINFO_ALU_SRA] = inst_sra | inst_srai;
|
||||
assign dec_alu_info_bus[`DECINFO_ALU_OR] = inst_or | inst_ori;
|
||||
assign dec_alu_info_bus[`DECINFO_ALU_AND] = inst_and | inst_andi;
|
||||
assign dec_alu_info_bus[`DECINFO_ALU_OP2IMM] = opcode_0010011 | inst_lui | inst_auipc;
|
||||
assign dec_alu_info_bus[`DECINFO_ALU_OP1PC] = inst_auipc;
|
||||
|
||||
wire[`DECINFO_BJP_BUS_WIDTH-1:0] dec_bjp_info_bus;
|
||||
assign dec_bjp_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_BJP;
|
||||
assign dec_bjp_info_bus[`DECINFO_BJP_JUMP] = inst_jal | inst_jalr;
|
||||
assign dec_bjp_info_bus[`DECINFO_BJP_BEQ] = inst_beq;
|
||||
assign dec_bjp_info_bus[`DECINFO_BJP_BNE] = inst_bne;
|
||||
assign dec_bjp_info_bus[`DECINFO_BJP_BLT] = inst_blt;
|
||||
assign dec_bjp_info_bus[`DECINFO_BJP_BGE] = inst_bge;
|
||||
assign dec_bjp_info_bus[`DECINFO_BJP_BLTU] = inst_bltu;
|
||||
assign dec_bjp_info_bus[`DECINFO_BJP_BGEU] = inst_bgeu;
|
||||
assign dec_bjp_info_bus[`DECINFO_BJP_OP1RS1] = inst_jalr;
|
||||
|
||||
wire[`DECINFO_MULDIV_BUS_WIDTH-1:0] dec_muldiv_info_bus;
|
||||
assign dec_muldiv_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_MULDIV;
|
||||
assign dec_muldiv_info_bus[`DECINFO_MULDIV_MUL] = inst_mul;
|
||||
assign dec_muldiv_info_bus[`DECINFO_MULDIV_MULH] = inst_mulh;
|
||||
assign dec_muldiv_info_bus[`DECINFO_MULDIV_MULHSU] = inst_mulhsu;
|
||||
assign dec_muldiv_info_bus[`DECINFO_MULDIV_MULHU] = inst_mulhu;
|
||||
assign dec_muldiv_info_bus[`DECINFO_MULDIV_DIV] = inst_div;
|
||||
assign dec_muldiv_info_bus[`DECINFO_MULDIV_DIVU] = inst_divu;
|
||||
assign dec_muldiv_info_bus[`DECINFO_MULDIV_REM] = inst_rem;
|
||||
assign dec_muldiv_info_bus[`DECINFO_MULDIV_REMU] = inst_remu;
|
||||
|
||||
wire[`DECINFO_CSR_BUS_WIDTH-1:0] dec_csr_info_bus;
|
||||
assign dec_csr_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_CSR;
|
||||
assign dec_csr_info_bus[`DECINFO_CSR_CSRRW] = inst_csrrw | inst_csrrwi;
|
||||
assign dec_csr_info_bus[`DECINFO_CSR_CSRRS] = inst_csrrs | inst_csrrsi;
|
||||
assign dec_csr_info_bus[`DECINFO_CSR_CSRRC] = inst_csrrc | inst_csrrci;
|
||||
assign dec_csr_info_bus[`DECINFO_CSR_RS1IMM] = inst_csrrwi | inst_csrrsi | inst_csrrci;
|
||||
assign dec_csr_info_bus[`DECINFO_CSR_CSRADDR] = inst_i[31:20];
|
||||
|
||||
wire[`DECINFO_MEM_BUS_WIDTH-1:0] dec_mem_info_bus;
|
||||
assign dec_mem_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_MEM;
|
||||
assign dec_mem_info_bus[`DECINFO_MEM_LB] = inst_lb;
|
||||
assign dec_mem_info_bus[`DECINFO_MEM_LH] = inst_lh;
|
||||
assign dec_mem_info_bus[`DECINFO_MEM_LW] = inst_lw;
|
||||
assign dec_mem_info_bus[`DECINFO_MEM_LBU] = inst_lbu;
|
||||
assign dec_mem_info_bus[`DECINFO_MEM_LHU] = inst_lhu;
|
||||
assign dec_mem_info_bus[`DECINFO_MEM_SB] = inst_sb;
|
||||
assign dec_mem_info_bus[`DECINFO_MEM_SH] = inst_sh;
|
||||
assign dec_mem_info_bus[`DECINFO_MEM_SW] = inst_sw;
|
||||
|
||||
wire[`DECINFO_SYS_BUS_WIDTH-1:0] dec_sys_info_bus;
|
||||
assign dec_sys_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_SYS;
|
||||
assign dec_sys_info_bus[`DECINFO_SYS_ECALL] = inst_ecall;
|
||||
assign dec_sys_info_bus[`DECINFO_SYS_EBREAK] = inst_ebreak;
|
||||
assign dec_sys_info_bus[`DECINFO_SYS_NOP] = inst_nop;
|
||||
assign dec_sys_info_bus[`DECINFO_SYS_MRET] = inst_mret;
|
||||
assign dec_sys_info_bus[`DECINFO_SYS_FENCE] = inst_fence | inst_fence_i;
|
||||
|
||||
// 指令中的立即数
|
||||
wire[31:0] inst_u_type_imm = {inst_i[31:12], 12'b0};
|
||||
wire[31:0] inst_j_type_imm = {{12{inst_i[31]}}, inst_i[19:12], inst_i[20], inst_i[30:21], 1'b0};
|
||||
wire[31:0] inst_b_type_imm = {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0};
|
||||
wire[31:0] inst_s_type_imm = {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]};
|
||||
wire[31:0] inst_i_type_imm = {{20{inst_i[31]}}, inst_i[31:20]};
|
||||
wire[31:0] inst_csr_type_imm = {27'h0, inst_i[19:15]};
|
||||
wire[31:0] inst_shift_type_imm = {27'h0, inst_i[24:20]};
|
||||
|
||||
wire inst_sel_u_imm = inst_lui | inst_auipc;
|
||||
wire inst_sel_j_imm = inst_jal;
|
||||
wire inst_sel_b_imm = inst_type_branch;
|
||||
wire inst_sel_s_imm = inst_type_store;
|
||||
wire inst_sel_i_imm = inst_addi | inst_slti | inst_sltiu | inst_xori | inst_ori | inst_andi | inst_type_load | inst_jalr;
|
||||
wire inst_sel_csr_imm = inst_csrrwi | inst_csrrsi | inst_csrrci;
|
||||
wire inst_sel_shift_imm = inst_slli | inst_srli | inst_srai;
|
||||
|
||||
assign dec_imm_o = ({32{inst_sel_u_imm}} & inst_u_type_imm) |
|
||||
({32{inst_sel_j_imm}} & inst_j_type_imm) |
|
||||
({32{inst_sel_b_imm}} & inst_b_type_imm) |
|
||||
({32{inst_sel_s_imm}} & inst_s_type_imm) |
|
||||
({32{inst_sel_i_imm}} & inst_i_type_imm) |
|
||||
({32{inst_sel_csr_imm}} & inst_csr_type_imm) |
|
||||
({32{inst_sel_shift_imm}} & inst_shift_type_imm);
|
||||
|
||||
wire op_alu = inst_lui | inst_auipc | opcode_0010011 | (opcode_0110011 & (~inst_type_muldiv));
|
||||
wire op_bjp = inst_jal | inst_jalr | inst_type_branch;
|
||||
wire op_muldiv = inst_type_muldiv;
|
||||
wire op_csr = inst_csrrw | inst_csrrwi | inst_csrrs | inst_csrrsi | inst_csrrc | inst_csrrci;
|
||||
wire op_sys = inst_ebreak | inst_ecall | inst_nop | inst_mret | inst_fence | inst_fence_i;
|
||||
wire op_mem = inst_type_load | inst_type_store;
|
||||
|
||||
assign dec_info_bus_o = ({`DECINFO_WIDTH{op_alu}} & {{`DECINFO_WIDTH-`DECINFO_ALU_BUS_WIDTH{1'b0}}, dec_alu_info_bus}) |
|
||||
({`DECINFO_WIDTH{op_bjp}} & {{`DECINFO_WIDTH-`DECINFO_BJP_BUS_WIDTH{1'b0}}, dec_bjp_info_bus}) |
|
||||
({`DECINFO_WIDTH{op_muldiv}} & {{`DECINFO_WIDTH-`DECINFO_MULDIV_BUS_WIDTH{1'b0}}, dec_muldiv_info_bus}) |
|
||||
({`DECINFO_WIDTH{op_csr}} & {{`DECINFO_WIDTH-`DECINFO_CSR_BUS_WIDTH{1'b0}}, dec_csr_info_bus}) |
|
||||
({`DECINFO_WIDTH{op_mem}} & {{`DECINFO_WIDTH-`DECINFO_MEM_BUS_WIDTH{1'b0}}, dec_mem_info_bus}) |
|
||||
({`DECINFO_WIDTH{op_sys}} & {{`DECINFO_WIDTH-`DECINFO_SYS_BUS_WIDTH{1'b0}}, dec_sys_info_bus});
|
||||
|
||||
assign dec_pc_o = inst_addr_i;
|
||||
|
||||
// 是否需要访问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
|
||||
|
|
|
@ -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
|
||||
|
|
251
rtl/core/ifu.sv
251
rtl/core/ifu.sv
|
@ -1,125 +1,126 @@
|
|||
/*
|
||||
Copyright 2020 Blue Liang, liangkangnan@163.com
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "defines.sv"
|
||||
|
||||
// 取指模块
|
||||
module ifu(
|
||||
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
|
||||
input wire flush_i,
|
||||
input wire[31:0] flush_addr_i, // 跳转地址
|
||||
input wire[`STALL_WIDTH-1:0] stall_i, // 流水线暂停标志
|
||||
input wire jtag_halt_i,
|
||||
|
||||
output wire[31:0] inst_o,
|
||||
output wire[31:0] pc_o,
|
||||
output wire inst_valid_o,
|
||||
|
||||
output wire[31:0] ibus_addr_o,
|
||||
input wire[31:0] ibus_data_i,
|
||||
output wire[31:0] ibus_data_o,
|
||||
output wire[3:0] ibus_sel_o,
|
||||
output wire ibus_we_o,
|
||||
output wire req_valid_o,
|
||||
input wire req_ready_i,
|
||||
input wire rsp_valid_i,
|
||||
output wire rsp_ready_o
|
||||
|
||||
);
|
||||
|
||||
assign req_valid_o = (~rst_n)? 1'b0:
|
||||
(flush_i)? 1'b0:
|
||||
stall_i[`STALL_PC]? 1'b0:
|
||||
jtag_halt_i? 1'b0:
|
||||
1'b1;
|
||||
assign rsp_ready_o = (~rst_n)? 1'b0: 1'b1;
|
||||
|
||||
wire ifu_req_hsked = (req_valid_o & req_ready_i);
|
||||
wire ifu_rsp_hsked = (rsp_valid_i & rsp_ready_o);
|
||||
|
||||
// 在执行多周期指令或者请求不到总线时需要暂停
|
||||
wire stall = stall_i[`STALL_PC] | (~ifu_req_hsked);
|
||||
|
||||
reg[31:0] pc;
|
||||
reg[31:0] pc_prev;
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
// 复位
|
||||
if (!rst_n) begin
|
||||
pc <= `CPU_RESET_ADDR;
|
||||
pc_prev <= 32'h0;
|
||||
// 冲刷
|
||||
end else if (flush_i) begin
|
||||
pc <= flush_addr_i;
|
||||
// 暂停,取上一条指令
|
||||
end else if (stall) begin
|
||||
pc <= pc_prev;
|
||||
// 取下一条指令
|
||||
end else begin
|
||||
pc <= pc + 32'h4;
|
||||
pc_prev <= pc;
|
||||
end
|
||||
end
|
||||
|
||||
wire[31:0] pc_r;
|
||||
// 将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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue