tinyriscv/rtl/core/exu_alu_datapath.sv

255 lines
7.5 KiB
Systemverilog

/*
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