mirror of
https://github.com/olofk/serv.git
synced 2026-01-15 15:56:04 +00:00
106 lines
2.5 KiB
Verilog
106 lines
2.5 KiB
Verilog
`default_nettype none
|
|
module serv_csr
|
|
(
|
|
input wire i_clk,
|
|
input wire i_en,
|
|
input wire [4:2] i_cnt,
|
|
input wire [3:2] i_cnt_r,
|
|
input wire i_e_op,
|
|
input wire i_ebreak,
|
|
input wire i_mem_cmd,
|
|
input wire i_mem_misalign,
|
|
//From mpram
|
|
input wire i_rf_csr_out,
|
|
//to mpram
|
|
output wire o_csr_in,
|
|
//Stuff
|
|
input wire i_mtip,
|
|
output wire o_new_irq,
|
|
input wire i_pending_irq,
|
|
input wire i_trap_taken,
|
|
input wire i_mstatus_en,
|
|
input wire i_mie_en,
|
|
input wire i_mcause_en,
|
|
input wire [1:0] i_csr_source,
|
|
input wire i_mret,
|
|
input wire i_d,
|
|
output wire o_q);
|
|
|
|
`include "serv_params.vh"
|
|
|
|
reg mstatus;
|
|
reg mstatus_mie;
|
|
reg mstatus_mpie;
|
|
reg mie_mtie;
|
|
|
|
reg mcause31;
|
|
reg [3:0] mcause3_0;
|
|
wire mcause;
|
|
|
|
wire csr_in;
|
|
wire csr_out;
|
|
|
|
reg timer_irq_r;
|
|
|
|
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 & i_en & mstatus) |
|
|
i_rf_csr_out |
|
|
(i_mcause_en & i_en & mcause);
|
|
|
|
assign o_q = csr_out;
|
|
|
|
wire timer_irq = i_mtip & 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;
|
|
|
|
assign o_new_irq = !timer_irq_r & timer_irq;
|
|
|
|
|
|
always @(posedge i_clk) begin
|
|
/*
|
|
Note: To save resources mstatus_mpie (mstatus bit 7) is not
|
|
readable or writable from sw
|
|
*/
|
|
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;
|
|
|
|
timer_irq_r <= timer_irq;
|
|
|
|
if (i_mret) begin
|
|
mstatus_mie <= mstatus_mpie;
|
|
end
|
|
|
|
if (i_trap_taken) begin
|
|
mstatus_mpie <= mstatus_mie;
|
|
mstatus_mie <= 1'b0;
|
|
mcause31 <= i_pending_irq;
|
|
mcause3_0 <= i_pending_irq ? 4'd7 :
|
|
i_e_op ? {!i_ebreak, 3'b011} :
|
|
i_mem_misalign ? {2'b01, i_mem_cmd, 1'b0} :
|
|
4'd0;
|
|
end
|
|
|
|
if (i_mcause_en & i_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
|
|
end
|
|
|
|
endmodule
|