SummerCart64/fw/rtl/serv/serv_ctrl.v

85 lines
2.3 KiB
Coq
Raw Permalink Normal View History

`default_nettype none
module serv_ctrl
#(parameter RESET_STRATEGY = "MINI",
parameter RESET_PC = 32'd0,
parameter WITH_CSR = 1)
(
input wire clk,
input wire i_rst,
//State
input wire i_pc_en,
input wire i_cnt12to31,
input wire i_cnt0,
input wire i_cnt1,
input wire i_cnt2,
//Control
input wire i_jump,
input wire i_jal_or_jalr,
input wire i_utype,
input wire i_pc_rel,
input wire i_trap,
input wire i_iscomp,
//Data
input wire i_imm,
input wire i_buf,
input wire i_csr_pc,
output wire o_rd,
output wire o_bad_pc,
//External
output reg [31:0] o_ibus_adr);
wire pc_plus_4;
wire pc_plus_4_cy;
reg pc_plus_4_cy_r;
wire pc_plus_offset;
wire pc_plus_offset_cy;
reg pc_plus_offset_cy_r;
wire pc_plus_offset_aligned;
wire plus_4;
wire pc = o_ibus_adr[0];
wire new_pc;
wire offset_a;
wire offset_b;
/* If i_iscomp=1: increment pc by 2 else increment pc by 4 */
assign plus_4 = i_iscomp ? i_cnt1 : i_cnt2;
assign o_bad_pc = pc_plus_offset_aligned;
assign {pc_plus_4_cy,pc_plus_4} = pc+plus_4+pc_plus_4_cy_r;
generate
if (|WITH_CSR) begin : gen_csr
assign new_pc = i_trap ? (i_csr_pc & !i_cnt0) : i_jump ? pc_plus_offset_aligned : pc_plus_4;
end else begin : gen_no_csr
assign new_pc = i_jump ? pc_plus_offset_aligned : pc_plus_4;
end
endgenerate
assign o_rd = (i_utype & pc_plus_offset_aligned) | (pc_plus_4 & i_jal_or_jalr);
assign offset_a = i_pc_rel & pc;
assign offset_b = i_utype ? (i_imm & i_cnt12to31): i_buf;
assign {pc_plus_offset_cy,pc_plus_offset} = offset_a+offset_b+pc_plus_offset_cy_r;
assign pc_plus_offset_aligned = pc_plus_offset & !i_cnt0;
initial if (RESET_STRATEGY == "NONE") o_ibus_adr = RESET_PC;
always @(posedge clk) begin
pc_plus_4_cy_r <= i_pc_en & pc_plus_4_cy;
pc_plus_offset_cy_r <= i_pc_en & pc_plus_offset_cy;
if (RESET_STRATEGY == "NONE") begin
if (i_pc_en)
o_ibus_adr <= {new_pc, o_ibus_adr[31:1]};
end else begin
if (i_pc_en | i_rst)
o_ibus_adr <= i_rst ? RESET_PC : {new_pc, o_ibus_adr[31:1]};
end
end
endmodule