Added qerv files
This commit is contained in:
@@ -72,6 +72,9 @@ module mcu #(
|
|||||||
assign GPI[32*3-1:32*2] = i_GPI_C;
|
assign GPI[32*3-1:32*2] = i_GPI_C;
|
||||||
assign GPI[32*4-1:32*3] = i_GPI_D;
|
assign GPI[32*4-1:32*3] = i_GPI_D;
|
||||||
|
|
||||||
|
assign wb_ext_ack = wb_ext_gpio_ack;
|
||||||
|
assign wb_ext_rdt = wb_ext_gpio_rdt;
|
||||||
|
|
||||||
// SERV core with mux splitting dbus into mem and ext and
|
// SERV core with mux splitting dbus into mem and ext and
|
||||||
// arbiter combining mem and ibus
|
// arbiter combining mem and ibus
|
||||||
// separate rst line to let other hardware keep core under reset
|
// separate rst line to let other hardware keep core under reset
|
||||||
|
|||||||
7
rtl/qerv/LICENSE
Normal file
7
rtl/qerv/LICENSE
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
ISC License
|
||||||
|
|
||||||
|
Copyright 2019, Olof Kindgren
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
152
rtl/qerv/qerv_immdec.v
Normal file
152
rtl/qerv/qerv_immdec.v
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
// SPDX-License-Identifier: ISC
|
||||||
|
`default_nettype none
|
||||||
|
module qerv_immdec
|
||||||
|
(
|
||||||
|
input wire i_clk,
|
||||||
|
//State
|
||||||
|
input wire i_cnt_en,
|
||||||
|
input wire i_cnt_done,
|
||||||
|
//Control
|
||||||
|
input wire [3:0] i_immdec_en,
|
||||||
|
input wire i_csr_imm_en,
|
||||||
|
input wire [3:0] i_ctrl,
|
||||||
|
output wire [4:0] o_rd_addr,
|
||||||
|
output wire [4:0] o_rs1_addr,
|
||||||
|
output wire [4:0] o_rs2_addr,
|
||||||
|
//Data
|
||||||
|
output wire [3:0] o_csr_imm,
|
||||||
|
output wire [3:0] o_imm,
|
||||||
|
//External
|
||||||
|
input wire i_wb_en,
|
||||||
|
input wire [31:7] i_wb_rdt);
|
||||||
|
|
||||||
|
reg [4:0] rd_addr;
|
||||||
|
reg [4:0] rs1_addr;
|
||||||
|
reg [4:0] rs2_addr;
|
||||||
|
|
||||||
|
reg i31;
|
||||||
|
reg i30;
|
||||||
|
reg i29;
|
||||||
|
reg i28;
|
||||||
|
reg i27;
|
||||||
|
reg i26;
|
||||||
|
reg i25;
|
||||||
|
reg i24;
|
||||||
|
reg i23;
|
||||||
|
reg i22;
|
||||||
|
reg i21;
|
||||||
|
reg i20;
|
||||||
|
reg i19;
|
||||||
|
reg i18;
|
||||||
|
reg i17;
|
||||||
|
reg i16;
|
||||||
|
reg i15;
|
||||||
|
reg i14;
|
||||||
|
reg i13;
|
||||||
|
reg i12;
|
||||||
|
reg i11;
|
||||||
|
reg i10;
|
||||||
|
reg i9;
|
||||||
|
reg i8;
|
||||||
|
reg i7;
|
||||||
|
|
||||||
|
reg i7_2;
|
||||||
|
reg i20_2;
|
||||||
|
|
||||||
|
wire signbit = i31 & !i_csr_imm_en;
|
||||||
|
|
||||||
|
assign o_csr_imm[3] = i18;
|
||||||
|
assign o_csr_imm[2] = i17;
|
||||||
|
assign o_csr_imm[1] = i16;
|
||||||
|
assign o_csr_imm[0] = i15;
|
||||||
|
|
||||||
|
assign o_rd_addr = rd_addr;
|
||||||
|
assign o_rs1_addr = rs1_addr;
|
||||||
|
assign o_rs2_addr = rs2_addr;
|
||||||
|
always @(posedge i_clk) begin
|
||||||
|
if (i_wb_en) begin
|
||||||
|
//Common
|
||||||
|
i31 <= i_wb_rdt[31];
|
||||||
|
|
||||||
|
//Bit lane 3
|
||||||
|
i19 <= i_wb_rdt[19];
|
||||||
|
i15 <= i_wb_rdt[15];
|
||||||
|
i20 <= i_wb_rdt[20];
|
||||||
|
i7 <= i_wb_rdt[7];
|
||||||
|
i27 <= i_wb_rdt[27];
|
||||||
|
i23 <= i_wb_rdt[23];
|
||||||
|
i10 <= i_wb_rdt[10];
|
||||||
|
|
||||||
|
//Bit lane 2
|
||||||
|
i22 <= i_wb_rdt[22];
|
||||||
|
i9 <= i_wb_rdt[ 9];
|
||||||
|
i26 <= i_wb_rdt[26];
|
||||||
|
i30 <= i_wb_rdt[30];
|
||||||
|
i14 <= i_wb_rdt[14];
|
||||||
|
i18 <= i_wb_rdt[18];
|
||||||
|
|
||||||
|
//Bit lane 1
|
||||||
|
i21 <= i_wb_rdt[21];
|
||||||
|
i8 <= i_wb_rdt[ 8];
|
||||||
|
i25 <= i_wb_rdt[25];
|
||||||
|
i29 <= i_wb_rdt[29];
|
||||||
|
i13 <= i_wb_rdt[13];
|
||||||
|
i17 <= i_wb_rdt[17];
|
||||||
|
|
||||||
|
//Bit lane 0
|
||||||
|
i11 <= i_wb_rdt[11];
|
||||||
|
i7_2 <= i_wb_rdt[7 ];
|
||||||
|
i20_2 <= i_wb_rdt[20];
|
||||||
|
i24 <= i_wb_rdt[24];
|
||||||
|
i28 <= i_wb_rdt[28];
|
||||||
|
i12 <= i_wb_rdt[12];
|
||||||
|
i16 <= i_wb_rdt[16];
|
||||||
|
|
||||||
|
rd_addr <= i_wb_rdt[11:7];
|
||||||
|
rs1_addr <= i_wb_rdt[19:15];
|
||||||
|
rs2_addr <= i_wb_rdt[24:20];
|
||||||
|
end
|
||||||
|
if (i_cnt_en) begin
|
||||||
|
//Bit lane 3
|
||||||
|
i10 <= i27;
|
||||||
|
i23 <= i27;
|
||||||
|
i27 <= i_ctrl[2] ? i7 : i_ctrl[1] ? signbit : i20;
|
||||||
|
i7 <= signbit;
|
||||||
|
i20 <= i15;
|
||||||
|
i15 <= i19;
|
||||||
|
i19 <= i_ctrl[3] ? signbit : i23;
|
||||||
|
|
||||||
|
//Bit lane 2
|
||||||
|
i22 <= i26;
|
||||||
|
i9 <= i26;
|
||||||
|
i26 <= i30;
|
||||||
|
i30 <= (i_ctrl[1] | i_ctrl[2]) ? signbit : i14;
|
||||||
|
i14 <= i18;
|
||||||
|
i18 <= i_ctrl[3] ? signbit : i22;
|
||||||
|
|
||||||
|
//Bit lane 1
|
||||||
|
i21 <= i25;
|
||||||
|
i8 <= i25;
|
||||||
|
i25 <= i29;
|
||||||
|
i29 <= (i_ctrl[1] | i_ctrl[2]) ? signbit : i13;
|
||||||
|
i13 <= i17;
|
||||||
|
i17 <= i_ctrl[3] ? signbit : i21;
|
||||||
|
|
||||||
|
//Bit lane 0
|
||||||
|
i7_2 <= i11;
|
||||||
|
i11 <= i28;
|
||||||
|
i20_2 <= i24;
|
||||||
|
i24 <= i28;
|
||||||
|
i28 <= (i_ctrl[1] | i_ctrl[2]) ? signbit : i12;
|
||||||
|
i12 <= i16;
|
||||||
|
i16 <= i_ctrl[3] ? signbit : i20_2;
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign o_imm[3] = (i_cnt_done ? signbit : (i_ctrl[0] ? i10 : i23));
|
||||||
|
assign o_imm[2] = i_ctrl[0] ? i9 : i22;
|
||||||
|
assign o_imm[1] = i_ctrl[0] ? i8 : i21;
|
||||||
|
assign o_imm[0] = i_ctrl[0] ? i7_2 : i20_2;
|
||||||
|
|
||||||
|
endmodule
|
||||||
222
rtl/qerv/serv_rf_top.v
Normal file
222
rtl/qerv/serv_rf_top.v
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
`default_nettype none
|
||||||
|
`include "../util/clog2.vh"
|
||||||
|
|
||||||
|
module qerv_rf_top
|
||||||
|
#(parameter RESET_PC = 32'd0,
|
||||||
|
/* COMPRESSED=1: Enable the compressed decoder and allowed misaligned jump of pc
|
||||||
|
COMPRESSED=0: Disable the compressed decoder and does not allow the misaligned jump of pc
|
||||||
|
*/
|
||||||
|
parameter [0:0] COMPRESSED = 0,
|
||||||
|
/*
|
||||||
|
ALIGN = 1: Fetch the aligned instruction by making two bus transactions if the misaligned address
|
||||||
|
is given to the instruction bus.
|
||||||
|
*/
|
||||||
|
parameter [0:0] ALIGN = COMPRESSED,
|
||||||
|
/* Multiplication and Division Unit
|
||||||
|
This parameter enables the interface for connecting SERV and MDU
|
||||||
|
*/
|
||||||
|
parameter [0:0] MDU = 0,
|
||||||
|
/* Register signals before or after the decoder
|
||||||
|
0 : Register after the decoder. Faster but uses more resources
|
||||||
|
1 : (default) Register before the decoder. Slower but uses less resources
|
||||||
|
*/
|
||||||
|
parameter PRE_REGISTER = 1,
|
||||||
|
/* Amount of reset applied to design
|
||||||
|
"NONE" : No reset at all. Relies on a POR to set correct initialization
|
||||||
|
values and that core isn't reset during runtime
|
||||||
|
"MINI" : Standard setting. Resets the minimal amount of FFs needed to
|
||||||
|
restart execution from the instruction at RESET_PC
|
||||||
|
*/
|
||||||
|
parameter RESET_STRATEGY = "MINI",
|
||||||
|
parameter [0:0] DEBUG = 1'b0,
|
||||||
|
parameter WITH_CSR = 1,
|
||||||
|
parameter W = 1,
|
||||||
|
parameter RF_WIDTH = W * 2,
|
||||||
|
parameter RF_L2D = `CLOG2((32+(WITH_CSR*4))*32/RF_WIDTH))
|
||||||
|
(
|
||||||
|
input wire clk,
|
||||||
|
input wire i_rst,
|
||||||
|
input wire i_timer_irq,
|
||||||
|
`ifdef RISCV_FORMAL
|
||||||
|
output wire rvfi_valid,
|
||||||
|
output wire [63:0] rvfi_order,
|
||||||
|
output wire [31:0] rvfi_insn,
|
||||||
|
output wire rvfi_trap,
|
||||||
|
output wire rvfi_halt,
|
||||||
|
output wire rvfi_intr,
|
||||||
|
output wire [1:0] rvfi_mode,
|
||||||
|
output wire [1:0] rvfi_ixl,
|
||||||
|
output wire [4:0] rvfi_rs1_addr,
|
||||||
|
output wire [4:0] rvfi_rs2_addr,
|
||||||
|
output wire [31:0] rvfi_rs1_rdata,
|
||||||
|
output wire [31:0] rvfi_rs2_rdata,
|
||||||
|
output wire [4:0] rvfi_rd_addr,
|
||||||
|
output wire [31:0] rvfi_rd_wdata,
|
||||||
|
output wire [31:0] rvfi_pc_rdata,
|
||||||
|
output wire [31:0] rvfi_pc_wdata,
|
||||||
|
output wire [31:0] rvfi_mem_addr,
|
||||||
|
output wire [3:0] rvfi_mem_rmask,
|
||||||
|
output wire [3:0] rvfi_mem_wmask,
|
||||||
|
output wire [31:0] rvfi_mem_rdata,
|
||||||
|
output wire [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,
|
||||||
|
|
||||||
|
// Extension
|
||||||
|
output wire [31:0] o_ext_rs1,
|
||||||
|
output wire [31:0] o_ext_rs2,
|
||||||
|
output wire [ 2:0] o_ext_funct3,
|
||||||
|
input wire [31:0] i_ext_rd,
|
||||||
|
input wire i_ext_ready,
|
||||||
|
// MDU
|
||||||
|
output wire o_mdu_valid);
|
||||||
|
|
||||||
|
localparam CSR_REGS = WITH_CSR*4;
|
||||||
|
|
||||||
|
wire rf_wreq;
|
||||||
|
wire rf_rreq;
|
||||||
|
wire [4+WITH_CSR:0] wreg0;
|
||||||
|
wire [4+WITH_CSR:0] wreg1;
|
||||||
|
wire wen0;
|
||||||
|
wire wen1;
|
||||||
|
wire [W-1:0] wdata0;
|
||||||
|
wire [W-1:0] wdata1;
|
||||||
|
wire [4+WITH_CSR:0] rreg0;
|
||||||
|
wire [4+WITH_CSR:0] rreg1;
|
||||||
|
wire rf_ready;
|
||||||
|
wire [W-1:0] rdata0;
|
||||||
|
wire [W-1:0] rdata1;
|
||||||
|
|
||||||
|
wire [RF_L2D-1:0] waddr;
|
||||||
|
wire [RF_WIDTH-1:0] wdata;
|
||||||
|
wire wen;
|
||||||
|
wire [RF_L2D-1:0] raddr;
|
||||||
|
wire ren;
|
||||||
|
wire [RF_WIDTH-1:0] rdata;
|
||||||
|
|
||||||
|
serv_rf_ram_if
|
||||||
|
#(.width (RF_WIDTH),
|
||||||
|
.reset_strategy (RESET_STRATEGY),
|
||||||
|
.csr_regs (CSR_REGS),
|
||||||
|
.W(W))
|
||||||
|
rf_ram_if
|
||||||
|
(.i_clk (clk),
|
||||||
|
.i_rst (i_rst),
|
||||||
|
.i_wreq (rf_wreq),
|
||||||
|
.i_rreq (rf_rreq),
|
||||||
|
.o_ready (rf_ready),
|
||||||
|
.i_wreg0 (wreg0),
|
||||||
|
.i_wreg1 (wreg1),
|
||||||
|
.i_wen0 (wen0),
|
||||||
|
.i_wen1 (wen1),
|
||||||
|
.i_wdata0 (wdata0),
|
||||||
|
.i_wdata1 (wdata1),
|
||||||
|
.i_rreg0 (rreg0),
|
||||||
|
.i_rreg1 (rreg1),
|
||||||
|
.o_rdata0 (rdata0),
|
||||||
|
.o_rdata1 (rdata1),
|
||||||
|
.o_waddr (waddr),
|
||||||
|
.o_wdata (wdata),
|
||||||
|
.o_wen (wen),
|
||||||
|
.o_raddr (raddr),
|
||||||
|
.o_ren (ren),
|
||||||
|
.i_rdata (rdata));
|
||||||
|
|
||||||
|
serv_rf_ram
|
||||||
|
#(.width (RF_WIDTH),
|
||||||
|
.csr_regs (CSR_REGS))
|
||||||
|
rf_ram
|
||||||
|
(.i_clk (clk),
|
||||||
|
.i_waddr (waddr),
|
||||||
|
.i_wdata (wdata),
|
||||||
|
.i_wen (wen),
|
||||||
|
.i_raddr (raddr),
|
||||||
|
.i_ren (ren),
|
||||||
|
.o_rdata (rdata));
|
||||||
|
|
||||||
|
qerv_top
|
||||||
|
#(.RESET_PC (RESET_PC),
|
||||||
|
.PRE_REGISTER (PRE_REGISTER),
|
||||||
|
.RESET_STRATEGY (RESET_STRATEGY),
|
||||||
|
.WITH_CSR (WITH_CSR),
|
||||||
|
.DEBUG (DEBUG),
|
||||||
|
.MDU(MDU),
|
||||||
|
.COMPRESSED(COMPRESSED),
|
||||||
|
.ALIGN(ALIGN),
|
||||||
|
.W(W))
|
||||||
|
cpu
|
||||||
|
(
|
||||||
|
.clk (clk),
|
||||||
|
.i_rst (i_rst),
|
||||||
|
.i_timer_irq (i_timer_irq),
|
||||||
|
`ifdef RISCV_FORMAL
|
||||||
|
.rvfi_valid (rvfi_valid ),
|
||||||
|
.rvfi_order (rvfi_order ),
|
||||||
|
.rvfi_insn (rvfi_insn ),
|
||||||
|
.rvfi_trap (rvfi_trap ),
|
||||||
|
.rvfi_halt (rvfi_halt ),
|
||||||
|
.rvfi_intr (rvfi_intr ),
|
||||||
|
.rvfi_mode (rvfi_mode ),
|
||||||
|
.rvfi_ixl (rvfi_ixl ),
|
||||||
|
.rvfi_rs1_addr (rvfi_rs1_addr ),
|
||||||
|
.rvfi_rs2_addr (rvfi_rs2_addr ),
|
||||||
|
.rvfi_rs1_rdata (rvfi_rs1_rdata),
|
||||||
|
.rvfi_rs2_rdata (rvfi_rs2_rdata),
|
||||||
|
.rvfi_rd_addr (rvfi_rd_addr ),
|
||||||
|
.rvfi_rd_wdata (rvfi_rd_wdata ),
|
||||||
|
.rvfi_pc_rdata (rvfi_pc_rdata ),
|
||||||
|
.rvfi_pc_wdata (rvfi_pc_wdata ),
|
||||||
|
.rvfi_mem_addr (rvfi_mem_addr ),
|
||||||
|
.rvfi_mem_rmask (rvfi_mem_rmask),
|
||||||
|
.rvfi_mem_wmask (rvfi_mem_wmask),
|
||||||
|
.rvfi_mem_rdata (rvfi_mem_rdata),
|
||||||
|
.rvfi_mem_wdata (rvfi_mem_wdata),
|
||||||
|
`endif
|
||||||
|
.o_rf_rreq (rf_rreq),
|
||||||
|
.o_rf_wreq (rf_wreq),
|
||||||
|
.i_rf_ready (rf_ready),
|
||||||
|
.o_wreg0 (wreg0),
|
||||||
|
.o_wreg1 (wreg1),
|
||||||
|
.o_wen0 (wen0),
|
||||||
|
.o_wen1 (wen1),
|
||||||
|
.o_wdata0 (wdata0),
|
||||||
|
.o_wdata1 (wdata1),
|
||||||
|
.o_rreg0 (rreg0),
|
||||||
|
.o_rreg1 (rreg1),
|
||||||
|
.i_rdata0 (rdata0),
|
||||||
|
.i_rdata1 (rdata1),
|
||||||
|
|
||||||
|
.o_ibus_adr (o_ibus_adr),
|
||||||
|
.o_ibus_cyc (o_ibus_cyc),
|
||||||
|
.i_ibus_rdt (i_ibus_rdt),
|
||||||
|
.i_ibus_ack (i_ibus_ack),
|
||||||
|
|
||||||
|
.o_dbus_adr (o_dbus_adr),
|
||||||
|
.o_dbus_dat (o_dbus_dat),
|
||||||
|
.o_dbus_sel (o_dbus_sel),
|
||||||
|
.o_dbus_we (o_dbus_we),
|
||||||
|
.o_dbus_cyc (o_dbus_cyc),
|
||||||
|
.i_dbus_rdt (i_dbus_rdt),
|
||||||
|
.i_dbus_ack (i_dbus_ack),
|
||||||
|
|
||||||
|
//Extension
|
||||||
|
.o_ext_funct3 (o_ext_funct3),
|
||||||
|
.i_ext_ready (i_ext_ready),
|
||||||
|
.i_ext_rd (i_ext_rd),
|
||||||
|
.o_ext_rs1 (o_ext_rs1),
|
||||||
|
.o_ext_rs2 (o_ext_rs2),
|
||||||
|
//MDU
|
||||||
|
.o_mdu_valid (o_mdu_valid));
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
`default_nettype wire
|
||||||
136
rtl/qerv/serv_synth_wrapper.v
Normal file
136
rtl/qerv/serv_synth_wrapper.v
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
`default_nettype none
|
||||||
|
`include "../util/clog2.vh"
|
||||||
|
|
||||||
|
module serv_synth_wrapper
|
||||||
|
#(
|
||||||
|
/* Register signals before or after the decoder
|
||||||
|
0 : Register after the decoder. Faster but uses more resources
|
||||||
|
1 : (default) Register before the decoder. Slower but uses less resources
|
||||||
|
*/
|
||||||
|
parameter PRE_REGISTER = 1,
|
||||||
|
/* Amount of reset applied to design
|
||||||
|
"NONE" : No reset at all. Relies on a POR to set correct initialization
|
||||||
|
values and that core isn't reset during runtime
|
||||||
|
"MINI" : Standard setting. Resets the minimal amount of FFs needed to
|
||||||
|
restart execution from the instruction at RESET_PC
|
||||||
|
*/
|
||||||
|
parameter RESET_STRATEGY = "MINI",
|
||||||
|
parameter WITH_CSR = 1,
|
||||||
|
parameter RF_WIDTH = 8,
|
||||||
|
parameter RF_L2D = `CLOG2((32+(WITH_CSR*4))*32/RF_WIDTH))
|
||||||
|
(
|
||||||
|
input wire clk,
|
||||||
|
input wire i_rst,
|
||||||
|
input wire i_timer_irq,
|
||||||
|
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,
|
||||||
|
|
||||||
|
output wire [RF_L2D-1:0] o_waddr,
|
||||||
|
output wire [RF_WIDTH-1:0] o_wdata,
|
||||||
|
output wire o_wen,
|
||||||
|
output wire [RF_L2D-1:0] o_raddr,
|
||||||
|
input wire [RF_WIDTH-1:0] i_rdata);
|
||||||
|
|
||||||
|
localparam CSR_REGS = WITH_CSR*4;
|
||||||
|
localparam W = 4;
|
||||||
|
|
||||||
|
wire rf_wreq;
|
||||||
|
wire rf_rreq;
|
||||||
|
wire [4+WITH_CSR:0] wreg0;
|
||||||
|
wire [4+WITH_CSR:0] wreg1;
|
||||||
|
wire wen0;
|
||||||
|
wire wen1;
|
||||||
|
wire [W-1:0] wdata0;
|
||||||
|
wire [W-1:0] wdata1;
|
||||||
|
wire [4+WITH_CSR:0] rreg0;
|
||||||
|
wire [4+WITH_CSR:0] rreg1;
|
||||||
|
wire rf_ready;
|
||||||
|
wire [W-1:0] rdata0;
|
||||||
|
wire [W-1:0] rdata1;
|
||||||
|
|
||||||
|
serv_rf_ram_if
|
||||||
|
#(.width (RF_WIDTH),
|
||||||
|
.reset_strategy (RESET_STRATEGY),
|
||||||
|
.W (W),
|
||||||
|
.csr_regs (CSR_REGS))
|
||||||
|
rf_ram_if
|
||||||
|
(.i_clk (clk),
|
||||||
|
.i_rst (i_rst),
|
||||||
|
.i_wreq (rf_wreq),
|
||||||
|
.i_rreq (rf_rreq),
|
||||||
|
.o_ready (rf_ready),
|
||||||
|
.i_wreg0 (wreg0),
|
||||||
|
.i_wreg1 (wreg1),
|
||||||
|
.i_wen0 (wen0),
|
||||||
|
.i_wen1 (wen1),
|
||||||
|
.i_wdata0 (wdata0),
|
||||||
|
.i_wdata1 (wdata1),
|
||||||
|
.i_rreg0 (rreg0),
|
||||||
|
.i_rreg1 (rreg1),
|
||||||
|
.o_rdata0 (rdata0),
|
||||||
|
.o_rdata1 (rdata1),
|
||||||
|
.o_waddr (o_waddr),
|
||||||
|
.o_wdata (o_wdata),
|
||||||
|
.o_wen (o_wen),
|
||||||
|
.o_raddr (o_raddr),
|
||||||
|
.i_rdata (i_rdata));
|
||||||
|
|
||||||
|
qerv_top
|
||||||
|
#(.RESET_PC (32'd0),
|
||||||
|
.PRE_REGISTER (PRE_REGISTER),
|
||||||
|
.RESET_STRATEGY (RESET_STRATEGY),
|
||||||
|
.WITH_CSR (WITH_CSR),
|
||||||
|
.W (W),
|
||||||
|
.MDU(1'b0))
|
||||||
|
cpu
|
||||||
|
(
|
||||||
|
.clk (clk),
|
||||||
|
.i_rst (i_rst),
|
||||||
|
.i_timer_irq (i_timer_irq),
|
||||||
|
.o_rf_rreq (rf_rreq),
|
||||||
|
.o_rf_wreq (rf_wreq),
|
||||||
|
.i_rf_ready (rf_ready),
|
||||||
|
.o_wreg0 (wreg0),
|
||||||
|
.o_wreg1 (wreg1),
|
||||||
|
.o_wen0 (wen0),
|
||||||
|
.o_wen1 (wen1),
|
||||||
|
.o_wdata0 (wdata0),
|
||||||
|
.o_wdata1 (wdata1),
|
||||||
|
.o_rreg0 (rreg0),
|
||||||
|
.o_rreg1 (rreg1),
|
||||||
|
.i_rdata0 (rdata0),
|
||||||
|
.i_rdata1 (rdata1),
|
||||||
|
|
||||||
|
.o_ibus_adr (o_ibus_adr),
|
||||||
|
.o_ibus_cyc (o_ibus_cyc),
|
||||||
|
.i_ibus_rdt (i_ibus_rdt),
|
||||||
|
.i_ibus_ack (i_ibus_ack),
|
||||||
|
|
||||||
|
.o_dbus_adr (o_dbus_adr),
|
||||||
|
.o_dbus_dat (o_dbus_dat),
|
||||||
|
.o_dbus_sel (o_dbus_sel),
|
||||||
|
.o_dbus_we (o_dbus_we),
|
||||||
|
.o_dbus_cyc (o_dbus_cyc),
|
||||||
|
.i_dbus_rdt (i_dbus_rdt),
|
||||||
|
.i_dbus_ack (i_dbus_ack),
|
||||||
|
|
||||||
|
//Extension
|
||||||
|
.o_ext_funct3 (),
|
||||||
|
.i_ext_ready (1'b0),
|
||||||
|
.i_ext_rd (32'd0),
|
||||||
|
.o_ext_rs1 (),
|
||||||
|
.o_ext_rs2 (),
|
||||||
|
//MDU
|
||||||
|
.o_mdu_valid ());
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
`default_nettype wire
|
||||||
694
rtl/qerv/serv_top.v
Normal file
694
rtl/qerv/serv_top.v
Normal file
@@ -0,0 +1,694 @@
|
|||||||
|
`default_nettype none
|
||||||
|
|
||||||
|
module qerv_top
|
||||||
|
#(parameter WITH_CSR = 1,
|
||||||
|
parameter W = 1,
|
||||||
|
parameter B = W-1,
|
||||||
|
parameter PRE_REGISTER = 1,
|
||||||
|
parameter RESET_STRATEGY = "MINI",
|
||||||
|
parameter RESET_PC = 32'd0,
|
||||||
|
parameter [0:0] DEBUG = 1'b0,
|
||||||
|
parameter [0:0] MDU = 1'b0,
|
||||||
|
parameter [0:0] COMPRESSED=0,
|
||||||
|
parameter [0:0] ALIGN = COMPRESSED)
|
||||||
|
(
|
||||||
|
input wire clk,
|
||||||
|
input wire i_rst,
|
||||||
|
input wire i_timer_irq,
|
||||||
|
`ifdef RISCV_FORMAL
|
||||||
|
output wire rvfi_valid,
|
||||||
|
output wire [63:0] rvfi_order,
|
||||||
|
output wire [31:0] rvfi_insn,
|
||||||
|
output wire rvfi_trap,
|
||||||
|
output wire rvfi_halt,
|
||||||
|
output wire rvfi_intr,
|
||||||
|
output wire [1:0] rvfi_mode,
|
||||||
|
output wire [1:0] rvfi_ixl,
|
||||||
|
output wire [4:0] rvfi_rs1_addr,
|
||||||
|
output wire [4:0] rvfi_rs2_addr,
|
||||||
|
output wire [31:0] rvfi_rs1_rdata,
|
||||||
|
output wire [31:0] rvfi_rs2_rdata,
|
||||||
|
output wire [4:0] rvfi_rd_addr,
|
||||||
|
output wire [31:0] rvfi_rd_wdata,
|
||||||
|
output wire [31:0] rvfi_pc_rdata,
|
||||||
|
output wire [31:0] rvfi_pc_wdata,
|
||||||
|
output wire [31:0] rvfi_mem_addr,
|
||||||
|
output wire [3:0] rvfi_mem_rmask,
|
||||||
|
output wire [3:0] rvfi_mem_wmask,
|
||||||
|
output wire [31:0] rvfi_mem_rdata,
|
||||||
|
output wire [31:0] rvfi_mem_wdata,
|
||||||
|
`endif
|
||||||
|
//RF Interface
|
||||||
|
output wire o_rf_rreq,
|
||||||
|
output wire o_rf_wreq,
|
||||||
|
input wire i_rf_ready,
|
||||||
|
output wire [4+WITH_CSR:0] o_wreg0,
|
||||||
|
output wire [4+WITH_CSR:0] o_wreg1,
|
||||||
|
output wire o_wen0,
|
||||||
|
output wire o_wen1,
|
||||||
|
output wire [B:0] o_wdata0,
|
||||||
|
output wire [B:0] o_wdata1,
|
||||||
|
output wire [4+WITH_CSR:0] o_rreg0,
|
||||||
|
output wire [4+WITH_CSR:0] o_rreg1,
|
||||||
|
input wire [B:0] i_rdata0,
|
||||||
|
input wire [B:0] i_rdata1,
|
||||||
|
|
||||||
|
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,
|
||||||
|
//Extension
|
||||||
|
output wire [ 2:0] o_ext_funct3,
|
||||||
|
input wire i_ext_ready,
|
||||||
|
input wire [31:0] i_ext_rd,
|
||||||
|
output wire [31:0] o_ext_rs1,
|
||||||
|
output wire [31:0] o_ext_rs2,
|
||||||
|
//MDU
|
||||||
|
output wire o_mdu_valid);
|
||||||
|
|
||||||
|
wire [4:0] rd_addr;
|
||||||
|
wire [4:0] rs1_addr;
|
||||||
|
wire [4:0] rs2_addr;
|
||||||
|
|
||||||
|
wire [3:0] immdec_ctrl;
|
||||||
|
wire [3:0] immdec_en;
|
||||||
|
|
||||||
|
wire sh_right;
|
||||||
|
wire bne_or_bge;
|
||||||
|
wire cond_branch;
|
||||||
|
wire two_stage_op;
|
||||||
|
wire e_op;
|
||||||
|
wire ebreak;
|
||||||
|
wire branch_op;
|
||||||
|
wire shift_op;
|
||||||
|
wire rd_op;
|
||||||
|
wire mdu_op;
|
||||||
|
|
||||||
|
wire rd_alu_en;
|
||||||
|
wire rd_csr_en;
|
||||||
|
wire rd_mem_en;
|
||||||
|
wire [B:0] ctrl_rd;
|
||||||
|
wire [B:0] alu_rd;
|
||||||
|
wire [B:0] mem_rd;
|
||||||
|
wire [B:0] csr_rd;
|
||||||
|
wire mtval_pc;
|
||||||
|
|
||||||
|
wire ctrl_pc_en;
|
||||||
|
wire jump;
|
||||||
|
wire jal_or_jalr;
|
||||||
|
wire utype;
|
||||||
|
wire mret;
|
||||||
|
wire [B:0] imm;
|
||||||
|
wire trap;
|
||||||
|
wire pc_rel;
|
||||||
|
wire iscomp;
|
||||||
|
|
||||||
|
wire init;
|
||||||
|
wire cnt_en;
|
||||||
|
wire cnt0to3;
|
||||||
|
wire cnt12to31;
|
||||||
|
wire cnt0;
|
||||||
|
wire cnt1;
|
||||||
|
wire cnt2;
|
||||||
|
wire cnt3;
|
||||||
|
wire cnt7;
|
||||||
|
wire cnt11;
|
||||||
|
wire cnt12;
|
||||||
|
|
||||||
|
wire cnt_done;
|
||||||
|
|
||||||
|
wire bufreg_en;
|
||||||
|
wire bufreg_sh_signed;
|
||||||
|
wire bufreg_rs1_en;
|
||||||
|
wire bufreg_imm_en;
|
||||||
|
wire bufreg_clr_lsb;
|
||||||
|
wire [B:0] bufreg_q;
|
||||||
|
wire [B:0] bufreg2_q;
|
||||||
|
wire [31:0] dbus_rdt;
|
||||||
|
wire dbus_ack;
|
||||||
|
|
||||||
|
wire alu_sub;
|
||||||
|
wire [1:0] alu_bool_op;
|
||||||
|
wire alu_cmp_eq;
|
||||||
|
wire alu_cmp_sig;
|
||||||
|
wire alu_cmp;
|
||||||
|
wire [2:0] alu_rd_sel;
|
||||||
|
|
||||||
|
wire [B:0] rs1;
|
||||||
|
wire [B:0] rs2;
|
||||||
|
wire rd_en;
|
||||||
|
|
||||||
|
wire [B:0] op_b;
|
||||||
|
wire op_b_sel;
|
||||||
|
|
||||||
|
wire mem_signed;
|
||||||
|
wire mem_word;
|
||||||
|
wire mem_half;
|
||||||
|
wire [1:0] mem_bytecnt;
|
||||||
|
wire sh_done;
|
||||||
|
|
||||||
|
wire mem_misalign;
|
||||||
|
|
||||||
|
wire [B:0] bad_pc;
|
||||||
|
|
||||||
|
wire csr_mstatus_en;
|
||||||
|
wire csr_mie_en;
|
||||||
|
wire csr_mcause_en;
|
||||||
|
wire [1:0] csr_source;
|
||||||
|
wire [B:0] csr_imm;
|
||||||
|
wire csr_d_sel;
|
||||||
|
wire csr_en;
|
||||||
|
wire [1:0] csr_addr;
|
||||||
|
wire [B:0] csr_pc;
|
||||||
|
wire csr_imm_en;
|
||||||
|
wire [B:0] csr_in;
|
||||||
|
wire [B:0] rf_csr_out;
|
||||||
|
wire dbus_en;
|
||||||
|
|
||||||
|
wire new_irq;
|
||||||
|
|
||||||
|
wire [1:0] lsb;
|
||||||
|
|
||||||
|
//verilator lint_off UNUSED
|
||||||
|
wire [31:0] i_wb_rdt;
|
||||||
|
//verilator lint_on UNUSED
|
||||||
|
|
||||||
|
wire [31:0] wb_ibus_adr;
|
||||||
|
wire wb_ibus_cyc;
|
||||||
|
wire [31:0] wb_ibus_rdt;
|
||||||
|
wire wb_ibus_ack;
|
||||||
|
|
||||||
|
generate
|
||||||
|
if (ALIGN) begin : gen_align
|
||||||
|
serv_aligner align
|
||||||
|
(
|
||||||
|
.clk(clk),
|
||||||
|
.rst(i_rst),
|
||||||
|
// serv_rf_top
|
||||||
|
.i_ibus_adr(wb_ibus_adr),
|
||||||
|
.i_ibus_cyc(wb_ibus_cyc),
|
||||||
|
.o_ibus_rdt(wb_ibus_rdt),
|
||||||
|
.o_ibus_ack(wb_ibus_ack),
|
||||||
|
// servant_arbiter
|
||||||
|
.o_wb_ibus_adr(o_ibus_adr),
|
||||||
|
.o_wb_ibus_cyc(o_ibus_cyc),
|
||||||
|
.i_wb_ibus_rdt(i_ibus_rdt),
|
||||||
|
.i_wb_ibus_ack(i_ibus_ack));
|
||||||
|
end else begin : gen_no_align
|
||||||
|
assign o_ibus_adr = wb_ibus_adr;
|
||||||
|
assign o_ibus_cyc = wb_ibus_cyc;
|
||||||
|
assign wb_ibus_rdt = i_ibus_rdt;
|
||||||
|
assign wb_ibus_ack = i_ibus_ack;
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
generate
|
||||||
|
if (COMPRESSED) begin : gen_compressed
|
||||||
|
serv_compdec compdec
|
||||||
|
(
|
||||||
|
.i_clk(clk),
|
||||||
|
.i_instr(wb_ibus_rdt),
|
||||||
|
.i_ack(wb_ibus_ack),
|
||||||
|
.o_instr(i_wb_rdt),
|
||||||
|
.o_iscomp(iscomp));
|
||||||
|
end else begin : gen_no_compressed
|
||||||
|
assign i_wb_rdt = wb_ibus_rdt;
|
||||||
|
assign iscomp = 1'b0;
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
serv_state
|
||||||
|
#(.RESET_STRATEGY (RESET_STRATEGY),
|
||||||
|
.WITH_CSR (WITH_CSR[0:0]),
|
||||||
|
.MDU(MDU),
|
||||||
|
.ALIGN(ALIGN),
|
||||||
|
.W(W))
|
||||||
|
state
|
||||||
|
(
|
||||||
|
.i_clk (clk),
|
||||||
|
.i_rst (i_rst),
|
||||||
|
//State
|
||||||
|
.i_new_irq (new_irq),
|
||||||
|
.i_alu_cmp (alu_cmp),
|
||||||
|
.o_init (init),
|
||||||
|
.o_cnt_en (cnt_en),
|
||||||
|
.o_cnt0to3 (cnt0to3),
|
||||||
|
.o_cnt12to31 (cnt12to31),
|
||||||
|
.o_cnt0 (cnt0),
|
||||||
|
.o_cnt1 (cnt1),
|
||||||
|
.o_cnt2 (cnt2),
|
||||||
|
.o_cnt3 (cnt3),
|
||||||
|
.o_cnt7 (cnt7),
|
||||||
|
.o_cnt11 (cnt11),
|
||||||
|
.o_cnt12 (cnt12),
|
||||||
|
.o_cnt_done (cnt_done),
|
||||||
|
.o_bufreg_en (bufreg_en),
|
||||||
|
.o_ctrl_pc_en (ctrl_pc_en),
|
||||||
|
.o_ctrl_jump (jump),
|
||||||
|
.o_ctrl_trap (trap),
|
||||||
|
.i_ctrl_misalign(lsb[1]),
|
||||||
|
.i_sh_done (sh_done),
|
||||||
|
.o_mem_bytecnt (mem_bytecnt),
|
||||||
|
.i_mem_misalign (mem_misalign),
|
||||||
|
//Control
|
||||||
|
.i_bne_or_bge (bne_or_bge),
|
||||||
|
.i_cond_branch (cond_branch),
|
||||||
|
.i_dbus_en (dbus_en),
|
||||||
|
.i_two_stage_op (two_stage_op),
|
||||||
|
.i_branch_op (branch_op),
|
||||||
|
.i_shift_op (shift_op),
|
||||||
|
.i_sh_right (sh_right),
|
||||||
|
.i_alu_rd_sel1 (alu_rd_sel[1]),
|
||||||
|
.i_rd_alu_en (rd_alu_en),
|
||||||
|
.i_e_op (e_op),
|
||||||
|
.i_rd_op (rd_op),
|
||||||
|
//MDU
|
||||||
|
.i_mdu_op (mdu_op),
|
||||||
|
.o_mdu_valid (o_mdu_valid),
|
||||||
|
//Extension
|
||||||
|
.i_mdu_ready (i_ext_ready),
|
||||||
|
//External
|
||||||
|
.o_dbus_cyc (o_dbus_cyc),
|
||||||
|
.i_dbus_ack (i_dbus_ack),
|
||||||
|
.o_ibus_cyc (wb_ibus_cyc),
|
||||||
|
.i_ibus_ack (wb_ibus_ack),
|
||||||
|
//RF Interface
|
||||||
|
.o_rf_rreq (o_rf_rreq),
|
||||||
|
.o_rf_wreq (o_rf_wreq),
|
||||||
|
.i_rf_ready (i_rf_ready),
|
||||||
|
.o_rf_rd_en (rd_en));
|
||||||
|
|
||||||
|
serv_decode
|
||||||
|
#(.PRE_REGISTER (PRE_REGISTER),
|
||||||
|
.MDU(MDU))
|
||||||
|
decode
|
||||||
|
(
|
||||||
|
.clk (clk),
|
||||||
|
//Input
|
||||||
|
.i_wb_rdt (i_wb_rdt[31:2]),
|
||||||
|
.i_wb_en (wb_ibus_ack),
|
||||||
|
//To state
|
||||||
|
.o_bne_or_bge (bne_or_bge),
|
||||||
|
.o_cond_branch (cond_branch),
|
||||||
|
.o_dbus_en (dbus_en),
|
||||||
|
.o_e_op (e_op),
|
||||||
|
.o_ebreak (ebreak),
|
||||||
|
.o_branch_op (branch_op),
|
||||||
|
.o_shift_op (shift_op),
|
||||||
|
.o_rd_op (rd_op),
|
||||||
|
.o_sh_right (sh_right),
|
||||||
|
.o_mdu_op (mdu_op),
|
||||||
|
.o_two_stage_op (two_stage_op),
|
||||||
|
//Extension
|
||||||
|
.o_ext_funct3 (o_ext_funct3),
|
||||||
|
|
||||||
|
//To bufreg
|
||||||
|
.o_bufreg_rs1_en (bufreg_rs1_en),
|
||||||
|
.o_bufreg_imm_en (bufreg_imm_en),
|
||||||
|
.o_bufreg_clr_lsb (bufreg_clr_lsb),
|
||||||
|
.o_bufreg_sh_signed (bufreg_sh_signed),
|
||||||
|
//To bufreg2
|
||||||
|
.o_op_b_source (op_b_sel),
|
||||||
|
//To ctrl
|
||||||
|
.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_sig (alu_cmp_sig),
|
||||||
|
.o_alu_rd_sel (alu_rd_sel),
|
||||||
|
//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),
|
||||||
|
.o_csr_imm_en (csr_imm_en),
|
||||||
|
.o_mtval_pc (mtval_pc ),
|
||||||
|
//To top
|
||||||
|
.o_immdec_ctrl (immdec_ctrl),
|
||||||
|
.o_immdec_en (immdec_en),
|
||||||
|
//To RF IF
|
||||||
|
.o_rd_mem_en (rd_mem_en),
|
||||||
|
.o_rd_csr_en (rd_csr_en),
|
||||||
|
.o_rd_alu_en (rd_alu_en));
|
||||||
|
|
||||||
|
generate
|
||||||
|
if (W == 1) begin : gen_serv_immdec
|
||||||
|
serv_immdec immdec
|
||||||
|
(
|
||||||
|
.i_clk (clk),
|
||||||
|
//State
|
||||||
|
.i_cnt_en (cnt_en),
|
||||||
|
.i_cnt_done (cnt_done),
|
||||||
|
//Control
|
||||||
|
.i_immdec_en (immdec_en),
|
||||||
|
.i_csr_imm_en (csr_imm_en),
|
||||||
|
.i_ctrl (immdec_ctrl),
|
||||||
|
.o_rd_addr (rd_addr),
|
||||||
|
.o_rs1_addr (rs1_addr),
|
||||||
|
.o_rs2_addr (rs2_addr),
|
||||||
|
//Data
|
||||||
|
.o_csr_imm (csr_imm),
|
||||||
|
.o_imm (imm),
|
||||||
|
//External
|
||||||
|
.i_wb_en (wb_ibus_ack),
|
||||||
|
.i_wb_rdt (i_wb_rdt[31:7]));
|
||||||
|
end else if (W == 4) begin : gen_qerv_immdec
|
||||||
|
qerv_immdec immdec
|
||||||
|
(
|
||||||
|
.i_clk (clk),
|
||||||
|
//State
|
||||||
|
.i_cnt_en (cnt_en),
|
||||||
|
.i_cnt_done (cnt_done),
|
||||||
|
//Control
|
||||||
|
.i_immdec_en (immdec_en),
|
||||||
|
.i_csr_imm_en (csr_imm_en),
|
||||||
|
.i_ctrl (immdec_ctrl),
|
||||||
|
.o_rd_addr (rd_addr),
|
||||||
|
.o_rs1_addr (rs1_addr),
|
||||||
|
.o_rs2_addr (rs2_addr),
|
||||||
|
//Data
|
||||||
|
.o_csr_imm (csr_imm),
|
||||||
|
.o_imm (imm),
|
||||||
|
//External
|
||||||
|
.i_wb_en (wb_ibus_ack),
|
||||||
|
.i_wb_rdt (i_wb_rdt[31:7]));
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
serv_bufreg
|
||||||
|
#(.MDU(MDU),
|
||||||
|
.W(W))
|
||||||
|
bufreg
|
||||||
|
(
|
||||||
|
.i_clk (clk),
|
||||||
|
//State
|
||||||
|
.i_cnt0 (cnt0),
|
||||||
|
.i_cnt1 (cnt1),
|
||||||
|
.i_cnt_done (cnt_done),
|
||||||
|
.i_en (bufreg_en),
|
||||||
|
.i_init (init),
|
||||||
|
.i_mdu_op (mdu_op),
|
||||||
|
.o_lsb (lsb),
|
||||||
|
//Control
|
||||||
|
.i_sh_signed (bufreg_sh_signed),
|
||||||
|
.i_rs1_en (bufreg_rs1_en),
|
||||||
|
.i_imm_en (bufreg_imm_en),
|
||||||
|
.i_clr_lsb (bufreg_clr_lsb),
|
||||||
|
.i_shift_op (shift_op),
|
||||||
|
.i_right_shift_op (sh_right),
|
||||||
|
.i_shamt (o_dbus_dat[26:24]),
|
||||||
|
//Data
|
||||||
|
.i_rs1 (rs1),
|
||||||
|
.i_imm (imm),
|
||||||
|
.o_q (bufreg_q),
|
||||||
|
//External
|
||||||
|
.o_dbus_adr (o_dbus_adr),
|
||||||
|
.o_ext_rs1 (o_ext_rs1));
|
||||||
|
|
||||||
|
serv_bufreg2 #(.W(W)) bufreg2
|
||||||
|
(
|
||||||
|
.i_clk (clk),
|
||||||
|
//State
|
||||||
|
.i_en (cnt_en),
|
||||||
|
.i_init (init),
|
||||||
|
.i_cnt7 (cnt7),
|
||||||
|
.i_cnt_done (cnt_done),
|
||||||
|
.i_sh_right (sh_right),
|
||||||
|
.i_lsb (lsb),
|
||||||
|
.i_bytecnt (mem_bytecnt),
|
||||||
|
.o_sh_done (sh_done),
|
||||||
|
//Control
|
||||||
|
.i_op_b_sel (op_b_sel),
|
||||||
|
.i_shift_op (shift_op),
|
||||||
|
//Data
|
||||||
|
.i_rs2 (rs2),
|
||||||
|
.i_imm (imm),
|
||||||
|
.o_op_b (op_b),
|
||||||
|
.o_q (bufreg2_q),
|
||||||
|
//External
|
||||||
|
.o_dat (o_dbus_dat),
|
||||||
|
.i_load (dbus_ack),
|
||||||
|
.i_dat (dbus_rdt));
|
||||||
|
|
||||||
|
serv_ctrl
|
||||||
|
#(.RESET_PC (RESET_PC),
|
||||||
|
.RESET_STRATEGY (RESET_STRATEGY),
|
||||||
|
.WITH_CSR (WITH_CSR),
|
||||||
|
.W (W))
|
||||||
|
ctrl
|
||||||
|
(
|
||||||
|
.clk (clk),
|
||||||
|
.i_rst (i_rst),
|
||||||
|
//State
|
||||||
|
.i_pc_en (ctrl_pc_en),
|
||||||
|
.i_cnt12to31 (cnt12to31),
|
||||||
|
.i_cnt0 (cnt0),
|
||||||
|
.i_cnt1 (cnt1),
|
||||||
|
.i_cnt2 (cnt2),
|
||||||
|
//Control
|
||||||
|
.i_jump (jump),
|
||||||
|
.i_jal_or_jalr (jal_or_jalr),
|
||||||
|
.i_utype (utype),
|
||||||
|
.i_pc_rel (pc_rel),
|
||||||
|
.i_trap (trap | mret),
|
||||||
|
.i_iscomp (iscomp),
|
||||||
|
//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 (wb_ibus_adr));
|
||||||
|
|
||||||
|
serv_alu #(.W (W)) alu
|
||||||
|
(
|
||||||
|
.clk (clk),
|
||||||
|
//State
|
||||||
|
.i_en (cnt_en),
|
||||||
|
.i_cnt0 (cnt0),
|
||||||
|
.o_cmp (alu_cmp),
|
||||||
|
//Control
|
||||||
|
.i_sub (alu_sub),
|
||||||
|
.i_bool_op (alu_bool_op),
|
||||||
|
.i_cmp_eq (alu_cmp_eq),
|
||||||
|
.i_cmp_sig (alu_cmp_sig),
|
||||||
|
.i_rd_sel (alu_rd_sel),
|
||||||
|
//Data
|
||||||
|
.i_rs1 (rs1),
|
||||||
|
.i_op_b (op_b),
|
||||||
|
.i_buf (bufreg_q),
|
||||||
|
.o_rd (alu_rd));
|
||||||
|
|
||||||
|
serv_rf_if
|
||||||
|
#(.WITH_CSR (WITH_CSR), .W(W))
|
||||||
|
rf_if
|
||||||
|
(//RF interface
|
||||||
|
.i_cnt_en (cnt_en),
|
||||||
|
.o_wreg0 (o_wreg0),
|
||||||
|
.o_wreg1 (o_wreg1),
|
||||||
|
.o_wen0 (o_wen0),
|
||||||
|
.o_wen1 (o_wen1),
|
||||||
|
.o_wdata0 (o_wdata0),
|
||||||
|
.o_wdata1 (o_wdata1),
|
||||||
|
.o_rreg0 (o_rreg0),
|
||||||
|
.o_rreg1 (o_rreg1),
|
||||||
|
.i_rdata0 (i_rdata0),
|
||||||
|
.i_rdata1 (i_rdata1),
|
||||||
|
|
||||||
|
//Trap interface
|
||||||
|
.i_trap (trap),
|
||||||
|
.i_mret (mret),
|
||||||
|
.i_mepc (wb_ibus_adr[B:0]),
|
||||||
|
.i_mtval_pc (mtval_pc),
|
||||||
|
.i_bufreg_q (bufreg_q),
|
||||||
|
.i_bad_pc (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),
|
||||||
|
.i_rd_waddr (rd_addr),
|
||||||
|
.i_ctrl_rd (ctrl_rd),
|
||||||
|
.i_alu_rd (alu_rd),
|
||||||
|
.i_rd_alu_en (rd_alu_en),
|
||||||
|
.i_csr_rd (csr_rd),
|
||||||
|
.i_rd_csr_en (rd_csr_en),
|
||||||
|
.i_mem_rd (mem_rd),
|
||||||
|
.i_rd_mem_en (rd_mem_en),
|
||||||
|
|
||||||
|
//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
|
||||||
|
#(.WITH_CSR (WITH_CSR[0:0]),
|
||||||
|
.W (W))
|
||||||
|
mem_if
|
||||||
|
(
|
||||||
|
.i_clk (clk),
|
||||||
|
//State
|
||||||
|
.i_bytecnt (mem_bytecnt),
|
||||||
|
.i_lsb (lsb),
|
||||||
|
.o_misalign (mem_misalign),
|
||||||
|
//Control
|
||||||
|
.i_mdu_op (mdu_op),
|
||||||
|
.i_signed (mem_signed),
|
||||||
|
.i_word (mem_word),
|
||||||
|
.i_half (mem_half),
|
||||||
|
//Data
|
||||||
|
.i_bufreg2_q (bufreg2_q),
|
||||||
|
.o_rd (mem_rd),
|
||||||
|
//External interface
|
||||||
|
.o_wb_sel (o_dbus_sel));
|
||||||
|
|
||||||
|
generate
|
||||||
|
if (|WITH_CSR) begin : gen_csr
|
||||||
|
serv_csr
|
||||||
|
#(.RESET_STRATEGY (RESET_STRATEGY),
|
||||||
|
.W(W))
|
||||||
|
csr
|
||||||
|
(
|
||||||
|
.i_clk (clk),
|
||||||
|
.i_rst (i_rst),
|
||||||
|
//State
|
||||||
|
.i_trig_irq (wb_ibus_ack),
|
||||||
|
.i_en (cnt_en),
|
||||||
|
.i_cnt0to3 (cnt0to3),
|
||||||
|
.i_cnt3 (cnt3),
|
||||||
|
.i_cnt7 (cnt7),
|
||||||
|
.i_cnt11 (cnt11),
|
||||||
|
.i_cnt12 (cnt12),
|
||||||
|
.i_cnt_done (cnt_done),
|
||||||
|
.i_mem_op (!mtval_pc),
|
||||||
|
.i_mtip (i_timer_irq),
|
||||||
|
.i_trap (trap),
|
||||||
|
.o_new_irq (new_irq),
|
||||||
|
//Control
|
||||||
|
.i_e_op (e_op),
|
||||||
|
.i_ebreak (ebreak),
|
||||||
|
.i_mem_cmd (o_dbus_we),
|
||||||
|
.i_mstatus_en (csr_mstatus_en),
|
||||||
|
.i_mie_en (csr_mie_en ),
|
||||||
|
.i_mcause_en (csr_mcause_en ),
|
||||||
|
.i_csr_source (csr_source),
|
||||||
|
.i_mret (mret),
|
||||||
|
.i_csr_d_sel (csr_d_sel),
|
||||||
|
//Data
|
||||||
|
.i_rf_csr_out (rf_csr_out),
|
||||||
|
.o_csr_in (csr_in),
|
||||||
|
.i_csr_imm (csr_imm),
|
||||||
|
.i_rs1 (rs1),
|
||||||
|
.o_q (csr_rd));
|
||||||
|
end else begin : gen_no_csr
|
||||||
|
assign csr_in = {W{1'b0}};
|
||||||
|
assign csr_rd = {W{1'b0}};
|
||||||
|
assign new_irq = 1'b0;
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
generate
|
||||||
|
if (DEBUG) begin : gen_debug
|
||||||
|
serv_debug #(.W (W), .RESET_PC (RESET_PC)) debug
|
||||||
|
(
|
||||||
|
`ifdef RISCV_FORMAL
|
||||||
|
.rvfi_valid (rvfi_valid ),
|
||||||
|
.rvfi_order (rvfi_order ),
|
||||||
|
.rvfi_insn (rvfi_insn ),
|
||||||
|
.rvfi_trap (rvfi_trap ),
|
||||||
|
.rvfi_halt (rvfi_halt ),
|
||||||
|
.rvfi_intr (rvfi_intr ),
|
||||||
|
.rvfi_mode (rvfi_mode ),
|
||||||
|
.rvfi_ixl (rvfi_ixl ),
|
||||||
|
.rvfi_rs1_addr (rvfi_rs1_addr ),
|
||||||
|
.rvfi_rs2_addr (rvfi_rs2_addr ),
|
||||||
|
.rvfi_rs1_rdata (rvfi_rs1_rdata),
|
||||||
|
.rvfi_rs2_rdata (rvfi_rs2_rdata),
|
||||||
|
.rvfi_rd_addr (rvfi_rd_addr ),
|
||||||
|
.rvfi_rd_wdata (rvfi_rd_wdata ),
|
||||||
|
.rvfi_pc_rdata (rvfi_pc_rdata ),
|
||||||
|
.rvfi_pc_wdata (rvfi_pc_wdata ),
|
||||||
|
.rvfi_mem_addr (rvfi_mem_addr ),
|
||||||
|
.rvfi_mem_rmask (rvfi_mem_rmask),
|
||||||
|
.rvfi_mem_wmask (rvfi_mem_wmask),
|
||||||
|
.rvfi_mem_rdata (rvfi_mem_rdata),
|
||||||
|
.rvfi_mem_wdata (rvfi_mem_wdata),
|
||||||
|
.i_dbus_adr (o_dbus_adr),
|
||||||
|
.i_dbus_dat (o_dbus_dat),
|
||||||
|
.i_dbus_sel (o_dbus_sel),
|
||||||
|
.i_dbus_we (o_dbus_we ),
|
||||||
|
.i_dbus_rdt (i_dbus_rdt),
|
||||||
|
.i_dbus_ack (i_dbus_ack),
|
||||||
|
.i_ctrl_pc_en (ctrl_pc_en),
|
||||||
|
.rs1 (rs1),
|
||||||
|
.rs2 (rs2),
|
||||||
|
.rs1_addr (rs1_addr),
|
||||||
|
.rs2_addr (rs2_addr),
|
||||||
|
.immdec_en (immdec_en),
|
||||||
|
.rd_en (rd_en),
|
||||||
|
.trap (trap),
|
||||||
|
.i_rf_ready (i_rf_ready),
|
||||||
|
.i_ibus_cyc (o_ibus_cyc),
|
||||||
|
.two_stage_op (two_stage_op),
|
||||||
|
.init (init),
|
||||||
|
.i_ibus_adr (o_ibus_adr),
|
||||||
|
`endif
|
||||||
|
.i_clk (clk),
|
||||||
|
.i_rst (i_rst),
|
||||||
|
.i_ibus_rdt (i_ibus_rdt),
|
||||||
|
.i_ibus_ack (i_ibus_ack),
|
||||||
|
.i_rd_addr (rd_addr ),
|
||||||
|
.i_cnt_en (cnt_en ),
|
||||||
|
.i_csr_in (csr_in ),
|
||||||
|
.i_csr_mstatus_en (csr_mstatus_en),
|
||||||
|
.i_csr_mie_en (csr_mie_en ),
|
||||||
|
.i_csr_mcause_en (csr_mcause_en ),
|
||||||
|
.i_csr_en (csr_en ),
|
||||||
|
.i_csr_addr (csr_addr),
|
||||||
|
.i_wen0 (o_wen0),
|
||||||
|
.i_wdata0 (o_wdata0),
|
||||||
|
.i_cnt_done (cnt_done));
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
|
||||||
|
generate
|
||||||
|
if (MDU) begin: gen_mdu
|
||||||
|
assign dbus_rdt = i_ext_ready ? i_ext_rd:i_dbus_rdt;
|
||||||
|
assign dbus_ack = i_dbus_ack | i_ext_ready;
|
||||||
|
end else begin : gen_no_mdu
|
||||||
|
assign dbus_rdt = i_dbus_rdt;
|
||||||
|
assign dbus_ack = i_dbus_ack;
|
||||||
|
end
|
||||||
|
assign o_ext_rs2 = o_dbus_dat;
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
`default_nettype wire
|
||||||
279
rtl/qerv/servile.v
Normal file
279
rtl/qerv/servile.v
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
/*
|
||||||
|
* servile.v : Top-level for Servile, the SERV convenience wrapper
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Olof Kindgren <olof.kindgren@gmail.com>
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
`default_nettype none
|
||||||
|
module servile
|
||||||
|
#(
|
||||||
|
parameter width = 1,
|
||||||
|
parameter reset_pc = 32'h00000000,
|
||||||
|
parameter reset_strategy = "MINI",
|
||||||
|
parameter rf_width = 2*width,
|
||||||
|
parameter [0:0] sim = 1'b0,
|
||||||
|
parameter [0:0] debug = 1'b0,
|
||||||
|
parameter [0:0] with_c = 1'b0,
|
||||||
|
parameter [0:0] with_csr = 1'b0,
|
||||||
|
parameter [0:0] with_mdu = 1'b0,
|
||||||
|
//Internally calculated. Do not touch
|
||||||
|
parameter B = width-1,
|
||||||
|
parameter regs = 32+with_csr*4,
|
||||||
|
parameter rf_l2d = $clog2(regs*32/rf_width))
|
||||||
|
(
|
||||||
|
input wire i_clk,
|
||||||
|
input wire i_rst,
|
||||||
|
input wire i_timer_irq,
|
||||||
|
|
||||||
|
//Memory (WB) interface
|
||||||
|
output wire [31:0] o_wb_mem_adr,
|
||||||
|
output wire [31:0] o_wb_mem_dat,
|
||||||
|
output wire [3:0] o_wb_mem_sel,
|
||||||
|
output wire o_wb_mem_we ,
|
||||||
|
output wire o_wb_mem_stb,
|
||||||
|
input wire [31:0] i_wb_mem_rdt,
|
||||||
|
input wire i_wb_mem_ack,
|
||||||
|
|
||||||
|
//Extension (WB) interface
|
||||||
|
output wire [31:0] o_wb_ext_adr,
|
||||||
|
output wire [31:0] o_wb_ext_dat,
|
||||||
|
output wire [3:0] o_wb_ext_sel,
|
||||||
|
output wire o_wb_ext_we ,
|
||||||
|
output wire o_wb_ext_stb,
|
||||||
|
input wire [31:0] i_wb_ext_rdt,
|
||||||
|
input wire i_wb_ext_ack,
|
||||||
|
|
||||||
|
//RF (SRAM) interface
|
||||||
|
output wire [rf_l2d-1:0] o_rf_waddr,
|
||||||
|
output wire [rf_width-1:0] o_rf_wdata,
|
||||||
|
output wire o_rf_wen,
|
||||||
|
output wire [rf_l2d-1:0] o_rf_raddr,
|
||||||
|
input wire [rf_width-1:0] i_rf_rdata,
|
||||||
|
output wire o_rf_ren);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
wire [31:0] wb_ibus_adr;
|
||||||
|
wire wb_ibus_stb;
|
||||||
|
wire [31:0] wb_ibus_rdt;
|
||||||
|
wire wb_ibus_ack;
|
||||||
|
|
||||||
|
wire [31:0] wb_dbus_adr;
|
||||||
|
wire [31:0] wb_dbus_dat;
|
||||||
|
wire [3:0] wb_dbus_sel;
|
||||||
|
wire wb_dbus_we;
|
||||||
|
wire wb_dbus_stb;
|
||||||
|
wire [31:0] wb_dbus_rdt;
|
||||||
|
wire wb_dbus_ack;
|
||||||
|
|
||||||
|
wire [31:0] wb_dmem_adr;
|
||||||
|
wire [31:0] wb_dmem_dat;
|
||||||
|
wire [3:0] wb_dmem_sel;
|
||||||
|
wire wb_dmem_we;
|
||||||
|
wire wb_dmem_stb;
|
||||||
|
wire [31:0] wb_dmem_rdt;
|
||||||
|
wire wb_dmem_ack;
|
||||||
|
|
||||||
|
wire rf_wreq;
|
||||||
|
wire rf_rreq;
|
||||||
|
wire [$clog2(regs)-1:0] wreg0;
|
||||||
|
wire [$clog2(regs)-1:0] wreg1;
|
||||||
|
wire wen0;
|
||||||
|
wire wen1;
|
||||||
|
wire [B:0] wdata0;
|
||||||
|
wire [B:0] wdata1;
|
||||||
|
wire [$clog2(regs)-1:0] rreg0;
|
||||||
|
wire [$clog2(regs)-1:0] rreg1;
|
||||||
|
wire rf_ready;
|
||||||
|
wire [B:0] rdata0;
|
||||||
|
wire [B:0] rdata1;
|
||||||
|
|
||||||
|
wire [31:0] mdu_rs1;
|
||||||
|
wire [31:0] mdu_rs2;
|
||||||
|
wire [ 2:0] mdu_op;
|
||||||
|
wire mdu_valid;
|
||||||
|
wire [31:0] mdu_rd;
|
||||||
|
wire mdu_ready;
|
||||||
|
|
||||||
|
servile_mux
|
||||||
|
#(.sim (sim))
|
||||||
|
mux
|
||||||
|
(.i_clk (i_clk),
|
||||||
|
.i_rst (i_rst & (reset_strategy != "NONE")),
|
||||||
|
|
||||||
|
.i_wb_cpu_adr (wb_dbus_adr),
|
||||||
|
.i_wb_cpu_dat (wb_dbus_dat),
|
||||||
|
.i_wb_cpu_sel (wb_dbus_sel),
|
||||||
|
.i_wb_cpu_we (wb_dbus_we),
|
||||||
|
.i_wb_cpu_stb (wb_dbus_stb),
|
||||||
|
.o_wb_cpu_rdt (wb_dbus_rdt),
|
||||||
|
.o_wb_cpu_ack (wb_dbus_ack),
|
||||||
|
|
||||||
|
.o_wb_mem_adr (wb_dmem_adr),
|
||||||
|
.o_wb_mem_dat (wb_dmem_dat),
|
||||||
|
.o_wb_mem_sel (wb_dmem_sel),
|
||||||
|
.o_wb_mem_we (wb_dmem_we),
|
||||||
|
.o_wb_mem_stb (wb_dmem_stb),
|
||||||
|
.i_wb_mem_rdt (wb_dmem_rdt),
|
||||||
|
.i_wb_mem_ack (wb_dmem_ack),
|
||||||
|
|
||||||
|
.o_wb_ext_adr (o_wb_ext_adr),
|
||||||
|
.o_wb_ext_dat (o_wb_ext_dat),
|
||||||
|
.o_wb_ext_sel (o_wb_ext_sel),
|
||||||
|
.o_wb_ext_we (o_wb_ext_we),
|
||||||
|
.o_wb_ext_stb (o_wb_ext_stb),
|
||||||
|
.i_wb_ext_rdt (i_wb_ext_rdt),
|
||||||
|
.i_wb_ext_ack (i_wb_ext_ack));
|
||||||
|
|
||||||
|
servile_arbiter arbiter
|
||||||
|
(.i_wb_cpu_dbus_adr (wb_dmem_adr),
|
||||||
|
.i_wb_cpu_dbus_dat (wb_dmem_dat),
|
||||||
|
.i_wb_cpu_dbus_sel (wb_dmem_sel),
|
||||||
|
.i_wb_cpu_dbus_we (wb_dmem_we ),
|
||||||
|
.i_wb_cpu_dbus_stb (wb_dmem_stb),
|
||||||
|
.o_wb_cpu_dbus_rdt (wb_dmem_rdt),
|
||||||
|
.o_wb_cpu_dbus_ack (wb_dmem_ack),
|
||||||
|
|
||||||
|
.i_wb_cpu_ibus_adr (wb_ibus_adr),
|
||||||
|
.i_wb_cpu_ibus_stb (wb_ibus_stb),
|
||||||
|
.o_wb_cpu_ibus_rdt (wb_ibus_rdt),
|
||||||
|
.o_wb_cpu_ibus_ack (wb_ibus_ack),
|
||||||
|
|
||||||
|
.o_wb_mem_adr (o_wb_mem_adr),
|
||||||
|
.o_wb_mem_dat (o_wb_mem_dat),
|
||||||
|
.o_wb_mem_sel (o_wb_mem_sel),
|
||||||
|
.o_wb_mem_we (o_wb_mem_we ),
|
||||||
|
.o_wb_mem_stb (o_wb_mem_stb),
|
||||||
|
.i_wb_mem_rdt (i_wb_mem_rdt),
|
||||||
|
.i_wb_mem_ack (i_wb_mem_ack));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
serv_rf_ram_if
|
||||||
|
#(.width (rf_width),
|
||||||
|
.W (width),
|
||||||
|
.reset_strategy (reset_strategy),
|
||||||
|
.csr_regs (with_csr*4))
|
||||||
|
rf_ram_if
|
||||||
|
(.i_clk (i_clk),
|
||||||
|
.i_rst (i_rst),
|
||||||
|
//RF IF
|
||||||
|
.i_wreq (rf_wreq),
|
||||||
|
.i_rreq (rf_rreq),
|
||||||
|
.o_ready (rf_ready),
|
||||||
|
.i_wreg0 (wreg0),
|
||||||
|
.i_wreg1 (wreg1),
|
||||||
|
.i_wen0 (wen0),
|
||||||
|
.i_wen1 (wen1),
|
||||||
|
.i_wdata0 (wdata0),
|
||||||
|
.i_wdata1 (wdata1),
|
||||||
|
.i_rreg0 (rreg0),
|
||||||
|
.i_rreg1 (rreg1),
|
||||||
|
.o_rdata0 (rdata0),
|
||||||
|
.o_rdata1 (rdata1),
|
||||||
|
//SRAM IF
|
||||||
|
.o_waddr (o_rf_waddr),
|
||||||
|
.o_wdata (o_rf_wdata),
|
||||||
|
.o_wen (o_rf_wen),
|
||||||
|
.o_raddr (o_rf_raddr),
|
||||||
|
.o_ren (o_rf_ren),
|
||||||
|
.i_rdata (i_rf_rdata));
|
||||||
|
|
||||||
|
generate
|
||||||
|
if (with_mdu) begin : gen_mdu
|
||||||
|
mdu_top mdu_serv
|
||||||
|
(.i_clk (i_clk),
|
||||||
|
.i_rst (i_rst),
|
||||||
|
.i_mdu_rs1 (mdu_rs1),
|
||||||
|
.i_mdu_rs2 (mdu_rs2),
|
||||||
|
.i_mdu_op (mdu_op),
|
||||||
|
.i_mdu_valid (mdu_valid),
|
||||||
|
.o_mdu_ready (mdu_ready),
|
||||||
|
.o_mdu_rd (mdu_rd));
|
||||||
|
end else begin
|
||||||
|
assign mdu_ready = 1'b0;
|
||||||
|
assign mdu_rd = 32'd0;
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
qerv_top
|
||||||
|
#(
|
||||||
|
.WITH_CSR (with_csr?1:0),
|
||||||
|
.W (width),
|
||||||
|
.PRE_REGISTER (1'b1),
|
||||||
|
.RESET_STRATEGY (reset_strategy),
|
||||||
|
.RESET_PC (reset_pc),
|
||||||
|
.DEBUG (debug),
|
||||||
|
.MDU (with_mdu),
|
||||||
|
.COMPRESSED (with_c))
|
||||||
|
cpu
|
||||||
|
(
|
||||||
|
.clk (i_clk),
|
||||||
|
.i_rst (i_rst),
|
||||||
|
.i_timer_irq (i_timer_irq),
|
||||||
|
|
||||||
|
`ifdef RISCV_FORMAL
|
||||||
|
.rvfi_valid (),
|
||||||
|
.rvfi_order (),
|
||||||
|
.rvfi_insn (),
|
||||||
|
.rvfi_trap (),
|
||||||
|
.rvfi_halt (),
|
||||||
|
.rvfi_intr (),
|
||||||
|
.rvfi_mode (),
|
||||||
|
.rvfi_ixl (),
|
||||||
|
.rvfi_rs1_addr (),
|
||||||
|
.rvfi_rs2_addr (),
|
||||||
|
.rvfi_rs1_rdata (),
|
||||||
|
.rvfi_rs2_rdata (),
|
||||||
|
.rvfi_rd_addr (),
|
||||||
|
.rvfi_rd_wdata (),
|
||||||
|
.rvfi_pc_rdata (),
|
||||||
|
.rvfi_pc_wdata (),
|
||||||
|
.rvfi_mem_addr (),
|
||||||
|
.rvfi_mem_rmask (),
|
||||||
|
.rvfi_mem_wmask (),
|
||||||
|
.rvfi_mem_rdata (),
|
||||||
|
.rvfi_mem_wdata (),
|
||||||
|
`endif
|
||||||
|
//RF IF
|
||||||
|
.o_rf_rreq (rf_rreq),
|
||||||
|
.o_rf_wreq (rf_wreq),
|
||||||
|
.i_rf_ready (rf_ready),
|
||||||
|
.o_wreg0 (wreg0),
|
||||||
|
.o_wreg1 (wreg1),
|
||||||
|
.o_wen0 (wen0),
|
||||||
|
.o_wen1 (wen1),
|
||||||
|
.o_wdata0 (wdata0),
|
||||||
|
.o_wdata1 (wdata1),
|
||||||
|
.o_rreg0 (rreg0),
|
||||||
|
.o_rreg1 (rreg1),
|
||||||
|
.i_rdata0 (rdata0),
|
||||||
|
.i_rdata1 (rdata1),
|
||||||
|
|
||||||
|
//Instruction bus
|
||||||
|
.o_ibus_adr (wb_ibus_adr),
|
||||||
|
.o_ibus_cyc (wb_ibus_stb),
|
||||||
|
.i_ibus_rdt (wb_ibus_rdt),
|
||||||
|
.i_ibus_ack (wb_ibus_ack),
|
||||||
|
|
||||||
|
//Data bus
|
||||||
|
.o_dbus_adr (wb_dbus_adr),
|
||||||
|
.o_dbus_dat (wb_dbus_dat),
|
||||||
|
.o_dbus_sel (wb_dbus_sel),
|
||||||
|
.o_dbus_we (wb_dbus_we),
|
||||||
|
.o_dbus_cyc (wb_dbus_stb),
|
||||||
|
.i_dbus_rdt (wb_dbus_rdt),
|
||||||
|
.i_dbus_ack (wb_dbus_ack),
|
||||||
|
|
||||||
|
//Extension IF
|
||||||
|
.o_ext_rs1 (mdu_rs1),
|
||||||
|
.o_ext_rs2 (mdu_rs2),
|
||||||
|
.o_ext_funct3 (mdu_op),
|
||||||
|
.i_ext_rd (mdu_rd),
|
||||||
|
.i_ext_ready (mdu_ready),
|
||||||
|
//MDU
|
||||||
|
.o_mdu_valid (mdu_valid));
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
`default_nettype wire
|
||||||
45
rtl/qerv/servile_arbiter.v
Normal file
45
rtl/qerv/servile_arbiter.v
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* servile_arbiter.v : I/D arbiter for the servile convenience wrapper.
|
||||||
|
* Relies on the fact that not ibus and dbus are active at the same time.
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Olof Kindgren <olof.kindgren@gmail.com>
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
module servile_arbiter
|
||||||
|
(
|
||||||
|
input wire [31:0] i_wb_cpu_dbus_adr,
|
||||||
|
input wire [31:0] i_wb_cpu_dbus_dat,
|
||||||
|
input wire [3:0] i_wb_cpu_dbus_sel,
|
||||||
|
input wire i_wb_cpu_dbus_we,
|
||||||
|
input wire i_wb_cpu_dbus_stb,
|
||||||
|
output wire [31:0] o_wb_cpu_dbus_rdt,
|
||||||
|
output wire o_wb_cpu_dbus_ack,
|
||||||
|
|
||||||
|
input wire [31:0] i_wb_cpu_ibus_adr,
|
||||||
|
input wire i_wb_cpu_ibus_stb,
|
||||||
|
output wire [31:0] o_wb_cpu_ibus_rdt,
|
||||||
|
output wire o_wb_cpu_ibus_ack,
|
||||||
|
|
||||||
|
output wire [31:0] o_wb_mem_adr,
|
||||||
|
output wire [31:0] o_wb_mem_dat,
|
||||||
|
output wire [3:0] o_wb_mem_sel,
|
||||||
|
output wire o_wb_mem_we,
|
||||||
|
output wire o_wb_mem_stb,
|
||||||
|
input wire [31:0] i_wb_mem_rdt,
|
||||||
|
input wire i_wb_mem_ack);
|
||||||
|
|
||||||
|
assign o_wb_cpu_dbus_rdt = i_wb_mem_rdt;
|
||||||
|
assign o_wb_cpu_dbus_ack = i_wb_mem_ack & !i_wb_cpu_ibus_stb;
|
||||||
|
|
||||||
|
assign o_wb_cpu_ibus_rdt = i_wb_mem_rdt;
|
||||||
|
assign o_wb_cpu_ibus_ack = i_wb_mem_ack & i_wb_cpu_ibus_stb;
|
||||||
|
|
||||||
|
assign o_wb_mem_adr = i_wb_cpu_ibus_stb ? i_wb_cpu_ibus_adr : i_wb_cpu_dbus_adr;
|
||||||
|
assign o_wb_mem_dat = i_wb_cpu_dbus_dat;
|
||||||
|
assign o_wb_mem_sel = i_wb_cpu_dbus_sel;
|
||||||
|
assign o_wb_mem_we = i_wb_cpu_dbus_we & !i_wb_cpu_ibus_stb;
|
||||||
|
assign o_wb_mem_stb = i_wb_cpu_ibus_stb | i_wb_cpu_dbus_stb;
|
||||||
|
|
||||||
|
|
||||||
|
endmodule
|
||||||
100
rtl/qerv/servile_mux.v
Normal file
100
rtl/qerv/servile_mux.v
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* servile_mux.v : Simple Wishbone mux for the servile convenience wrapper.
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Olof Kindgren <olof.kindgren@gmail.com>
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
module servile_mux
|
||||||
|
#(parameter [0:0] sim = 1'b0, //Enable simulation features
|
||||||
|
parameter [31:0] sim_sig_adr = 32'h80000000,
|
||||||
|
parameter [31:0] sim_halt_adr = 32'h90000000)
|
||||||
|
(
|
||||||
|
input wire i_clk,
|
||||||
|
input wire i_rst,
|
||||||
|
|
||||||
|
input wire [31:0] i_wb_cpu_adr,
|
||||||
|
input wire [31:0] i_wb_cpu_dat,
|
||||||
|
input wire [3:0] i_wb_cpu_sel,
|
||||||
|
input wire i_wb_cpu_we,
|
||||||
|
input wire i_wb_cpu_stb,
|
||||||
|
output wire [31:0] o_wb_cpu_rdt,
|
||||||
|
output wire o_wb_cpu_ack,
|
||||||
|
|
||||||
|
output wire [31:0] o_wb_mem_adr,
|
||||||
|
output wire [31:0] o_wb_mem_dat,
|
||||||
|
output wire [3:0] o_wb_mem_sel,
|
||||||
|
output wire o_wb_mem_we,
|
||||||
|
output wire o_wb_mem_stb,
|
||||||
|
input wire [31:0] i_wb_mem_rdt,
|
||||||
|
input wire i_wb_mem_ack,
|
||||||
|
|
||||||
|
output wire [31:0] o_wb_ext_adr,
|
||||||
|
output wire [31:0] o_wb_ext_dat,
|
||||||
|
output wire [3:0] o_wb_ext_sel,
|
||||||
|
output wire o_wb_ext_we,
|
||||||
|
output wire o_wb_ext_stb,
|
||||||
|
input wire [31:0] i_wb_ext_rdt,
|
||||||
|
input wire i_wb_ext_ack);
|
||||||
|
|
||||||
|
wire sig_en;
|
||||||
|
wire halt_en;
|
||||||
|
reg sim_ack;
|
||||||
|
|
||||||
|
wire ext = (i_wb_cpu_adr[31:30] != 2'b00);
|
||||||
|
|
||||||
|
assign o_wb_cpu_rdt = ext ? i_wb_ext_rdt : i_wb_mem_rdt;
|
||||||
|
assign o_wb_cpu_ack = i_wb_ext_ack | i_wb_mem_ack | sim_ack;
|
||||||
|
|
||||||
|
assign o_wb_mem_adr = i_wb_cpu_adr;
|
||||||
|
assign o_wb_mem_dat = i_wb_cpu_dat;
|
||||||
|
assign o_wb_mem_sel = i_wb_cpu_sel;
|
||||||
|
assign o_wb_mem_we = i_wb_cpu_we;
|
||||||
|
assign o_wb_mem_stb = i_wb_cpu_stb & !ext & !(sig_en|halt_en);
|
||||||
|
|
||||||
|
assign o_wb_ext_adr = i_wb_cpu_adr;
|
||||||
|
assign o_wb_ext_dat = i_wb_cpu_dat;
|
||||||
|
assign o_wb_ext_sel = i_wb_cpu_sel;
|
||||||
|
assign o_wb_ext_we = i_wb_cpu_we;
|
||||||
|
assign o_wb_ext_stb = i_wb_cpu_stb & ext & !(sig_en|halt_en);
|
||||||
|
|
||||||
|
generate
|
||||||
|
if (sim) begin
|
||||||
|
|
||||||
|
integer f = 0;
|
||||||
|
|
||||||
|
assign sig_en = |f & i_wb_cpu_we & (i_wb_cpu_adr == sim_sig_adr);
|
||||||
|
assign halt_en = i_wb_cpu_we & (i_wb_cpu_adr == sim_halt_adr);
|
||||||
|
|
||||||
|
reg [1023:0] signature_file;
|
||||||
|
|
||||||
|
initial
|
||||||
|
/* verilator lint_off WIDTH */
|
||||||
|
if ($value$plusargs("signature=%s", signature_file)) begin
|
||||||
|
$display("Writing signature to %0s", signature_file);
|
||||||
|
f = $fopen(signature_file, "w");
|
||||||
|
end
|
||||||
|
/* verilator lint_on WIDTH */
|
||||||
|
|
||||||
|
always @(posedge i_clk) begin
|
||||||
|
sim_ack <= 1'b0;
|
||||||
|
if (i_wb_cpu_stb & !sim_ack) begin
|
||||||
|
sim_ack <= sig_en|halt_en;
|
||||||
|
if (sig_en & (f != 0))
|
||||||
|
$fwrite(f, "%c", i_wb_cpu_dat[7:0]);
|
||||||
|
else if(halt_en) begin
|
||||||
|
$display("Test complete");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if (i_rst)
|
||||||
|
sim_ack <= 1'b0;
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
assign sig_en = 1'b0;
|
||||||
|
assign halt_en = 1'b0;
|
||||||
|
initial sim_ack = 1'b0;
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
endmodule
|
||||||
77
rtl/qerv/servile_rf_mem_if.v
Normal file
77
rtl/qerv/servile_rf_mem_if.v
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* servile_rf_mem_if.v : Arbiter to allow a shared SRAM for RF and memory accesses. RF is mapped to the highest 128 bytes of the memory. Requires 8-bit RF accesses.
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: 2024 Olof Kindgren <olof.kindgren@gmail.com>
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
`default_nettype none
|
||||||
|
module servile_rf_mem_if
|
||||||
|
#(//Memory parameters
|
||||||
|
parameter depth = 256,
|
||||||
|
//RF parameters
|
||||||
|
parameter rf_regs = 32,
|
||||||
|
//Internally calculated. Do not touch
|
||||||
|
parameter rf_depth = $clog2(rf_regs*4),
|
||||||
|
parameter aw = $clog2(depth))
|
||||||
|
(
|
||||||
|
input wire i_clk,
|
||||||
|
input wire i_rst,
|
||||||
|
input wire [rf_depth-1:0] i_waddr,
|
||||||
|
input wire [7:0] i_wdata,
|
||||||
|
input wire i_wen,
|
||||||
|
input wire [rf_depth-1:0] i_raddr,
|
||||||
|
output wire [7:0] o_rdata,
|
||||||
|
input wire i_ren,
|
||||||
|
|
||||||
|
output wire [aw-1:0] o_sram_waddr,
|
||||||
|
output wire [7:0] o_sram_wdata,
|
||||||
|
output wire o_sram_wen,
|
||||||
|
output wire [aw-1:0] o_sram_raddr,
|
||||||
|
input wire [7:0] i_sram_rdata,
|
||||||
|
output wire o_sram_ren,
|
||||||
|
|
||||||
|
input wire [aw-1:2] i_wb_adr,
|
||||||
|
input wire [31:0] i_wb_dat,
|
||||||
|
input wire [3:0] i_wb_sel,
|
||||||
|
input wire i_wb_we,
|
||||||
|
input wire i_wb_stb,
|
||||||
|
output wire [31:0] o_wb_rdt,
|
||||||
|
output reg o_wb_ack);
|
||||||
|
|
||||||
|
reg [1:0] bsel;
|
||||||
|
|
||||||
|
wire wb_en = i_wb_stb & !i_wen & !o_wb_ack;
|
||||||
|
|
||||||
|
wire wb_we = i_wb_we & i_wb_sel[bsel];
|
||||||
|
|
||||||
|
wire [aw-1:0] rf_waddr = ~{{aw-rf_depth{1'b0}},i_waddr};
|
||||||
|
wire [aw-1:0] rf_raddr = ~{{aw-rf_depth{1'b0}},i_raddr};
|
||||||
|
|
||||||
|
assign o_sram_waddr = wb_en ? {i_wb_adr[aw-1:2],bsel} : rf_waddr;
|
||||||
|
assign o_sram_wdata = wb_en ? i_wb_dat[bsel*8+:8] : i_wdata;
|
||||||
|
assign o_sram_wen = wb_en ? wb_we : i_wen;
|
||||||
|
assign o_sram_raddr = wb_en ? {i_wb_adr[aw-1:2],bsel} : rf_raddr;
|
||||||
|
assign o_sram_ren = wb_en ? !i_wb_we : i_ren;
|
||||||
|
|
||||||
|
reg [23:0] wb_rdt;
|
||||||
|
assign o_wb_rdt = {i_sram_rdata, wb_rdt};
|
||||||
|
|
||||||
|
reg regzero;
|
||||||
|
always @(posedge i_clk) begin
|
||||||
|
|
||||||
|
if (wb_en) bsel <= bsel + 2'd1;
|
||||||
|
o_wb_ack <= wb_en & &bsel;
|
||||||
|
if (bsel == 2'b01) wb_rdt[7:0] <= i_sram_rdata;
|
||||||
|
if (bsel == 2'b10) wb_rdt[15:8] <= i_sram_rdata;
|
||||||
|
if (bsel == 2'b11) wb_rdt[23:16] <= i_sram_rdata;
|
||||||
|
if (i_rst) begin
|
||||||
|
bsel <= 2'd0;
|
||||||
|
o_wb_ack <= 1'b0;
|
||||||
|
end
|
||||||
|
regzero <= &i_raddr[rf_depth-1:2];
|
||||||
|
end
|
||||||
|
|
||||||
|
assign o_rdata = regzero ? 8'd0 : i_sram_rdata;
|
||||||
|
|
||||||
|
endmodule
|
||||||
Reference in New Issue
Block a user