mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-25 15:16:53 +01:00
150 lines
3.9 KiB
Verilog
150 lines
3.9 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_mtval_pc,
|
|
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,
|
|
input wire i_rd_mem_en,
|
|
|
|
//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);
|
|
|
|
|
|
/*
|
|
********** Write side ***********
|
|
*/
|
|
|
|
wire rd_wen = i_rd_wen & (|i_rd_waddr);
|
|
|
|
generate
|
|
if (|WITH_CSR) begin : gen_csr
|
|
wire rd = (i_ctrl_rd ) |
|
|
(i_alu_rd & i_rd_alu_en) |
|
|
(i_csr_rd & i_rd_csr_en) |
|
|
(i_mem_rd & i_rd_mem_en);
|
|
|
|
wire mtval = i_mtval_pc ? i_bad_pc : i_bufreg_q;
|
|
|
|
assign o_wdata0 = i_trap ? mtval : rd;
|
|
assign o_wdata1 = i_trap ? i_mepc : i_csr;
|
|
|
|
/* Port 0 handles writes to mtval during traps and rd otherwise
|
|
* Port 1 handles writes to mepc during traps and csr accesses otherwise
|
|
*
|
|
* GPR registers are mapped to address 0-31 (bits 0xxxxx).
|
|
* Following that are four CSR registers
|
|
* mscratch 100000
|
|
* mtvec 100001
|
|
* mepc 100010
|
|
* mtval 100011
|
|
*/
|
|
|
|
assign o_wreg0 = i_trap ? {6'b100011} : {1'b0,i_rd_waddr};
|
|
assign o_wreg1 = i_trap ? {6'b100010} : {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 : gen_no_csr
|
|
wire rd = (i_ctrl_rd ) |
|
|
(i_alu_rd & i_rd_alu_en) |
|
|
(i_mem_rd & i_rd_mem_en);
|
|
|
|
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
|