mirror of
https://github.com/olofk/serv.git
synced 2025-04-20 03:47:09 -04:00
Add Servile convenience wrapper
Servile is a new convenience wrapper that implements common common configuration for SERV-based systems so that they don't have to be repeated in every design.
This commit is contained in:
parent
1dc37d9fd4
commit
8d91e2d288
9 changed files with 687 additions and 0 deletions
|
@ -6,4 +6,5 @@ A CPU is only as good as its eosystem. In order to make use of SERV, it needs to
|
|||
|
||||
Welcome to the reservoir, a pool of ready-made designs and subsystems for different purpsoses that you can use to quickly get started with SERV or integrate it into larger designs.
|
||||
|
||||
.. include:: servile.rst
|
||||
.. include:: servant.rst
|
||||
|
|
BIN
doc/servile.png
Normal file
BIN
doc/servile.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.4 KiB |
166
doc/servile.rst
Normal file
166
doc/servile.rst
Normal file
|
@ -0,0 +1,166 @@
|
|||
Servile : Convenience wrapper
|
||||
=============================
|
||||
|
||||
.. figure:: servile.png
|
||||
|
||||
Servile convenience wrapper
|
||||
|
||||
Servile is a helper component that takes care of common configuration and is used as a building block in the other designs and subsystems. It exposes a memory bus intended to be connected to a combined data and instruction memory, an extension bus for peripheral controllers and accelerators and an RF interface for connecting to an SRAM for GPR and CSR registers.
|
||||
|
||||
.. figure:: servile_int.png
|
||||
|
||||
Servile block diagram
|
||||
|
||||
Internally, Servile contains logic for optionally instantiating an MDU core for the M extension, an arbiter to route instruction fetches and main memory accesses through the same interface and a mux to split up the memory map into memory (0x00000000-0x3FFFFFFF) and external accesses (0x40000000-0xFFFFFFFF). The mux also contains simulation-only logic to write output to a log file and stop the simulation.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
||||
.. list-table:: Parameters
|
||||
:header-rows: 1
|
||||
:widths: 10 20 80
|
||||
|
||||
* - Parameter
|
||||
- Values
|
||||
- Description
|
||||
* - reset_pc
|
||||
- 0x00000000 (default) - 0xFFFFFFFC
|
||||
- Address of first instruction to fetch from memory after reset (Reset vector)
|
||||
* - reset_strategy
|
||||
- "MINI" (default), "NONE"
|
||||
- | 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.
|
||||
* - rf_width
|
||||
- 2 (default), 4, 8, 16, 32
|
||||
- Width of the data bus to the RF memory. Typically smaller values use less resources, but can be implementation-dependant.
|
||||
* - sim
|
||||
- 0 (default), 1
|
||||
- | Enable simulation mode. In simulation mode, two memory addresses have special purposes.
|
||||
| 0x80000000: Writes to this address puts the byte in the lowest data byte into a log file decided by the "signature" plusarg.
|
||||
| 0x90000000: Writes to this address ends the simulation.
|
||||
* - with_c
|
||||
- 0 (default), 1
|
||||
- Enable the C extension. This also makes SERV support misaligned loads and stores.
|
||||
* - with_csr
|
||||
- 0 (default), 1
|
||||
- Enable the Zicsr extension. This also enables timer IRQ and exception handling. Note that SERV only implements a small subset of the CSR registers.
|
||||
* - with_mdu
|
||||
- 0 (default), 1
|
||||
- Enables the Multiplication and Division Unit (MDU) to support the M extension. Note that this only enables the interface and the decoder logic. The MDU itself is external from SERV.
|
||||
|
||||
Signals
|
||||
-------
|
||||
|
||||
.. list-table:: Signals
|
||||
:header-rows: 1
|
||||
:widths: 30 10 5 75
|
||||
|
||||
* - Signal
|
||||
- Width
|
||||
- Direction
|
||||
- Description
|
||||
* - i_clk
|
||||
- 1
|
||||
- in
|
||||
- Clock
|
||||
* - i_rst
|
||||
- 1
|
||||
- in
|
||||
- Synchronous reset
|
||||
* - i_timer_irq
|
||||
- 1
|
||||
- in
|
||||
- Timer interrupt
|
||||
* - **Memory interface**
|
||||
-
|
||||
-
|
||||
- Connect to instruction/data memory
|
||||
* - o_wb_mem_adr
|
||||
- 32
|
||||
- out
|
||||
- Memory bus address
|
||||
* - o_wb_mem_dat
|
||||
- 32
|
||||
- out
|
||||
- Memory bus data
|
||||
* - o_wb_mem_sel
|
||||
- 4
|
||||
- out
|
||||
- Memory bus write data byte select mask
|
||||
* - o_wb_mem_we
|
||||
- 1
|
||||
- out
|
||||
- Memory bus write transaction
|
||||
* - o_wb_mem_stb
|
||||
- 1
|
||||
- out
|
||||
- Memory bus active strobe
|
||||
* - i_wb_mem_rdt
|
||||
- 32
|
||||
- in
|
||||
- Memory bus read data
|
||||
* - i_wb_mem_ack
|
||||
- 1
|
||||
- in
|
||||
- Memory bus cycle acknowledged
|
||||
* - **Extension interface**
|
||||
-
|
||||
-
|
||||
- Connect to peripheral controllers
|
||||
* - o_wb_ext_adr
|
||||
- 32
|
||||
- out
|
||||
- Data bus address
|
||||
* - o_wb_ext_dat
|
||||
- 32
|
||||
- out
|
||||
- Data bus write data
|
||||
* - o_wb_ext_sel
|
||||
- 4
|
||||
- out
|
||||
- Data bus write data byte select mask
|
||||
* - o_wb_ext_we
|
||||
- 1
|
||||
- out
|
||||
- Data bus write transaction
|
||||
* - o_wb_ext_stb
|
||||
- 1
|
||||
- out
|
||||
- Data bus active cycle
|
||||
* - i_wb_ext_rdt
|
||||
- 32
|
||||
- in
|
||||
- Data bus return data
|
||||
* - i_wb_ext_ack
|
||||
- 1
|
||||
- in
|
||||
- Data bus return data valid
|
||||
* - **RF (SRAM) interface**
|
||||
-
|
||||
-
|
||||
-
|
||||
* - o_rf_waddr
|
||||
- ceil(log2(regs*32/rf_width)
|
||||
- out
|
||||
- RF memory write address
|
||||
* - o_rf_wdata
|
||||
- rf_width
|
||||
- out
|
||||
- RF memory write data
|
||||
* - o_rf_wen
|
||||
- 1
|
||||
- out
|
||||
- RF memory write enable
|
||||
* - o_rf_raddr
|
||||
- ceil(log2(regs*32/rf_width)
|
||||
- out
|
||||
- RF memory read address
|
||||
* - i_rf_rdata
|
||||
- rf_width
|
||||
- out
|
||||
- RF memory read data
|
||||
* - o_rf_ren
|
||||
- 1
|
||||
- out
|
||||
- RF memory read enable
|
BIN
doc/servile_int.png
Normal file
BIN
doc/servile_int.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
26
servile.core
Normal file
26
servile.core
Normal file
|
@ -0,0 +1,26 @@
|
|||
CAPI=2:
|
||||
|
||||
name : ::servile:1.3.0
|
||||
|
||||
description: Convenience wrapper for SERV
|
||||
|
||||
filesets:
|
||||
rtl:
|
||||
files:
|
||||
- servile/servile_rf_mem_if.v
|
||||
- servile/servile_mux.v
|
||||
- servile/servile_arbiter.v
|
||||
- servile/servile.v
|
||||
file_type: verilogSource
|
||||
depend : [serv]
|
||||
|
||||
targets:
|
||||
default:
|
||||
filesets: [rtl]
|
||||
|
||||
lint:
|
||||
filesets: [rtl]
|
||||
flow: lint
|
||||
flow_options:
|
||||
tool: verilator
|
||||
toplevel: servile
|
273
servile/servile.v
Normal file
273
servile/servile.v
Normal file
|
@ -0,0 +1,273 @@
|
|||
/*
|
||||
* 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 reset_pc = 32'h00000000,
|
||||
parameter reset_strategy = "MINI",
|
||||
parameter rf_width = 8,
|
||||
parameter [0:0] sim = 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 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 wdata0;
|
||||
wire wdata1;
|
||||
wire [$clog2(regs)-1:0] rreg0;
|
||||
wire [$clog2(regs)-1:0] rreg1;
|
||||
wire rf_ready;
|
||||
wire rdata0;
|
||||
wire 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),
|
||||
.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
|
||||
|
||||
serv_top
|
||||
#(
|
||||
.WITH_CSR (with_csr?1:0),
|
||||
.PRE_REGISTER (1'b1),
|
||||
.RESET_STRATEGY (reset_strategy),
|
||||
.RESET_PC (reset_pc),
|
||||
.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
servile/servile_arbiter.v
Normal file
45
servile/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
|
99
servile/servile_mux.v
Normal file
99
servile/servile_mux.v
Normal file
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* 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
|
||||
|
||||
assign sig_en = 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;
|
||||
integer f = 0;
|
||||
|
||||
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;
|
||||
always @(*) sim_ack = 1'b0;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
77
servile/servile_rf_mem_if.v
Normal file
77
servile/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
|
Loading…
Add table
Add a link
Reference in a new issue