1
0
mirror of https://github.com/olofk/serv.git synced 2026-02-17 04:26:49 +00:00
Files
olofk.serv/rtl/serv_rf_if.v
2021-04-18 00:13:47 +02:00

146 lines
3.6 KiB
Verilog

`default_nettype none
module serv_rf_if
#(parameter WITH_CSR = 1)
(//RF Interface
input wire i_cnt_en,
output wire [4+WITH_CSR:0] o_wreg0,
output wire [4+WITH_CSR:0] o_wreg1,
output wire o_wen0,
output wire o_wen1,
output wire o_wdata0,
output wire o_wdata1,
output wire [4+WITH_CSR:0] o_rreg0,
output wire [4+WITH_CSR:0] o_rreg1,
input wire i_rdata0,
input wire i_rdata1,
//Trap interface
input wire i_trap,
input wire i_mret,
input wire i_mepc,
input wire i_mem_op,
input wire i_bufreg_q,
input wire i_bad_pc,
output wire o_csr_pc,
//CSR interface
input wire i_csr_en,
input wire [1:0] i_csr_addr,
input wire i_csr,
output wire o_csr,
//RD write port
input wire i_rd_wen,
input wire [4:0] i_rd_waddr,
input wire i_ctrl_rd,
input wire i_alu_rd,
input wire i_rd_alu_en,
input wire i_csr_rd,
input wire i_rd_csr_en,
input wire i_mem_rd,
//RS1 read port
input wire [4:0] i_rs1_raddr,
output wire o_rs1,
//RS2 read port
input wire [4:0] i_rs2_raddr,
output wire o_rs2);
`include "serv_params.vh"
/*
********** Write side ***********
*/
wire rd_wen = i_rd_wen & (|i_rd_waddr);
generate
if (WITH_CSR) begin
wire rd = (i_ctrl_rd ) |
(i_alu_rd & i_rd_alu_en) |
(i_csr_rd & i_rd_csr_en) |
(i_mem_rd);
wire mtval = i_mem_op ? i_bufreg_q : i_bad_pc;
assign o_wdata0 = i_trap ? mtval : rd;
assign o_wdata1 = i_trap ? i_mepc : i_csr;
//port 0 rd mtval
//port 1 csr mepc
//mepc 100010
//mtval 100011
//csr 1000xx
//rd 0xxxxx
assign o_wreg0 = i_trap ? {4'b1000,CSR_MTVAL} : {1'b0,i_rd_waddr};
assign o_wreg1 = i_trap ? {4'b1000,CSR_MEPC} : {4'b1000,i_csr_addr};
assign o_wen0 = i_cnt_en & (i_trap | rd_wen);
assign o_wen1 = i_cnt_en & (i_trap | i_csr_en);
/*
********** Read side ***********
*/
//0 : RS1
//1 : RS2 / CSR
assign o_rreg0 = {1'b0, i_rs1_raddr};
/*
The address of the second read port (o_rreg1) can get assigned from four
different sources
Normal operations : i_rs2_raddr
CSR access : i_csr_addr
trap : MTVEC
mret : MEPC
Address 0-31 in the RF are assigned to the GPRs. After that follows the four
CSRs on addresses 32-35
32 MSCRATCH
33 MTVEC
34 MEPC
35 MTVAL
The expression below is an optimized version of this logic
*/
wire sel_rs2 = !(i_trap | i_mret | i_csr_en);
assign o_rreg1 = {~sel_rs2,
i_rs2_raddr[4:2] & {3{sel_rs2}},
{1'b0,i_trap} | {i_mret,1'b0} | ({2{i_csr_en}} & i_csr_addr) | ({2{sel_rs2}} & i_rs2_raddr[1:0])};
assign o_rs1 = i_rdata0;
assign o_rs2 = i_rdata1;
assign o_csr = i_rdata1 & i_csr_en;
assign o_csr_pc = i_rdata1;
end else begin
wire rd = (i_ctrl_rd ) |
(i_alu_rd & i_rd_alu_en) |
(i_mem_rd);
assign o_wdata0 = rd;
assign o_wdata1 = 1'b0;
assign o_wreg0 = i_rd_waddr;
assign o_wreg1 = 5'd0;
assign o_wen0 = i_cnt_en & rd_wen;
assign o_wen1 = 1'b0;
/*
********** Read side ***********
*/
assign o_rreg0 = i_rs1_raddr;
assign o_rreg1 = i_rs2_raddr;
assign o_rs1 = i_rdata0;
assign o_rs2 = i_rdata1;
assign o_csr = 1'b0;
assign o_csr_pc = 1'b0;
end // else: !if(WITH_CSR)
endgenerate
endmodule