1
0
mirror of https://github.com/olofk/serv.git synced 2026-01-13 15:17:25 +00:00
olofk.serv/rtl/serv_ctrl.v
2018-11-18 13:05:38 +01:00

113 lines
2.3 KiB
Verilog

`default_nettype none
module serv_ctrl
(
input wire clk,
input wire i_rst,
input wire i_en,
input wire i_pc_en,
input wire i_cnt_done,
input wire i_jump,
input wire i_offset,
input wire i_rs1,
input wire i_jalr,
input wire i_auipc,
input wire i_trap,
input wire i_csr_pc,
output wire o_rd,
output wire o_bad_pc,
output reg o_misalign = 1'b0,
output wire [31:0] o_ibus_adr,
output reg o_ibus_cyc,
input wire i_ibus_ack);
parameter RESET_PC = 32'd8;
wire pc_plus_4;
wire pc_plus_offset;
wire plus_4;
wire pc;
wire new_pc;
wire offset_a;
assign plus_4 = en_pc_2r & !en_pc_3r;
assign o_ibus_adr[0] = pc;
assign o_bad_pc = pc_plus_offset_aligned;
ser_add ser_add_pc_plus_4
(
.clk (clk),
.a (pc),
.b (plus_4),
.clr (i_cnt_done),
.q (pc_plus_4),
.o_v ());
shift_reg
#(
.LEN (32),
.INIT (RESET_PC))
pc_reg
(
.clk (clk),
.i_en (i_pc_en),
.i_d (new_pc),
.o_q (pc),
.o_par (o_ibus_adr[31:1])
);
assign new_pc = i_trap ? (i_csr_pc & en_pc_r) : i_jump ? pc_plus_offset_aligned : pc_plus_4;
assign o_rd = i_auipc ? pc_plus_offset_aligned : pc_plus_4;
assign offset_a = i_jalr ? i_rs1 : pc;
ser_add ser_add_pc_plus_offset
(
.clk (clk),
.a (offset_a),
.b (i_offset),
.clr (i_cnt_done),
.q (pc_plus_offset),
.o_v ());
wire pc_plus_offset_aligned = pc_plus_offset & en_pc_r;
reg en_r;
reg en_2r;
reg en_3r;
reg en_pc_r;
reg en_pc_2r;
reg en_pc_3r;
always @(posedge clk) begin
en_r <= i_en;
en_2r <= en_r;
en_3r <= en_2r;
en_pc_r <= i_pc_en;
en_pc_2r <= en_pc_r;
en_pc_3r <= en_pc_2r;
if (en_r & !en_2r)
o_misalign <= pc_plus_offset;
if (en_pc_r & !i_pc_en)
o_ibus_cyc <= 1'b1;
else if (o_ibus_cyc & i_ibus_ack)
o_ibus_cyc <= 1'b0;
if (i_rst) begin
en_r <= 1'b0;
en_2r <= 1'b0;
en_3r <= 1'b0;
en_pc_r <= 1'b1;
en_pc_2r <= 1'b0;
en_pc_3r <= 1'b0;
o_ibus_cyc <= 1'b0;
end
end
endmodule