mirror of
https://github.com/olofk/serv.git
synced 2026-01-30 13:06:17 +00:00
Since FPGA uses fixed-size RAM, it's better in most cases to store the CSR in unused memory positions in that RAM. Since the decoding is made more complex, the old register file implementation is kept around since that is more efficient when we don't want CSR and potentially when the FPGA support hardware shift registers.
105 lines
2.4 KiB
Verilog
105 lines
2.4 KiB
Verilog
`default_nettype none
|
|
module serv_csr
|
|
(
|
|
input wire i_clk,
|
|
input wire [4:0] i_cnt,
|
|
input wire [3:0] i_cnt_r,
|
|
//From mpram
|
|
input wire i_rf_csr_out,
|
|
//to mpram
|
|
output wire o_csr_in,
|
|
//Stuff
|
|
input wire i_mtip,
|
|
output wire o_timer_irq_en,
|
|
input wire i_mstatus_en,
|
|
input wire i_mie_en,
|
|
input wire i_mip_en,
|
|
input wire i_mepc_en,
|
|
input wire i_mcause_en,
|
|
input wire i_mtval_en,
|
|
input wire [1:0] i_csr_source,
|
|
input wire i_trap,
|
|
input wire i_pc,
|
|
input wire i_mtval,
|
|
input wire [3:0] i_mcause,
|
|
input wire i_d,
|
|
output wire o_q);
|
|
|
|
`include "serv_params.vh"
|
|
/*
|
|
300 mstatus RWSC
|
|
304 mie SCWi
|
|
305 mtvec RW
|
|
344 mip CWi
|
|
|
|
340 mscratch
|
|
341 mepc RW
|
|
342 mcause R
|
|
343 mtval
|
|
*/
|
|
|
|
reg mstatus;
|
|
reg mstatus_mie;
|
|
reg mie_mtie;
|
|
|
|
reg [31:0] mepc;
|
|
reg mcause31;
|
|
reg [3:0] mcause3_0;
|
|
wire mcause;
|
|
reg [31:0] mtval;
|
|
|
|
wire csr_in;
|
|
wire csr_out;
|
|
|
|
assign csr_in = (i_csr_source == CSR_SOURCE_EXT) ? i_d :
|
|
(i_csr_source == CSR_SOURCE_SET) ? csr_out | i_d :
|
|
(i_csr_source == CSR_SOURCE_CLR) ? csr_out & ~i_d :
|
|
(i_csr_source == CSR_SOURCE_CSR) ? csr_out :
|
|
1'bx;
|
|
|
|
assign csr_out = (i_mstatus_en & mstatus) |
|
|
i_rf_csr_out |
|
|
(i_mepc_en & mepc[0]) |
|
|
(i_mcause_en & mcause) |
|
|
(i_mtval_en & mtval[0]);
|
|
|
|
assign o_q = csr_out;
|
|
|
|
assign o_timer_irq_en = mstatus_mie & mie_mtie;
|
|
|
|
assign mcause = (i_cnt[4:2] == 3'd0) ? mcause3_0[0] : //[3:0]
|
|
((i_cnt[4:2] == 3'd7) & i_cnt_r[3]) ? mcause31 //[31]
|
|
: 1'b0;
|
|
|
|
assign o_csr_in = csr_in;
|
|
|
|
always @(posedge i_clk) begin
|
|
if (i_mstatus_en & (i_cnt[4:2] == 3'd0) & i_cnt_r[3])
|
|
mstatus_mie <= csr_in;
|
|
|
|
if (i_mie_en & (i_cnt[4:2] == 3'd1) & i_cnt_r[3])
|
|
mie_mtie <= csr_in;
|
|
|
|
mstatus <= (i_cnt[4:2] == 0) & i_cnt_r[2] & mstatus_mie;
|
|
|
|
if (i_trap) begin
|
|
mcause31 <= i_mtip & o_timer_irq_en;
|
|
mcause3_0 <= (i_mtip & o_timer_irq_en) ? 4'd7 : i_mcause[3:0];
|
|
end
|
|
|
|
if (i_mepc_en | i_trap)
|
|
mepc <= {i_trap ? i_pc : csr_in, mepc[31:1]};
|
|
|
|
if (i_mcause_en) begin
|
|
if (i_cnt[4:2] == 3'd0)
|
|
mcause3_0 <= {csr_in, mcause3_0[3:1]};
|
|
if ((i_cnt[4:2] == 3'd7) & i_cnt_r[3])
|
|
mcause31 <= csr_in;
|
|
end
|
|
|
|
if (i_mtval_en | i_trap)
|
|
mtval <= {i_trap ? i_mtval : csr_in, mtval[31:1]};
|
|
end
|
|
|
|
endmodule
|