mirror of
https://github.com/olofk/serv.git
synced 2026-02-24 15:37:38 +00:00
This was originally thrown out since it was slow and cost too much resources. Due to other changes in the core, it is now cheaper than the other one
448 lines
12 KiB
Verilog
448 lines
12 KiB
Verilog
`default_nettype none
|
|
|
|
module serv_top
|
|
(
|
|
input wire clk,
|
|
input wire i_rst,
|
|
input wire i_timer_irq,
|
|
`ifdef RISCV_FORMAL
|
|
output reg rvfi_valid = 1'b0,
|
|
output reg [63:0] rvfi_order = 64'd0,
|
|
output reg [31:0] rvfi_insn = 32'd0,
|
|
output reg rvfi_trap = 1'b0,
|
|
output reg rvfi_halt = 1'b0,
|
|
output reg rvfi_intr = 1'b0,
|
|
output reg [1:0] rvfi_mode = 2'b11,
|
|
output reg [1:0] rvfi_ixl = 2'b01,
|
|
output reg [4:0] rvfi_rs1_addr,
|
|
output reg [4:0] rvfi_rs2_addr,
|
|
output reg [31:0] rvfi_rs1_rdata,
|
|
output reg [31:0] rvfi_rs2_rdata,
|
|
output reg [4:0] rvfi_rd_addr,
|
|
output reg [31:0] rvfi_rd_wdata,
|
|
output reg [31:0] rvfi_pc_rdata,
|
|
output reg [31:0] rvfi_pc_wdata,
|
|
output reg [31:0] rvfi_mem_addr,
|
|
output reg [3:0] rvfi_mem_rmask,
|
|
output reg [3:0] rvfi_mem_wmask,
|
|
output reg [31:0] rvfi_mem_rdata,
|
|
output reg [31:0] rvfi_mem_wdata,
|
|
`endif
|
|
output wire [31:0] o_ibus_adr,
|
|
output wire o_ibus_cyc,
|
|
input wire [31:0] i_ibus_rdt,
|
|
input wire i_ibus_ack,
|
|
output wire [31:0] o_dbus_adr,
|
|
output wire [31:0] o_dbus_dat,
|
|
output wire [3:0] o_dbus_sel,
|
|
output wire o_dbus_we ,
|
|
output wire o_dbus_cyc,
|
|
input wire [31:0] i_dbus_rdt,
|
|
input wire i_dbus_ack);
|
|
|
|
`include "serv_params.vh"
|
|
|
|
wire [4:0] rd_addr;
|
|
wire [4:0] rs1_addr;
|
|
wire [4:0] rs2_addr;
|
|
|
|
wire take_branch;
|
|
wire e_op;
|
|
wire ebreak;
|
|
wire branch_op;
|
|
wire mem_op;
|
|
wire shift_op;
|
|
wire slt_op;
|
|
|
|
wire rd_alu_en;
|
|
wire rd_csr_en;
|
|
wire ctrl_rd;
|
|
wire alu_rd;
|
|
wire mem_rd;
|
|
wire csr_rd;
|
|
wire rd;
|
|
|
|
wire ctrl_pc_en;
|
|
wire jump;
|
|
wire jalr;
|
|
wire jal_or_jalr;
|
|
wire utype;
|
|
wire mret;
|
|
wire imm;
|
|
wire trap;
|
|
wire pc_rel;
|
|
|
|
wire init;
|
|
wire run;
|
|
wire cnt_en;
|
|
wire [4:0] cnt;
|
|
wire [3:0] cnt_r;
|
|
|
|
wire cnt_done;
|
|
|
|
wire bufreg_hold;
|
|
wire bufreg_rs1_en;
|
|
wire bufreg_imm_en;
|
|
wire bufreg_loop;
|
|
wire bufreg_q;
|
|
|
|
wire alu_sub;
|
|
wire [1:0] alu_bool_op;
|
|
wire alu_cmp_eq;
|
|
wire alu_cmp_uns;
|
|
wire alu_cmp;
|
|
wire alu_shamt_en;
|
|
wire alu_sh_signed;
|
|
wire alu_sh_right;
|
|
wire alu_sh_done;
|
|
wire [1:0] alu_rd_sel;
|
|
|
|
wire rf_rreq;
|
|
wire rf_wreq;
|
|
wire rf_ready;
|
|
wire rs1;
|
|
wire rs2;
|
|
wire rd_en;
|
|
|
|
wire op_b_source;
|
|
wire op_b;
|
|
|
|
wire mem_signed;
|
|
wire mem_word;
|
|
wire mem_half;
|
|
wire [1:0] mem_bytecnt;
|
|
|
|
wire mem_misalign;
|
|
|
|
wire bad_pc;
|
|
|
|
wire csr_mstatus_en;
|
|
wire csr_mie_en;
|
|
wire csr_mcause_en;
|
|
wire [1:0] csr_source;
|
|
wire csr_imm;
|
|
wire csr_d_sel;
|
|
wire csr_en;
|
|
wire [1:0] csr_addr;
|
|
wire csr_pc;
|
|
|
|
parameter RESET_PC = 32'd8;
|
|
|
|
wire new_irq;
|
|
|
|
wire [1:0] lsb;
|
|
wire [31:0] bufreg_out;
|
|
|
|
serv_state state
|
|
(
|
|
.i_clk (clk),
|
|
.i_rst (i_rst),
|
|
.i_new_irq (new_irq),
|
|
.i_dbus_ack (i_dbus_ack),
|
|
.i_ibus_ack (i_ibus_ack),
|
|
.o_rf_rreq (rf_rreq),
|
|
.o_rf_wreq (rf_wreq),
|
|
.i_rf_ready (rf_ready),
|
|
.i_take_branch (take_branch),
|
|
.i_branch_op (branch_op),
|
|
.i_mem_op (mem_op),
|
|
.i_shift_op (shift_op),
|
|
.i_slt_op (slt_op),
|
|
.i_e_op (e_op),
|
|
.i_rs1_addr (rs1_addr),
|
|
.o_init (init),
|
|
.o_run (run),
|
|
.o_cnt_en (cnt_en),
|
|
.o_cnt (cnt),
|
|
.o_cnt_r (cnt_r),
|
|
.o_cnt_done (cnt_done),
|
|
.o_bufreg_hold (bufreg_hold),
|
|
.o_ctrl_pc_en (ctrl_pc_en),
|
|
.o_ctrl_jump (jump),
|
|
.o_ctrl_trap (trap),
|
|
.i_ctrl_misalign(lsb[1]),
|
|
.o_alu_shamt_en (alu_shamt_en),
|
|
.i_alu_sh_done (alu_sh_done),
|
|
.o_dbus_cyc (o_dbus_cyc),
|
|
.o_mem_bytecnt (mem_bytecnt),
|
|
.i_mem_misalign (mem_misalign),
|
|
.o_csr_imm (csr_imm));
|
|
|
|
wire bufreg_clr_lsb;
|
|
|
|
serv_decode decode
|
|
(
|
|
.clk (clk),
|
|
//Input
|
|
.i_cnt_en (cnt_en),
|
|
.i_cnt_done (cnt_done),
|
|
.i_wb_rdt (i_ibus_rdt),
|
|
.i_wb_en (o_ibus_cyc & i_ibus_ack),
|
|
.i_alu_cmp (alu_cmp),
|
|
//To state
|
|
.o_take_branch (take_branch),
|
|
.o_e_op (e_op),
|
|
.o_ebreak (ebreak),
|
|
.o_branch_op (branch_op),
|
|
.o_mem_op (mem_op),
|
|
.o_shift_op (shift_op),
|
|
.o_slt_op (slt_op),
|
|
//To bufreg
|
|
.o_bufreg_loop (bufreg_loop),
|
|
.o_bufreg_rs1_en (bufreg_rs1_en),
|
|
.o_bufreg_imm_en (bufreg_imm_en),
|
|
.o_bufreg_clr_lsb (bufreg_clr_lsb),
|
|
//To ctrl
|
|
.o_ctrl_jalr (jalr),
|
|
.o_ctrl_jal_or_jalr (jal_or_jalr),
|
|
.o_ctrl_utype (utype),
|
|
.o_ctrl_pc_rel (pc_rel),
|
|
.o_ctrl_mret (mret),
|
|
//To alu
|
|
.o_alu_sub (alu_sub),
|
|
.o_alu_bool_op (alu_bool_op),
|
|
.o_alu_cmp_eq (alu_cmp_eq),
|
|
.o_alu_cmp_uns (alu_cmp_uns),
|
|
.o_alu_sh_signed (alu_sh_signed),
|
|
.o_alu_sh_right (alu_sh_right),
|
|
.o_alu_rd_sel (alu_rd_sel),
|
|
//To RF
|
|
.o_rf_rd_en (rd_en),
|
|
.o_rf_rd_addr (rd_addr),
|
|
.o_rf_rs1_addr (rs1_addr),
|
|
.o_rf_rs2_addr (rs2_addr),
|
|
//To mem IF
|
|
.o_mem_cmd (o_dbus_we),
|
|
.o_mem_signed (mem_signed),
|
|
.o_mem_word (mem_word),
|
|
.o_mem_half (mem_half),
|
|
//To CSR
|
|
.o_csr_en (csr_en),
|
|
.o_csr_addr (csr_addr),
|
|
.o_csr_mstatus_en (csr_mstatus_en),
|
|
.o_csr_mie_en (csr_mie_en),
|
|
.o_csr_mcause_en (csr_mcause_en),
|
|
.o_csr_source (csr_source),
|
|
.o_csr_d_sel (csr_d_sel),
|
|
//To top
|
|
.o_imm (imm),
|
|
.o_op_b_source (op_b_source),
|
|
.o_rd_csr_en (rd_csr_en),
|
|
.o_rd_alu_en (rd_alu_en));
|
|
|
|
assign o_dbus_adr = {bufreg_out[31:2], 2'b00};
|
|
|
|
serv_bufreg bufreg
|
|
(
|
|
.i_clk (clk),
|
|
.i_rst (i_rst),
|
|
.i_cnt (cnt[4:2]),
|
|
.i_cnt_r (cnt_r[1:0]),
|
|
.i_en (!bufreg_hold),
|
|
.i_init (init),
|
|
.i_loop (bufreg_loop),
|
|
.i_rs1 (rs1),
|
|
.i_rs1_en (bufreg_rs1_en),
|
|
.i_imm (imm),
|
|
.i_imm_en (bufreg_imm_en),
|
|
.i_clr_lsb (bufreg_clr_lsb),
|
|
.o_lsb (lsb),
|
|
.o_reg (bufreg_out),
|
|
.o_q (bufreg_q));
|
|
|
|
serv_ctrl
|
|
#(.RESET_PC (RESET_PC))
|
|
ctrl
|
|
(
|
|
.clk (clk),
|
|
.i_rst (i_rst),
|
|
//State
|
|
.i_pc_en (ctrl_pc_en),
|
|
.i_cnt (cnt[4:2]),
|
|
.i_cnt_r (cnt_r[2:1]),
|
|
.i_cnt_done (cnt_done),
|
|
//Control
|
|
.i_jump (jump),
|
|
.i_jal_or_jalr (jal_or_jalr),
|
|
.i_utype (utype),
|
|
.i_pc_rel (pc_rel),
|
|
.i_trap (trap | mret),
|
|
//Data
|
|
.i_imm (imm),
|
|
.i_buf (bufreg_q),
|
|
.i_csr_pc (csr_pc),
|
|
.o_rd (ctrl_rd),
|
|
.o_bad_pc (bad_pc),
|
|
//External
|
|
.o_ibus_adr (o_ibus_adr),
|
|
.o_ibus_cyc (o_ibus_cyc),
|
|
.i_ibus_ack (i_ibus_ack));
|
|
|
|
assign rd = (ctrl_rd ) |
|
|
(rd_alu_en & alu_rd ) |
|
|
(csr_rd & rd_csr_en) |
|
|
(mem_rd);
|
|
|
|
assign op_b = (op_b_source == OP_B_SOURCE_IMM) ? imm : rs2;
|
|
|
|
serv_alu alu
|
|
(
|
|
.clk (clk),
|
|
.i_rst (i_rst),
|
|
.i_en (cnt_en),
|
|
.i_rs1 (rs1),
|
|
.i_op_b (op_b),
|
|
.i_buf (bufreg_q),
|
|
.i_init (init),
|
|
.i_cnt_done (cnt_done),
|
|
.i_sub (alu_sub),
|
|
.i_bool_op (alu_bool_op),
|
|
.i_cmp_eq (alu_cmp_eq),
|
|
.i_cmp_uns (alu_cmp_uns),
|
|
.o_cmp (alu_cmp),
|
|
.i_shamt_en (alu_shamt_en),
|
|
.i_sh_right (alu_sh_right),
|
|
.i_sh_signed (alu_sh_signed),
|
|
.o_sh_done (alu_sh_done),
|
|
.i_rd_sel (alu_rd_sel),
|
|
.o_rd (alu_rd));
|
|
|
|
wire csr_in;
|
|
wire rf_csr_out;
|
|
|
|
serv_mpram regfile
|
|
(
|
|
.i_clk (clk),
|
|
.i_rst (i_rst),
|
|
.i_run (run),
|
|
//Trap interface
|
|
.i_trap (trap),
|
|
.i_mret (mret),
|
|
.i_mepc (o_ibus_adr[0]),
|
|
.i_mtval (mem_misalign ? bufreg_q : bad_pc),
|
|
.o_csr_pc (csr_pc),
|
|
//CSR write port
|
|
.i_csr_en (csr_en),
|
|
.i_csr_addr (csr_addr),
|
|
.i_csr (csr_in),
|
|
//RD write port
|
|
.i_rd_wen (rd_en & (|rd_addr)),
|
|
.i_rd_waddr (rd_addr),
|
|
.i_rd (rd),
|
|
|
|
.i_rreq (rf_rreq),
|
|
.i_wreq (rf_wreq),
|
|
.o_rgnt (rf_ready),
|
|
//RS1 read port
|
|
.i_rs1_raddr (rs1_addr),
|
|
.o_rs1 (rs1),
|
|
//RS2 read port
|
|
.i_rs2_raddr (rs2_addr),
|
|
.o_rs2 (rs2),
|
|
//CSR read port
|
|
.o_csr (rf_csr_out));
|
|
|
|
serv_mem_if mem_if
|
|
(
|
|
.i_clk (clk),
|
|
.i_rst (i_rst),
|
|
.i_en (cnt_en),
|
|
.i_init (init),
|
|
.i_mem_op (mem_op),
|
|
.i_signed (mem_signed),
|
|
.i_word (mem_word),
|
|
.i_half (mem_half),
|
|
.i_bytecnt (mem_bytecnt),
|
|
.i_rs2 (rs2),
|
|
.o_rd (mem_rd),
|
|
.i_lsb (lsb),
|
|
.o_misalign (mem_misalign),
|
|
//External interface
|
|
.o_wb_dat (o_dbus_dat),
|
|
.o_wb_sel (o_dbus_sel),
|
|
.i_wb_rdt (i_dbus_rdt),
|
|
.i_wb_ack (i_dbus_ack));
|
|
|
|
serv_csr csr
|
|
(
|
|
.i_clk (clk),
|
|
.i_run (run),
|
|
.i_cnt (cnt[4:2]),
|
|
.i_cnt_r (cnt_r[3:2]),
|
|
.i_e_op (e_op),
|
|
.i_ebreak (ebreak),
|
|
.i_mem_cmd (o_dbus_we),
|
|
.i_mem_misalign (mem_misalign),
|
|
.i_rf_csr_out (rf_csr_out),
|
|
.o_csr_in (csr_in),
|
|
.i_mtip (i_timer_irq),
|
|
.o_new_irq (new_irq),
|
|
.i_mstatus_en (csr_mstatus_en),
|
|
.i_mie_en (csr_mie_en ),
|
|
.i_mcause_en (csr_mcause_en ),
|
|
.i_csr_source (csr_source),
|
|
.i_trap (trap),
|
|
.i_d (csr_d_sel ? csr_imm : rs1),
|
|
.o_q (csr_rd));
|
|
|
|
`ifdef RISCV_FORMAL
|
|
reg [31:0] pc = RESET_PC;
|
|
|
|
wire rs_en = (branch_op|mem_op|shift_op|slt_op) ? init : ctrl_pc_en;
|
|
|
|
always @(posedge clk) begin
|
|
rvfi_valid <= cnt_done & ctrl_pc_en & !i_rst;
|
|
rvfi_order <= rvfi_order + {63'd0,rvfi_valid};
|
|
if (o_ibus_cyc & i_ibus_ack)
|
|
rvfi_insn <= i_ibus_rdt;
|
|
if (rd_en)
|
|
rvfi_rd_wdata <= {rd,rvfi_rd_wdata[31:1]};
|
|
if (cnt_done & ctrl_pc_en) begin
|
|
rvfi_pc_rdata <= pc;
|
|
if (!rd_en)
|
|
rvfi_rd_addr <= 5'd0;
|
|
if (!rd_en | !(|rd_addr))
|
|
rvfi_rd_wdata <= 32'd0;
|
|
end
|
|
rvfi_trap <= trap;
|
|
if (rvfi_valid) begin
|
|
rvfi_trap <= 1'b0;
|
|
pc <= rvfi_pc_wdata;
|
|
end
|
|
|
|
rvfi_halt <= 1'b0;
|
|
rvfi_intr <= 1'b0;
|
|
rvfi_mode <= 2'd3;
|
|
rvfi_ixl = 2'd1;
|
|
if (rf_ready) begin
|
|
rvfi_rs1_addr <= rs1_addr;
|
|
rvfi_rs2_addr <= rs2_addr;
|
|
rvfi_rd_addr <= rd_addr;
|
|
end
|
|
if (rs_en) begin
|
|
rvfi_rs1_rdata <= {rs1,rvfi_rs1_rdata[31:1]};
|
|
rvfi_rs2_rdata <= {rs2,rvfi_rs2_rdata[31:1]};
|
|
end
|
|
|
|
if (i_dbus_ack) begin
|
|
rvfi_mem_addr <= o_dbus_adr;
|
|
rvfi_mem_rmask <= o_dbus_we ? 4'b0000 : o_dbus_sel;
|
|
rvfi_mem_wmask <= o_dbus_we ? o_dbus_sel : 4'b0000;
|
|
rvfi_mem_rdata <= i_dbus_rdt;
|
|
rvfi_mem_wdata <= o_dbus_dat;
|
|
end
|
|
if (i_ibus_ack) begin
|
|
rvfi_mem_rmask <= 4'b0000;
|
|
rvfi_mem_wmask <= 4'b0000;
|
|
end
|
|
end
|
|
/* verilator lint_off COMBDLY */
|
|
always @(o_ibus_adr)
|
|
rvfi_pc_wdata <= o_ibus_adr;
|
|
/* verilator lint_on COMBDLY */
|
|
|
|
|
|
`endif
|
|
|
|
endmodule
|