mirror of
https://github.com/olofk/serv.git
synced 2025-04-20 03:47:09 -04:00
Compare commits
No commits in common. "main" and "1.3.0" have entirely different histories.
39 changed files with 230 additions and 861 deletions
2
.github/workflows/formal.yml
vendored
2
.github/workflows/formal.yml
vendored
|
@ -14,7 +14,7 @@ jobs:
|
|||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: cores/serv/serv-src
|
||||
- uses: YosysHQ/setup-oss-cad-suite@v3
|
||||
- uses: YosysHQ/setup-oss-cad-suite@v2
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Prepare formal tests
|
||||
|
|
22
.github/workflows/openlane.yml
vendored
22
.github/workflows/openlane.yml
vendored
|
@ -2,23 +2,19 @@ name: Build GDS using OpenLANE and sky130 PDK
|
|||
|
||||
on: [push]
|
||||
jobs:
|
||||
build-openlane-sky130:
|
||||
build-openlane:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
REPO : serv
|
||||
VLNV : serv
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
- name: Checkout subservient
|
||||
uses: actions/checkout@v4
|
||||
- name: Build with Openlane
|
||||
uses: librecores/ci-fusesoc-action@migrate-dockerized
|
||||
with:
|
||||
path: serv
|
||||
- run: echo "EDALIZE_LAUNCHER=el_docker" >> $GITHUB_ENV
|
||||
- run: pip3 install fusesoc
|
||||
- run: fusesoc library add $REPO $GITHUB_WORKSPACE/$REPO
|
||||
- run: fusesoc run --target=sky130 $VLNV
|
||||
- run: find -name *.gds
|
||||
core: serv
|
||||
target: sky130
|
||||
tool: openlane
|
||||
- name: Store artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: serv.gds
|
||||
path: /home/runner/work/serv/serv/serv/build/serv_1.3.0/sky130-openlane/runs/serv_synth_wrapper/results/final/gds/serv_synth_wrapper.gds
|
||||
path: /home/runner/work/serv/serv/build/serv_1.3.0/sky130-openlane/gds/serv_synth_wrapper.gds
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# SERV
|
||||
|
||||
[](https://gitter.im/librecores/serv?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://github.com/olofk/serv/actions/workflows/ci.yml)
|
||||
[](https://github.com/olofk/serv/actions?query=workflow%3ACI)
|
||||
[](https://serv.readthedocs.io/en/latest/?badge=latest)
|
||||
|
||||
SERV is an award-winning bit-serial RISC-V core
|
||||
|
@ -158,7 +158,7 @@ This will synthesize for the default Vivado part. To synthesise for a specific d
|
|||
|
||||
SERV, or rather the Servant SoC, can run the [Zephyr RTOS](https://www.zephyrproject.org). The Servant-specific drivers and BSP is located in the zephyr subdirectory of the SERV repository. In order to use Zephyr on Servant, a project directory structure must be set up that allows Zephyr to load the Servant-specific files as a module.
|
||||
|
||||
First, the Zephyr SDK and the "west" build tool must be installed. The [Zephyr getting started guide](https://docs.zephyrproject.org/latest/getting_started/index.html) describes these steps in more detail.
|
||||
First, the Zephyr SDK and the "west" build too must be installed. The [Zephyr getting started guide](https://docs.zephyrproject.org/latest/getting_started/index.html) describes these steps in more detail.
|
||||
|
||||
Assuming that SERV was installed into `$WORKSPACE/fusesoc_libraries/serv` as per the prerequisites, run the following command to make the workspace also work as a Zephyr workspace.
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ module servant_sim
|
|||
|
||||
parameter memfile = "";
|
||||
parameter memsize = 8192;
|
||||
parameter width = 1;
|
||||
parameter with_csr = 1;
|
||||
parameter compressed = 0;
|
||||
parameter align = compressed;
|
||||
|
@ -23,8 +22,6 @@ module servant_sim
|
|||
servant
|
||||
#(.memfile (memfile),
|
||||
.memsize (memsize),
|
||||
.width (width),
|
||||
.debug (1'b1),
|
||||
.sim (1),
|
||||
.with_csr (with_csr),
|
||||
.compress (compressed[0:0]),
|
||||
|
|
|
@ -154,7 +154,7 @@ int main(int argc, char **argv, char **env)
|
|||
do_gpio(&gpio_context, top->q);
|
||||
}
|
||||
if (tf && top->wb_clk && top->pc_vld)
|
||||
if (write(tf, (void *)&top->pc_adr, 4) < 0) exit(1);
|
||||
write(tf, (void *)&top->pc_adr, 4);
|
||||
if (timeout && (main_time >= timeout)) {
|
||||
printf("Timeout: Exiting at time %lu\n", main_time);
|
||||
done = true;
|
||||
|
|
|
@ -3,13 +3,8 @@ module servant_tb;
|
|||
|
||||
parameter memfile = "hello_uart.hex";
|
||||
parameter memsize = 8192;
|
||||
parameter width = 1;
|
||||
parameter with_csr = 1;
|
||||
|
||||
localparam baud_rate =
|
||||
(width == 4) ? 57600*3 :
|
||||
57600;
|
||||
|
||||
reg wb_clk = 1'b0;
|
||||
reg wb_rst = 1'b1;
|
||||
|
||||
|
@ -20,12 +15,11 @@ module servant_tb;
|
|||
|
||||
vlog_tb_utils vtu();
|
||||
|
||||
uart_decoder #(baud_rate) uart_decoder (q);
|
||||
uart_decoder #(57600) uart_decoder (q);
|
||||
|
||||
servant_sim
|
||||
#(.memfile (memfile),
|
||||
.memsize (memsize),
|
||||
.width (width),
|
||||
.with_csr (with_csr))
|
||||
dut
|
||||
(.wb_clk (wb_clk),
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
## Clock signal
|
||||
set_property -dict { PACKAGE_PIN J3 IOSTANDARD LVCMOS18 } [get_ports i_clk];
|
||||
create_clock -add -name sys_clk_pin -period 40.00 [get_ports i_clk];
|
||||
|
||||
## LED 0
|
||||
set_property -dict { PACKAGE_PIN P1 IOSTANDARD LVCMOS18 } [get_ports o_led_0];
|
||||
|
||||
# PMOD A, Connector J5
|
||||
# Connector pin, Package pin, PMOD type 4 UART
|
||||
# 1, F8, CTS
|
||||
# 2, F7, TXD
|
||||
# 3, E6, RXD
|
||||
# 4, E5, RTS
|
||||
# 5, GND
|
||||
# 6, VCC
|
||||
# 7, G6,
|
||||
# 8, G5,
|
||||
# 9, C8,
|
||||
# 10, C7,
|
||||
# 11, GND
|
||||
# 12, VCC
|
||||
set_property -dict { PACKAGE_PIN F7 IOSTANDARD LVCMOS33 } [get_ports o_uart_tx]
|
|
@ -1,12 +1,14 @@
|
|||
`verilator_config
|
||||
// Bits [1:0] in i_wb_rdt are not used at all
|
||||
lint_off -rule UNUSED -file "*/serv_top.v" -lines 179
|
||||
lint_off -rule UNUSED -file "*/serv_top.v" -lines 178
|
||||
|
||||
//Some bits in the instruction word are not used in serv_decode but it's easier
|
||||
//to just send in the whole word than picking out bits
|
||||
lint_off -rule UNUSED -file "*/serv_decode.v" -lines 8
|
||||
|
||||
lint_off -rule UNUSED -file "*/serv_top.v" -lines 177
|
||||
|
||||
//Some variables are only used when we connect an Extension with serv_decode
|
||||
lint_off -rule UNUSED -file "*/serv_top.v" -lines 70
|
||||
lint_off -rule UNUSED -file "*/serv_top.v" -lines 67
|
||||
|
||||
|
||||
|
|
|
@ -2,5 +2,4 @@
|
|||
Datasheet
|
||||
*********
|
||||
|
||||
.. include:: overview.rst
|
||||
.. include:: interface.rst
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
Interface
|
||||
=========
|
||||
|
||||
Top level
|
||||
---------
|
||||
|
||||
Users of SERV can choose to use either serv_top or serv_rf_top depending on what best fits the application. serv_top contains all the main logic of SERV except for the actual storage for the register file (RF).
|
||||
|
||||
.. image:: serv_top.png
|
||||
|
@ -194,29 +191,3 @@ Signals
|
|||
- 1
|
||||
- in
|
||||
- RF interface channel 1 read data
|
||||
|
||||
Extension interface
|
||||
-------------------
|
||||
|
||||
The SERV CPU, being the smallest RISC-V CPU, has a design that is primarily focused on simplicity and minimalism. However, to increase its utility without complicating the core design, it can be extended using an extension interface. The extension interface allows additional functionality to be added to the SERV CPU core through custom accelerators that are called for when specific instructions are encountered. SERV has built-in support for connecting an MDU (Multiplication/Division Unit) that implements the M ISA extension by setting the MDU parameter. Other accelerators need changes to the decoder.
|
||||
|
||||
When SERV detects instructions to be executed by an external accelerator through the extension interface, it will treat them as :ref:`two-stage operations`. In stage 1, the values in `o_ext_rs1` and `o_ext_rs2` are prepared to be sent to the accelerator. Once stage 1 is completed, SERV will assert the corresponding valid signal for the accelerator (e.g. `o_mdu_valid` for the M extension accelerator). The accelerator can now perform its work and when it has completed its result it will return that value in `i_ext_rd` and strobe `i_ext_ready` for one cycle. The following cycle, SERV will start stage two and store the received result. The waveform below explains this in more detail.
|
||||
|
||||
.. wavedrom::
|
||||
|
||||
{ signal: [
|
||||
{ name: "clk" , wave: "P...|...|...|..."},
|
||||
{ name: "init" , wave: "1...|..0|...|...", node: ".......d..", data: "r0"},
|
||||
{ name: "o_rf_wreq" , wave: "0...|...|10.|...", node: ".........g", data: "r1"},
|
||||
{ name: "i_rf_ready" , wave: "010.|...|10.|...", node: ".a.......h.", data: "r1"},
|
||||
{ name: "cnt_en" , wave: "0.1.|..0|.1.|..0", node: "..b.......i"},
|
||||
{ name: "cnt_done" , wave: "0...|.10|...|.10", node: "......c.."},
|
||||
{ name: "o_ext_rs1" , wave: ".234567x|...|...", node: "..", data: "d0 d1 ... d30 d31"},
|
||||
{ name: "o_ext_rs2" , wave: ".234567x|...|...", node: "..", data: "d0 d1 ... d30 d31"},
|
||||
{ name: "o_mdu_valid", wave: "0...|..1|.0.|...", node: ".......e", data: "0 1 ... 30 31"},
|
||||
{ name: "i_ext_ready", wave: "0...|...|10.|...", node: ".........f", data: "0 1 ... 30 31"},
|
||||
{ name: "i_ext_rd" , wave: "....|...|234567x", node: "..", data: "d0 d1 ... d30 d31"},
|
||||
],
|
||||
edge : [
|
||||
"a~>b", "c~>d", "e~>f", "f~>g", "h~>i"]
|
||||
}
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
Overview
|
||||
========
|
||||
|
||||
The SERV RISC-V CPU is an award-winning and highly compact processor core based on the RISC-V instruction set architecture (ISA). It is designed to be the smallest possible RISC-V compliant CPU and is particularly well-suited for embedded systems and applications where silicon area is critical.
|
||||
|
||||
Key Features
|
||||
------------
|
||||
|
||||
* **ISA:** RISC-V RV32IZifencei
|
||||
* **Optional ISA extensions:** C, M, Zicsr
|
||||
* **Optional features:** Timer interrupts, Extension interface
|
||||
* **Architecture:** Bit-serial (one bit processed per clock cycle)
|
||||
* **License:** ISC (available under other commercial licenses upon request)
|
||||
* **OS support:** Zephyr 3.7
|
||||
* **SW support:** Compatible with standard RISC-V toolchains
|
||||
* **Area:** Smallest RISC-V core available
|
||||
|
||||
Applications
|
||||
------------
|
||||
|
||||
* **Embedded Systems:** Ideal for minimalistic embedded control tasks
|
||||
* **IoT Devices:** Suitable for Internet of Things devices where space and power are limited
|
||||
* **Education:** Excellent resource for teaching and understanding the RISC-V architecture and CPU design
|
||||
* **Research:** Platform for research in minimalistic computing designs and for bringing up new fabrication processes
|
||||
|
||||
Area
|
||||
----
|
||||
|
||||
.. list-table:: Area for minimal configuration [#]_
|
||||
:widths: 25 25 25 25
|
||||
:header-rows: 1
|
||||
|
||||
* - Lattice iCE40
|
||||
- Altera Cyclone10LP
|
||||
- AMD Artix-7
|
||||
- CMOS
|
||||
* - 198LUT/164FF
|
||||
- 239LUT/164FF
|
||||
- 125LUT/164FF
|
||||
- 2.1kGE
|
||||
|
||||
.. [#] Excluding register file
|
|
@ -9,4 +9,3 @@ Welcome to the reservoir, a pool of ready-made designs and subsystems for differ
|
|||
.. include:: servile.rst
|
||||
.. include:: serving.rst
|
||||
.. include:: servant.rst
|
||||
.. include:: subservient.rst
|
||||
|
|
|
@ -184,7 +184,7 @@ Pin B1 is used for UART output with 115200 baud rate. The serial port on Kolibri
|
|||
ldprog -Ks build/servant_1.3.0/machdyne_kolibri-icestorm/servant_1.3.0.bin
|
||||
|
||||
MAX10 10M08 Evaluation Kit
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
FPGA Pin 75 (Arduino_IO01 J5 pin 7) is used for UART output with 57600 baud rate. SW1 is reset and Led 1 q output.
|
||||
|
||||
|
@ -248,13 +248,6 @@ FPGA Pin F14 (HSTC GPIO addon connector J2, pin 2) is used for UART output with
|
|||
|
||||
fusesoc run --target=sockit servant
|
||||
|
||||
Trenz Electronic TE0802
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
PMOD A marked J5, pin two, on the board is used for UART output with 115200 baud rate.
|
||||
|
||||
fusesoc run --target=te0802 servant
|
||||
|
||||
TinyFPGA BX
|
||||
^^^^^^^^^^^
|
||||
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 8.6 KiB |
|
@ -1,10 +0,0 @@
|
|||
Subservient : SERV ASIC macro
|
||||
=============================
|
||||
|
||||
.. figure:: subservient.png
|
||||
|
||||
Subservient ASIC macro
|
||||
|
||||
`Subservient <https://github.com/olofk/subservient>`_ is a minimal reference system that just requires connecting one single-port SRAM for data, instructions and RF. It is intended to make ASIC integration easier.
|
||||
|
||||
|
|
@ -4,12 +4,11 @@ module serv_bufreg2
|
|||
//State
|
||||
input wire i_en,
|
||||
input wire i_init,
|
||||
input wire i_cnt7,
|
||||
input wire i_cnt_done,
|
||||
input wire i_sh_right,
|
||||
input wire [1:0] i_lsb,
|
||||
input wire [1:0] i_bytecnt,
|
||||
input wire i_byte_valid,
|
||||
output wire o_sh_done,
|
||||
output wire o_sh_done_r,
|
||||
//Control
|
||||
input wire i_op_b_sel,
|
||||
input wire i_shift_op,
|
||||
|
@ -25,46 +24,30 @@ module serv_bufreg2
|
|||
|
||||
reg [31:0] dat;
|
||||
|
||||
/*
|
||||
Before a store operation, the data to be written needs to be shifted into
|
||||
place. Depending on the address alignment, we need to shift different
|
||||
amounts. One formula for calculating this is to say that we shift when
|
||||
i_lsb + i_bytecnt < 4. Unfortunately, the synthesis tools don't seem to be
|
||||
clever enough so the hideous expression below is used to achieve the same
|
||||
thing in a more optimal way.
|
||||
*/
|
||||
wire byte_valid
|
||||
= (!i_lsb[0] & !i_lsb[1]) |
|
||||
(!i_bytecnt[0] & !i_bytecnt[1]) |
|
||||
(!i_bytecnt[1] & !i_lsb[1]) |
|
||||
(!i_bytecnt[1] & !i_lsb[0]) |
|
||||
(!i_bytecnt[0] & !i_lsb[1]);
|
||||
|
||||
assign o_op_b = i_op_b_sel ? i_rs2 : i_imm;
|
||||
|
||||
wire shift_en = i_shift_op ? (i_en & i_init & (i_bytecnt == 2'b00)) : (i_en & byte_valid);
|
||||
|
||||
wire cnt_en = (i_shift_op & (!i_init | (i_cnt_done & i_sh_right)));
|
||||
wire dat_en = i_shift_op | (i_en & i_byte_valid);
|
||||
|
||||
/* The dat register has three different use cases for store, load and
|
||||
shift operations.
|
||||
store : Data to be written is shifted to the correct position in dat during
|
||||
init by shift_en and is presented on the data bus as o_wb_dat
|
||||
init by dat_en and is presented on the data bus as o_wb_dat
|
||||
load : Data from the bus gets latched into dat during i_wb_ack and is then
|
||||
shifted out at the appropriate time to end up in the correct
|
||||
position in rd
|
||||
shift : Data is shifted in during init. After that, the six LSB are used as
|
||||
a downcounter (with bit 5 initially set to 0) that trigger
|
||||
o_sh_done when they wrap around to indicate that
|
||||
a downcounter (with bit 5 initially set to 0) that triggers
|
||||
o_sh_done and o_sh_done_r when they wrap around to indicate that
|
||||
the requested number of shifts have been performed
|
||||
*/
|
||||
wire [5:0] dat_shamt = cnt_en ?
|
||||
wire [5:0] dat_shamt = (i_shift_op & !i_init) ?
|
||||
//Down counter mode
|
||||
dat[29:24]-1 :
|
||||
dat[5:0]-1 :
|
||||
//Shift reg mode with optional clearing of bit 5
|
||||
{dat[30] & !(i_shift_op & i_cnt7),dat[29:25]};
|
||||
{dat[6] & !(i_shift_op & i_cnt_done),dat[5:1]};
|
||||
|
||||
assign o_sh_done = dat_shamt[5];
|
||||
assign o_sh_done_r = dat[5];
|
||||
|
||||
assign o_q =
|
||||
((i_lsb == 2'd3) & dat[24]) |
|
||||
|
@ -75,8 +58,8 @@ module serv_bufreg2
|
|||
assign o_dat = dat;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (shift_en | cnt_en | i_load)
|
||||
dat <= i_load ? i_dat : {o_op_b, dat[31], dat_shamt, dat[24:1]};
|
||||
if (dat_en | i_load)
|
||||
dat <= i_load ? i_dat : {o_op_b, dat[31:7], dat_shamt};
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -14,8 +14,6 @@ module serv_csr
|
|||
input wire i_cnt0to3,
|
||||
input wire i_cnt3,
|
||||
input wire i_cnt7,
|
||||
input wire i_cnt11,
|
||||
input wire i_cnt12,
|
||||
input wire i_cnt_done,
|
||||
input wire i_mem_op,
|
||||
input wire i_mtip,
|
||||
|
@ -65,17 +63,7 @@ module serv_csr
|
|||
(i_csr_source == CSR_SOURCE_CSR) ? csr_out :
|
||||
{W{1'bx}};
|
||||
|
||||
wire [B:0] mstatus;
|
||||
|
||||
generate
|
||||
if (W==1) begin : gen_mstatus_w1
|
||||
assign mstatus = ((mstatus_mie & i_cnt3) | (i_cnt11 | i_cnt12));
|
||||
end else if (W==4) begin : gen_mstatus_w4
|
||||
assign mstatus = {i_cnt11 | (mstatus_mie & i_cnt3), 2'b00, i_cnt12};
|
||||
end
|
||||
endgenerate
|
||||
|
||||
assign csr_out = ({W{i_mstatus_en & i_en}} & mstatus) |
|
||||
assign csr_out = ({i_mstatus_en & mstatus_mie & i_cnt3 & i_en,{B{1'b0}}}) |
|
||||
i_rf_csr_out |
|
||||
({W{i_mcause_en & i_en}} & mcause);
|
||||
|
||||
|
|
345
rtl/serv_debug.v
345
rtl/serv_debug.v
|
@ -1,345 +0,0 @@
|
|||
module serv_debug
|
||||
#(parameter W = 1,
|
||||
parameter RESET_PC = 0,
|
||||
//Internally calculated. Do not touch
|
||||
parameter B=W-1)
|
||||
(
|
||||
`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, // Not used
|
||||
output reg rvfi_intr = 1'b0, // Not used
|
||||
output reg [1:0] rvfi_mode = 2'b11, // Not used
|
||||
output reg [1:0] rvfi_ixl = 2'b01, // Not used
|
||||
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 wire [31:0] rvfi_rd_wdata,
|
||||
output reg [31:0] rvfi_pc_rdata,
|
||||
output wire [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,
|
||||
input wire [31:0] i_dbus_adr,
|
||||
input wire [31:0] i_dbus_dat,
|
||||
input wire [3:0] i_dbus_sel,
|
||||
input wire i_dbus_we,
|
||||
input wire [31:0] i_dbus_rdt,
|
||||
input wire i_dbus_ack,
|
||||
input wire i_ctrl_pc_en,
|
||||
input wire [B:0] rs1,
|
||||
input wire [B:0] rs2,
|
||||
input wire [4:0] rs1_addr,
|
||||
input wire [4:0] rs2_addr,
|
||||
input wire [3:0] immdec_en,
|
||||
input wire rd_en,
|
||||
input wire trap,
|
||||
input wire i_rf_ready,
|
||||
input wire i_ibus_cyc,
|
||||
input wire two_stage_op,
|
||||
input wire init,
|
||||
input wire [31:0] i_ibus_adr,
|
||||
`endif
|
||||
input wire i_clk,
|
||||
input wire i_rst,
|
||||
input wire [31:0] i_ibus_rdt,
|
||||
input wire i_ibus_ack,
|
||||
input wire [4:0] i_rd_addr,
|
||||
input wire i_cnt_en,
|
||||
input wire [B:0] i_csr_in,
|
||||
input wire i_csr_mstatus_en,
|
||||
input wire i_csr_mie_en,
|
||||
input wire i_csr_mcause_en,
|
||||
input wire i_csr_en,
|
||||
input wire [1:0] i_csr_addr,
|
||||
input wire i_wen0,
|
||||
input wire [B:0] i_wdata0,
|
||||
input wire i_cnt_done);
|
||||
|
||||
reg update_rd = 1'b0;
|
||||
reg update_mscratch;
|
||||
reg update_mtvec;
|
||||
reg update_mepc;
|
||||
reg update_mtval;
|
||||
reg update_mstatus;
|
||||
reg update_mie;
|
||||
reg update_mcause;
|
||||
|
||||
reg [31:0] dbg_rd = 32'hxxxxxxxx;
|
||||
reg [31:0] dbg_csr = 32'hxxxxxxxx;
|
||||
reg [31:0] dbg_mstatus = 32'hxxxxxxxx;
|
||||
reg [31:0] dbg_mie = 32'hxxxxxxxx;
|
||||
reg [31:0] dbg_mcause = 32'hxxxxxxxx;
|
||||
reg [31:0] dbg_mscratch = 32'hxxxxxxxx;
|
||||
reg [31:0] dbg_mtvec = 32'hxxxxxxxx;
|
||||
reg [31:0] dbg_mepc = 32'hxxxxxxxx;
|
||||
reg [31:0] dbg_mtval = 32'hxxxxxxxx;
|
||||
reg [31:0] x1 = 32'hxxxxxxxx;
|
||||
reg [31:0] x2 = 32'hxxxxxxxx;
|
||||
reg [31:0] x3 = 32'hxxxxxxxx;
|
||||
reg [31:0] x4 = 32'hxxxxxxxx;
|
||||
reg [31:0] x5 = 32'hxxxxxxxx;
|
||||
reg [31:0] x6 = 32'hxxxxxxxx;
|
||||
reg [31:0] x7 = 32'hxxxxxxxx;
|
||||
reg [31:0] x8 = 32'hxxxxxxxx;
|
||||
reg [31:0] x9 = 32'hxxxxxxxx;
|
||||
reg [31:0] x10 = 32'hxxxxxxxx;
|
||||
reg [31:0] x11 = 32'hxxxxxxxx;
|
||||
reg [31:0] x12 = 32'hxxxxxxxx;
|
||||
reg [31:0] x13 = 32'hxxxxxxxx;
|
||||
reg [31:0] x14 = 32'hxxxxxxxx;
|
||||
reg [31:0] x15 = 32'hxxxxxxxx;
|
||||
reg [31:0] x16 = 32'hxxxxxxxx;
|
||||
reg [31:0] x17 = 32'hxxxxxxxx;
|
||||
reg [31:0] x18 = 32'hxxxxxxxx;
|
||||
reg [31:0] x19 = 32'hxxxxxxxx;
|
||||
reg [31:0] x20 = 32'hxxxxxxxx;
|
||||
reg [31:0] x21 = 32'hxxxxxxxx;
|
||||
reg [31:0] x22 = 32'hxxxxxxxx;
|
||||
reg [31:0] x23 = 32'hxxxxxxxx;
|
||||
reg [31:0] x24 = 32'hxxxxxxxx;
|
||||
reg [31:0] x25 = 32'hxxxxxxxx;
|
||||
reg [31:0] x26 = 32'hxxxxxxxx;
|
||||
reg [31:0] x27 = 32'hxxxxxxxx;
|
||||
reg [31:0] x28 = 32'hxxxxxxxx;
|
||||
reg [31:0] x29 = 32'hxxxxxxxx;
|
||||
reg [31:0] x30 = 32'hxxxxxxxx;
|
||||
reg [31:0] x31 = 32'hxxxxxxxx;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
update_rd <= i_cnt_done & i_wen0;
|
||||
|
||||
if (i_wen0)
|
||||
dbg_rd <= {i_wdata0,dbg_rd[31:W]};
|
||||
|
||||
//End of instruction that writes to RF
|
||||
if (update_rd) begin
|
||||
case (i_rd_addr)
|
||||
5'd1 : x1 <= dbg_rd;
|
||||
5'd2 : x2 <= dbg_rd;
|
||||
5'd3 : x3 <= dbg_rd;
|
||||
5'd4 : x4 <= dbg_rd;
|
||||
5'd5 : x5 <= dbg_rd;
|
||||
5'd6 : x6 <= dbg_rd;
|
||||
5'd7 : x7 <= dbg_rd;
|
||||
5'd8 : x8 <= dbg_rd;
|
||||
5'd9 : x9 <= dbg_rd;
|
||||
5'd10 : x10 <= dbg_rd;
|
||||
5'd11 : x11 <= dbg_rd;
|
||||
5'd12 : x12 <= dbg_rd;
|
||||
5'd13 : x13 <= dbg_rd;
|
||||
5'd14 : x14 <= dbg_rd;
|
||||
5'd15 : x15 <= dbg_rd;
|
||||
5'd16 : x16 <= dbg_rd;
|
||||
5'd17 : x17 <= dbg_rd;
|
||||
5'd18 : x18 <= dbg_rd;
|
||||
5'd19 : x19 <= dbg_rd;
|
||||
5'd20 : x20 <= dbg_rd;
|
||||
5'd21 : x21 <= dbg_rd;
|
||||
5'd22 : x22 <= dbg_rd;
|
||||
5'd23 : x23 <= dbg_rd;
|
||||
5'd24 : x24 <= dbg_rd;
|
||||
5'd25 : x25 <= dbg_rd;
|
||||
5'd26 : x26 <= dbg_rd;
|
||||
5'd27 : x27 <= dbg_rd;
|
||||
5'd28 : x28 <= dbg_rd;
|
||||
5'd29 : x29 <= dbg_rd;
|
||||
5'd30 : x30 <= dbg_rd;
|
||||
5'd31 : x31 <= dbg_rd;
|
||||
default : ;
|
||||
endcase
|
||||
end
|
||||
|
||||
update_mscratch <= i_cnt_done & i_csr_en & (i_csr_addr == 2'b00);
|
||||
update_mtvec <= i_cnt_done & i_csr_en & (i_csr_addr == 2'b01);
|
||||
update_mepc <= i_cnt_done & i_csr_en & (i_csr_addr == 2'b10);
|
||||
update_mtval <= i_cnt_done & i_csr_en & (i_csr_addr == 2'b11);
|
||||
update_mstatus <= i_cnt_done & i_csr_mstatus_en;
|
||||
update_mie <= i_cnt_done & i_csr_mie_en;
|
||||
update_mcause <= i_cnt_done & i_csr_mcause_en;
|
||||
|
||||
if (i_cnt_en)
|
||||
dbg_csr <= {i_csr_in, dbg_csr[31:W]};
|
||||
|
||||
if (update_mscratch) dbg_mscratch <= dbg_csr;
|
||||
if (update_mtvec) dbg_mtvec <= dbg_csr;
|
||||
if (update_mepc ) dbg_mepc <= dbg_csr;
|
||||
if (update_mtval) dbg_mtval <= dbg_csr;
|
||||
if (update_mstatus) dbg_mstatus <= dbg_csr;
|
||||
if (update_mie) dbg_mie <= dbg_csr;
|
||||
if (update_mcause) dbg_mcause <= dbg_csr;
|
||||
end
|
||||
|
||||
reg LUI, AUIPC, JAL, JALR, BEQ, BNE, BLT, BGE, BLTU, BGEU, LB, LH, LW, LBU, LHU, SB, SH, SW, ADDI, SLTI, SLTIU, XORI, ORI, ANDI,SLLI, SRLI, SRAI, ADD, SUB, SLL, SLT, SLTU, XOR, SRL, SRA, OR, AND, FENCE, ECALL, EBREAK;
|
||||
reg CSRRW, CSRRS, CSRRC, CSRRWI, CSRRSI, CSRRCI;
|
||||
reg OTHER;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_ibus_ack) begin
|
||||
LUI <= 1'b0;
|
||||
AUIPC <= 1'b0;
|
||||
JAL <= 1'b0;
|
||||
JALR <= 1'b0;
|
||||
BEQ <= 1'b0;
|
||||
BNE <= 1'b0;
|
||||
BLT <= 1'b0;
|
||||
BGE <= 1'b0;
|
||||
BLTU <= 1'b0;
|
||||
BGEU <= 1'b0;
|
||||
LB <= 1'b0;
|
||||
LH <= 1'b0;
|
||||
LW <= 1'b0;
|
||||
LBU <= 1'b0;
|
||||
LHU <= 1'b0;
|
||||
SB <= 1'b0;
|
||||
SH <= 1'b0;
|
||||
SW <= 1'b0;
|
||||
ADDI <= 1'b0;
|
||||
SLTI <= 1'b0;
|
||||
SLTIU <= 1'b0;
|
||||
XORI <= 1'b0;
|
||||
ORI <= 1'b0;
|
||||
ANDI <= 1'b0;
|
||||
SLLI <= 1'b0;
|
||||
SRLI <= 1'b0;
|
||||
SRAI <= 1'b0;
|
||||
ADD <= 1'b0;
|
||||
SUB <= 1'b0;
|
||||
SLL <= 1'b0;
|
||||
SLT <= 1'b0;
|
||||
SLTU <= 1'b0;
|
||||
XOR <= 1'b0;
|
||||
SRL <= 1'b0;
|
||||
SRA <= 1'b0;
|
||||
OR <= 1'b0;
|
||||
AND <= 1'b0;
|
||||
FENCE <= 1'b0;
|
||||
ECALL <= 1'b0;
|
||||
EBREAK <= 1'b0;
|
||||
CSRRW <= 1'b0;
|
||||
CSRRS <= 1'b0;
|
||||
CSRRC <= 1'b0;
|
||||
CSRRWI <= 1'b0;
|
||||
CSRRSI <= 1'b0;
|
||||
CSRRCI <= 1'b0;
|
||||
OTHER <= 1'b0;
|
||||
|
||||
casez(i_ibus_rdt)
|
||||
// 3322222_22222 11111_111 11
|
||||
// 1098765_43210 98765_432 10987_65432_10
|
||||
32'b???????_?????_?????_???_?????_01101_11 : LUI <= 1'b1;
|
||||
32'b???????_?????_?????_???_?????_00101_11 : AUIPC <= 1'b1;
|
||||
32'b???????_?????_?????_???_?????_11011_11 : JAL <= 1'b1;
|
||||
32'b???????_?????_?????_000_?????_11001_11 : JALR <= 1'b1;
|
||||
32'b???????_?????_?????_000_?????_11000_11 : BEQ <= 1'b1;
|
||||
32'b???????_?????_?????_001_?????_11000_11 : BNE <= 1'b1;
|
||||
32'b???????_?????_?????_100_?????_11000_11 : BLT <= 1'b1;
|
||||
32'b???????_?????_?????_101_?????_11000_11 : BGE <= 1'b1;
|
||||
32'b???????_?????_?????_110_?????_11000_11 : BLTU <= 1'b1;
|
||||
32'b???????_?????_?????_111_?????_11000_11 : BGEU <= 1'b1;
|
||||
32'b???????_?????_?????_000_?????_00000_11 : LB <= 1'b1;
|
||||
32'b???????_?????_?????_001_?????_00000_11 : LH <= 1'b1;
|
||||
32'b???????_?????_?????_010_?????_00000_11 : LW <= 1'b1;
|
||||
32'b???????_?????_?????_100_?????_00000_11 : LBU <= 1'b1;
|
||||
32'b???????_?????_?????_101_?????_00000_11 : LHU <= 1'b1;
|
||||
32'b???????_?????_?????_000_?????_01000_11 : SB <= 1'b1;
|
||||
32'b???????_?????_?????_001_?????_01000_11 : SH <= 1'b1;
|
||||
32'b???????_?????_?????_010_?????_01000_11 : SW <= 1'b1;
|
||||
32'b???????_?????_?????_000_?????_00100_11 : ADDI <= 1'b1;
|
||||
32'b???????_?????_?????_010_?????_00100_11 : SLTI <= 1'b1;
|
||||
32'b???????_?????_?????_011_?????_00100_11 : SLTIU <= 1'b1;
|
||||
32'b???????_?????_?????_100_?????_00100_11 : XORI <= 1'b1;
|
||||
32'b???????_?????_?????_110_?????_00100_11 : ORI <= 1'b1;
|
||||
32'b???????_?????_?????_111_?????_00100_11 : ANDI <= 1'b1;
|
||||
32'b0000000_?????_?????_001_?????_00100_11 : SLLI <= 1'b1;
|
||||
32'b0000000_?????_?????_101_?????_00100_11 : SRLI <= 1'b1;
|
||||
32'b0100000_?????_?????_101_?????_00100_11 : SRAI <= 1'b1;
|
||||
32'b0000000_?????_?????_000_?????_01100_11 : ADD <= 1'b1;
|
||||
32'b0100000_?????_?????_000_?????_01100_11 : SUB <= 1'b1;
|
||||
32'b0000000_?????_?????_001_?????_01100_11 : SLL <= 1'b1;
|
||||
32'b0000000_?????_?????_010_?????_01100_11 : SLT <= 1'b1;
|
||||
32'b0000000_?????_?????_011_?????_01100_11 : SLTU <= 1'b1;
|
||||
32'b???????_?????_?????_100_?????_01100_11 : XOR <= 1'b1;
|
||||
32'b0000000_?????_?????_101_?????_01100_11 : SRL <= 1'b1;
|
||||
32'b0100000_?????_?????_101_?????_01100_11 : SRA <= 1'b1;
|
||||
32'b???????_?????_?????_110_?????_01100_11 : OR <= 1'b1;
|
||||
32'b???????_?????_?????_111_?????_01100_11 : AND <= 1'b1;
|
||||
32'b???????_?????_?????_000_?????_00011_11 : FENCE <= 1'b1;
|
||||
32'b0000000_00000_00000_000_00000_11100_11 : ECALL <= 1'b1;
|
||||
32'b0000000_00001_00000_000_00000_11100_11 : EBREAK <= 1'b1;
|
||||
32'b???????_?????_?????_001_?????_11100_11 : CSRRW <= 1'b1;
|
||||
32'b???????_?????_?????_010_?????_11100_11 : CSRRS <= 1'b1;
|
||||
32'b???????_?????_?????_011_?????_11100_11 : CSRRC <= 1'b1;
|
||||
32'b???????_?????_?????_101_?????_11100_11 : CSRRWI <= 1'b1;
|
||||
32'b???????_?????_?????_110_?????_11100_11 : CSRRSI <= 1'b1;
|
||||
32'b???????_?????_?????_111_?????_11100_11 : CSRRCI <= 1'b1;
|
||||
default : OTHER <= 1'b1;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
`ifdef RISCV_FORMAL
|
||||
reg [31:0] pc = RESET_PC;
|
||||
|
||||
wire rs_en = two_stage_op ? init : i_ctrl_pc_en;
|
||||
|
||||
assign rvfi_rd_wdata = update_rd ? dbg_rd : 32'd0;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
/* End of instruction */
|
||||
rvfi_valid <= i_cnt_done & i_ctrl_pc_en & !i_rst;
|
||||
rvfi_order <= rvfi_order + {63'd0,rvfi_valid};
|
||||
|
||||
/* Get instruction word when it's fetched from ibus */
|
||||
if (i_ibus_cyc & i_ibus_ack)
|
||||
rvfi_insn <= i_ibus_rdt;
|
||||
|
||||
|
||||
if (i_cnt_done & i_ctrl_pc_en) begin
|
||||
rvfi_pc_rdata <= pc;
|
||||
if (!(rd_en & (|i_rd_addr))) begin
|
||||
rvfi_rd_addr <= 5'd0;
|
||||
end
|
||||
end
|
||||
rvfi_trap <= trap;
|
||||
if (rvfi_valid) begin
|
||||
rvfi_trap <= 1'b0;
|
||||
pc <= rvfi_pc_wdata;
|
||||
end
|
||||
|
||||
/* RS1 not valid during J, U instructions (immdec_en[1]) */
|
||||
/* RS2 not valid during I, J, U instructions (immdec_en[2]) */
|
||||
if (i_rf_ready) begin
|
||||
rvfi_rs1_addr <= !immdec_en[1] ? rs1_addr : 5'd0;
|
||||
rvfi_rs2_addr <= !immdec_en[2] /*rs2_valid*/ ? rs2_addr : 5'd0;
|
||||
rvfi_rd_addr <= i_rd_addr;
|
||||
end
|
||||
if (rs_en) begin
|
||||
rvfi_rs1_rdata <= {(!immdec_en[1] ? rs1 : {W{1'b0}}),rvfi_rs1_rdata[31:W]};
|
||||
rvfi_rs2_rdata <= {(!immdec_en[2] ? rs2 : {W{1'b0}}),rvfi_rs2_rdata[31:W]};
|
||||
end
|
||||
|
||||
if (i_dbus_ack) begin
|
||||
rvfi_mem_addr <= i_dbus_adr;
|
||||
rvfi_mem_rmask <= i_dbus_we ? 4'b0000 : i_dbus_sel;
|
||||
rvfi_mem_wmask <= i_dbus_we ? i_dbus_sel : 4'b0000;
|
||||
rvfi_mem_rdata <= i_dbus_rdt;
|
||||
rvfi_mem_wdata <= i_dbus_dat;
|
||||
end
|
||||
if (i_ibus_ack) begin
|
||||
rvfi_mem_rmask <= 4'b0000;
|
||||
rvfi_mem_wmask <= 4'b0000;
|
||||
end
|
||||
end
|
||||
|
||||
assign rvfi_pc_wdata = i_ibus_adr;
|
||||
|
||||
`endif
|
||||
|
||||
endmodule
|
|
@ -15,6 +15,7 @@ module serv_decode
|
|||
output reg o_ebreak,
|
||||
output reg o_branch_op,
|
||||
output reg o_shift_op,
|
||||
output reg o_slt_or_branch,
|
||||
output reg o_rd_op,
|
||||
output reg o_two_stage_op,
|
||||
output reg o_dbus_en,
|
||||
|
@ -78,6 +79,7 @@ module serv_decode
|
|||
~opcode[2] | (funct3[0] & ~funct3[1] & ~opcode[0] & ~opcode[4]) |
|
||||
(funct3[1] & ~funct3[2] & ~opcode[0] & ~opcode[4]) | co_mdu_op;
|
||||
wire co_shift_op = (opcode[2] & ~funct3[1]) & !co_mdu_op;
|
||||
wire co_slt_or_branch = (opcode[4] | (funct3[1] & opcode[2]) | (imm30 & opcode[2] & opcode[3] & ~funct3[2])) & !co_mdu_op;
|
||||
wire co_branch_op = opcode[4];
|
||||
wire co_dbus_en = ~opcode[2] & ~opcode[4];
|
||||
wire co_mtval_pc = opcode[4];
|
||||
|
@ -186,7 +188,7 @@ module serv_decode
|
|||
wire co_rd_csr_en = csr_op;
|
||||
|
||||
wire co_csr_en = csr_op & csr_valid;
|
||||
wire co_csr_mstatus_en = csr_op & !op26 & !op22 & !op20;
|
||||
wire co_csr_mstatus_en = csr_op & !op26 & !op22;
|
||||
wire co_csr_mie_en = csr_op & !op26 & op22 & !op20;
|
||||
wire co_csr_mcause_en = csr_op & op21 & !op20;
|
||||
|
||||
|
@ -257,6 +259,7 @@ module serv_decode
|
|||
o_ebreak = co_ebreak;
|
||||
o_branch_op = co_branch_op;
|
||||
o_shift_op = co_shift_op;
|
||||
o_slt_or_branch = co_slt_or_branch;
|
||||
o_rd_op = co_rd_op;
|
||||
o_mdu_op = co_mdu_op;
|
||||
o_ext_funct3 = co_ext_funct3;
|
||||
|
@ -318,6 +321,7 @@ module serv_decode
|
|||
o_mtval_pc <= co_mtval_pc;
|
||||
o_branch_op <= co_branch_op;
|
||||
o_shift_op <= co_shift_op;
|
||||
o_slt_or_branch <= co_slt_or_branch;
|
||||
o_rd_op <= co_rd_op;
|
||||
o_mdu_op <= co_mdu_op;
|
||||
o_ext_funct3 <= co_ext_funct3;
|
||||
|
|
|
@ -10,6 +10,7 @@ module serv_mem_if
|
|||
//State
|
||||
input wire [1:0] i_bytecnt,
|
||||
input wire [1:0] i_lsb,
|
||||
output wire o_byte_valid,
|
||||
output wire o_misalign,
|
||||
//Control
|
||||
input wire i_signed,
|
||||
|
@ -25,6 +26,21 @@ module serv_mem_if
|
|||
|
||||
reg signbit;
|
||||
|
||||
/*
|
||||
Before a store operation, the data to be written needs to be shifted into
|
||||
place. Depending on the address alignment, we need to shift different
|
||||
amounts. One formula for calculating this is to say that we shift when
|
||||
i_lsb + i_bytecnt < 4. Unfortunately, the synthesis tools don't seem to be
|
||||
clever enough so the hideous expression below is used to achieve the same
|
||||
thing in a more optimal way.
|
||||
*/
|
||||
assign o_byte_valid
|
||||
= (!i_lsb[0] & !i_lsb[1]) |
|
||||
(!i_bytecnt[0] & !i_bytecnt[1]) |
|
||||
(!i_bytecnt[1] & !i_lsb[1]) |
|
||||
(!i_bytecnt[1] & !i_lsb[0]) |
|
||||
(!i_bytecnt[0] & !i_lsb[1]);
|
||||
|
||||
wire dat_valid =
|
||||
i_mdu_op |
|
||||
i_word |
|
||||
|
|
|
@ -27,10 +27,8 @@ module serv_rf_top
|
|||
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_WIDTH = 2,
|
||||
parameter RF_L2D = $clog2((32+(WITH_CSR*4))*32/RF_WIDTH))
|
||||
(
|
||||
input wire clk,
|
||||
|
@ -88,13 +86,13 @@ module serv_rf_top
|
|||
wire [4+WITH_CSR:0] wreg1;
|
||||
wire wen0;
|
||||
wire wen1;
|
||||
wire [W-1:0] wdata0;
|
||||
wire [W-1:0] wdata1;
|
||||
wire wdata0;
|
||||
wire 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 rdata0;
|
||||
wire rdata1;
|
||||
|
||||
wire [RF_L2D-1:0] waddr;
|
||||
wire [RF_WIDTH-1:0] wdata;
|
||||
|
@ -106,8 +104,7 @@ module serv_rf_top
|
|||
serv_rf_ram_if
|
||||
#(.width (RF_WIDTH),
|
||||
.reset_strategy (RESET_STRATEGY),
|
||||
.csr_regs (CSR_REGS),
|
||||
.W(W))
|
||||
.csr_regs (CSR_REGS))
|
||||
rf_ram_if
|
||||
(.i_clk (clk),
|
||||
.i_rst (i_rst),
|
||||
|
@ -148,11 +145,9 @@ module serv_rf_top
|
|||
.PRE_REGISTER (PRE_REGISTER),
|
||||
.RESET_STRATEGY (RESET_STRATEGY),
|
||||
.WITH_CSR (WITH_CSR),
|
||||
.DEBUG (DEBUG),
|
||||
.MDU(MDU),
|
||||
.COMPRESSED(COMPRESSED),
|
||||
.ALIGN(ALIGN),
|
||||
.W(W))
|
||||
.ALIGN(ALIGN))
|
||||
cpu
|
||||
(
|
||||
.clk (clk),
|
||||
|
|
|
@ -20,8 +20,6 @@ module serv_state
|
|||
output wire o_cnt2,
|
||||
output wire o_cnt3,
|
||||
output wire o_cnt7,
|
||||
output wire o_cnt11,
|
||||
output wire o_cnt12,
|
||||
output wire o_cnt_done,
|
||||
output wire o_bufreg_en,
|
||||
output wire o_ctrl_pc_en,
|
||||
|
@ -29,6 +27,7 @@ module serv_state
|
|||
output wire o_ctrl_trap,
|
||||
input wire i_ctrl_misalign,
|
||||
input wire i_sh_done,
|
||||
input wire i_sh_done_r,
|
||||
output wire [1:0] o_mem_bytecnt,
|
||||
input wire i_mem_misalign,
|
||||
//Control
|
||||
|
@ -39,8 +38,7 @@ module serv_state
|
|||
input wire i_branch_op,
|
||||
input wire i_shift_op,
|
||||
input wire i_sh_right,
|
||||
input wire i_alu_rd_sel1,
|
||||
input wire i_rd_alu_en,
|
||||
input wire i_slt_or_branch,
|
||||
input wire i_e_op,
|
||||
input wire i_rd_op,
|
||||
//MDU
|
||||
|
@ -59,6 +57,7 @@ module serv_state
|
|||
input wire i_rf_ready,
|
||||
output wire o_rf_rd_en);
|
||||
|
||||
reg stage_two_req;
|
||||
reg init_done;
|
||||
wire misalign_trap_sync;
|
||||
|
||||
|
@ -78,8 +77,6 @@ module serv_state
|
|||
assign o_cnt2 = (o_cnt[4:2] == 3'd0) & cnt_r[2];
|
||||
assign o_cnt3 = (o_cnt[4:2] == 3'd0) & cnt_r[3];
|
||||
assign o_cnt7 = (o_cnt[4:2] == 3'd1) & cnt_r[3];
|
||||
assign o_cnt11 = (o_cnt[4:2] == 3'd2) & cnt_r[3];
|
||||
assign o_cnt12 = (o_cnt[4:2] == 3'd3) & cnt_r[0];
|
||||
|
||||
//Take branch for jump or branch instructions (opcode == 1x0xx) if
|
||||
//a) It's an unconditional branch (opcode[0] == 1)
|
||||
|
@ -89,27 +86,21 @@ module serv_state
|
|||
//been calculated.
|
||||
wire take_branch = i_branch_op & (!i_cond_branch | (i_alu_cmp^i_bne_or_bge));
|
||||
|
||||
wire last_init = o_cnt_done & o_init;
|
||||
|
||||
//valid signal for mdu
|
||||
assign o_mdu_valid = MDU & !o_cnt_en & init_done & i_mdu_op;
|
||||
|
||||
//Prepare RF for writes when everything is ready to enter stage two
|
||||
// and the first stage didn't cause a misalign exception
|
||||
//Left shifts, SLT & Branch ops. First cycle after init
|
||||
//Right shift. o_sh_done
|
||||
//Mem ops. i_dbus_ack
|
||||
//MDU ops. i_mdu_ready
|
||||
assign o_rf_wreq = (i_shift_op & (i_sh_right ? (i_sh_done & (last_init | !o_cnt_en & init_done)) : last_init)) |
|
||||
assign o_rf_wreq = !misalign_trap_sync & !o_cnt_en & init_done &
|
||||
((i_shift_op & (i_sh_done | !i_sh_right)) |
|
||||
i_dbus_ack | (MDU & i_mdu_ready) |
|
||||
(i_branch_op & (last_init & !trap_pending)) |
|
||||
(i_rd_alu_en & i_alu_rd_sel1 & last_init);
|
||||
i_slt_or_branch);
|
||||
|
||||
assign o_dbus_cyc = !o_cnt_en & init_done & i_dbus_en & !i_mem_misalign;
|
||||
|
||||
//Prepare RF for reads when a new instruction is fetched
|
||||
// or when stage one caused an exception (rreq implies a write request too)
|
||||
assign o_rf_rreq = i_ibus_ack | (trap_pending & last_init);
|
||||
assign o_rf_rreq = i_ibus_ack | (stage_two_req & misalign_trap_sync);
|
||||
|
||||
assign o_rf_rd_en = i_rd_op & !o_init;
|
||||
|
||||
|
@ -124,8 +115,7 @@ module serv_state
|
|||
shift : Shift in during phase 1. Continue shifting between phases (except
|
||||
for the first cycle after init). Shift out during phase 2
|
||||
*/
|
||||
|
||||
assign o_bufreg_en = (o_cnt_en & (o_init | ((o_ctrl_trap | i_branch_op) & i_two_stage_op))) | (i_shift_op & init_done & (i_sh_right | i_sh_done));
|
||||
assign o_bufreg_en = (o_cnt_en & (o_init | ((o_ctrl_trap | i_branch_op) & i_two_stage_op))) | (i_shift_op & !stage_two_req & (i_sh_right | i_sh_done_r) & init_done);
|
||||
|
||||
assign o_ibus_cyc = ibus_cyc & !i_rst;
|
||||
|
||||
|
@ -151,10 +141,14 @@ module serv_state
|
|||
o_ctrl_jump <= o_init & take_branch;
|
||||
end
|
||||
|
||||
//Need a strobe for the first cycle in the IDLE state after INIT
|
||||
stage_two_req <= o_cnt_done & o_init;
|
||||
|
||||
if (i_rst) begin
|
||||
if (RESET_STRATEGY != "NONE") begin
|
||||
init_done <= 1'b0;
|
||||
o_ctrl_jump <= 1'b0;
|
||||
stage_two_req <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -186,7 +180,7 @@ module serv_state
|
|||
reg [3:0] cnt_lsb;
|
||||
always @(posedge i_clk) begin
|
||||
o_cnt <= o_cnt + {2'd0,cnt_r[3]};
|
||||
cnt_lsb <= {cnt_lsb[2:0],(cnt_lsb[3] & !o_cnt_done) | i_rf_ready};
|
||||
cnt_lsb <= {cnt_lsb[2:0],(cnt_lsb[3] & !o_cnt_done) | (i_rf_ready & !o_cnt_en)};
|
||||
if (i_rst & (RESET_STRATEGY != "NONE")) begin
|
||||
o_cnt <= 3'd0;
|
||||
cnt_lsb <= 4'b0000;
|
||||
|
@ -212,15 +206,15 @@ module serv_state
|
|||
|
||||
assign o_ctrl_trap = WITH_CSR & (i_e_op | i_new_irq | misalign_trap_sync);
|
||||
|
||||
generate
|
||||
if (WITH_CSR) begin : gen_csr
|
||||
reg misalign_trap_sync_r;
|
||||
|
||||
//trap_pending is only guaranteed to have correct value during the
|
||||
// last cycle of the init stage
|
||||
wire trap_pending = WITH_CSR & ((take_branch & i_ctrl_misalign & !ALIGN) |
|
||||
(i_dbus_en & i_mem_misalign));
|
||||
|
||||
generate
|
||||
if (WITH_CSR) begin : gen_csr
|
||||
reg misalign_trap_sync_r;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_ibus_ack | o_cnt_done | i_rst)
|
||||
misalign_trap_sync_r <= !(i_ibus_ack | i_rst) & ((trap_pending & o_init) | misalign_trap_sync_r);
|
||||
|
|
264
rtl/serv_top.v
264
rtl/serv_top.v
|
@ -1,13 +1,10 @@
|
|||
`default_nettype none
|
||||
|
||||
module serv_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 WITH_CSR = 1,
|
||||
parameter PRE_REGISTER = 1,
|
||||
parameter RESET_STRATEGY = "MINI",
|
||||
parameter RESET_PC = 32'd0,
|
||||
parameter [0:0] MDU = 1'b0,
|
||||
parameter [0:0] COMPRESSED=0,
|
||||
parameter [0:0] ALIGN = COMPRESSED)
|
||||
|
@ -16,27 +13,27 @@ module serv_top
|
|||
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,
|
||||
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
|
||||
//RF Interface
|
||||
output wire o_rf_rreq,
|
||||
|
@ -46,12 +43,12 @@ module serv_top
|
|||
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 o_wdata0,
|
||||
output wire 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,
|
||||
input wire i_rdata0,
|
||||
input wire i_rdata1,
|
||||
|
||||
output wire [31:0] o_ibus_adr,
|
||||
output wire o_ibus_cyc,
|
||||
|
@ -88,16 +85,17 @@ module serv_top
|
|||
wire ebreak;
|
||||
wire branch_op;
|
||||
wire shift_op;
|
||||
wire slt_or_branch;
|
||||
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 ctrl_rd;
|
||||
wire alu_rd;
|
||||
wire mem_rd;
|
||||
wire csr_rd;
|
||||
wire mtval_pc;
|
||||
|
||||
wire ctrl_pc_en;
|
||||
|
@ -105,7 +103,7 @@ module serv_top
|
|||
wire jal_or_jalr;
|
||||
wire utype;
|
||||
wire mret;
|
||||
wire [B:0] imm;
|
||||
wire imm;
|
||||
wire trap;
|
||||
wire pc_rel;
|
||||
wire iscomp;
|
||||
|
@ -119,8 +117,6 @@ module serv_top
|
|||
wire cnt2;
|
||||
wire cnt3;
|
||||
wire cnt7;
|
||||
wire cnt11;
|
||||
wire cnt12;
|
||||
|
||||
wire cnt_done;
|
||||
|
||||
|
@ -129,8 +125,8 @@ module serv_top
|
|||
wire bufreg_rs1_en;
|
||||
wire bufreg_imm_en;
|
||||
wire bufreg_clr_lsb;
|
||||
wire [B:0] bufreg_q;
|
||||
wire [B:0] bufreg2_q;
|
||||
wire bufreg_q;
|
||||
wire bufreg2_q;
|
||||
wire [31:0] dbus_rdt;
|
||||
wire dbus_ack;
|
||||
|
||||
|
@ -141,11 +137,11 @@ module serv_top
|
|||
wire alu_cmp;
|
||||
wire [2:0] alu_rd_sel;
|
||||
|
||||
wire [B:0] rs1;
|
||||
wire [B:0] rs2;
|
||||
wire rs1;
|
||||
wire rs2;
|
||||
wire rd_en;
|
||||
|
||||
wire [B:0] op_b;
|
||||
wire op_b;
|
||||
wire op_b_sel;
|
||||
|
||||
wire mem_signed;
|
||||
|
@ -153,23 +149,25 @@ module serv_top
|
|||
wire mem_half;
|
||||
wire [1:0] mem_bytecnt;
|
||||
wire sh_done;
|
||||
wire sh_done_r;
|
||||
wire byte_valid;
|
||||
|
||||
wire mem_misalign;
|
||||
|
||||
wire [B:0] bad_pc;
|
||||
wire 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_imm;
|
||||
wire csr_d_sel;
|
||||
wire csr_en;
|
||||
wire [1:0] csr_addr;
|
||||
wire [B:0] csr_pc;
|
||||
wire csr_pc;
|
||||
wire csr_imm_en;
|
||||
wire [B:0] csr_in;
|
||||
wire [B:0] rf_csr_out;
|
||||
wire csr_in;
|
||||
wire rf_csr_out;
|
||||
wire dbus_en;
|
||||
|
||||
wire new_irq;
|
||||
|
@ -226,8 +224,7 @@ module serv_top
|
|||
#(.RESET_STRATEGY (RESET_STRATEGY),
|
||||
.WITH_CSR (WITH_CSR[0:0]),
|
||||
.MDU(MDU),
|
||||
.ALIGN(ALIGN),
|
||||
.W(W))
|
||||
.ALIGN(ALIGN))
|
||||
state
|
||||
(
|
||||
.i_clk (clk),
|
||||
|
@ -244,8 +241,6 @@ module serv_top
|
|||
.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),
|
||||
|
@ -253,6 +248,7 @@ module serv_top
|
|||
.o_ctrl_trap (trap),
|
||||
.i_ctrl_misalign(lsb[1]),
|
||||
.i_sh_done (sh_done),
|
||||
.i_sh_done_r (sh_done_r),
|
||||
.o_mem_bytecnt (mem_bytecnt),
|
||||
.i_mem_misalign (mem_misalign),
|
||||
//Control
|
||||
|
@ -263,8 +259,7 @@ module serv_top
|
|||
.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_slt_or_branch (slt_or_branch),
|
||||
.i_e_op (e_op),
|
||||
.i_rd_op (rd_op),
|
||||
//MDU
|
||||
|
@ -300,6 +295,7 @@ module serv_top
|
|||
.o_ebreak (ebreak),
|
||||
.o_branch_op (branch_op),
|
||||
.o_shift_op (shift_op),
|
||||
.o_slt_or_branch (slt_or_branch),
|
||||
.o_rd_op (rd_op),
|
||||
.o_sh_right (sh_right),
|
||||
.o_mdu_op (mdu_op),
|
||||
|
@ -399,12 +395,11 @@ module serv_top
|
|||
//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),
|
||||
.i_byte_valid (byte_valid),
|
||||
.o_sh_done (sh_done),
|
||||
.o_sh_done_r (sh_done_r),
|
||||
//Control
|
||||
.i_op_b_sel (op_b_sel),
|
||||
.i_shift_op (shift_op),
|
||||
|
@ -421,8 +416,7 @@ module serv_top
|
|||
serv_ctrl
|
||||
#(.RESET_PC (RESET_PC),
|
||||
.RESET_STRATEGY (RESET_STRATEGY),
|
||||
.WITH_CSR (WITH_CSR),
|
||||
.W (W))
|
||||
.WITH_CSR (WITH_CSR))
|
||||
ctrl
|
||||
(
|
||||
.clk (clk),
|
||||
|
@ -449,7 +443,7 @@ module serv_top
|
|||
//External
|
||||
.o_ibus_adr (wb_ibus_adr));
|
||||
|
||||
serv_alu #(.W (W)) alu
|
||||
serv_alu alu
|
||||
(
|
||||
.clk (clk),
|
||||
//State
|
||||
|
@ -469,7 +463,7 @@ module serv_top
|
|||
.o_rd (alu_rd));
|
||||
|
||||
serv_rf_if
|
||||
#(.WITH_CSR (WITH_CSR), .W(W))
|
||||
#(.WITH_CSR (WITH_CSR))
|
||||
rf_if
|
||||
(//RF interface
|
||||
.i_cnt_en (cnt_en),
|
||||
|
@ -487,7 +481,7 @@ module serv_top
|
|||
//Trap interface
|
||||
.i_trap (trap),
|
||||
.i_mret (mret),
|
||||
.i_mepc (wb_ibus_adr[B:0]),
|
||||
.i_mepc (wb_ibus_adr[0]),
|
||||
.i_mtval_pc (mtval_pc),
|
||||
.i_bufreg_q (bufreg_q),
|
||||
.i_bad_pc (bad_pc),
|
||||
|
@ -518,14 +512,14 @@ module serv_top
|
|||
.o_csr (rf_csr_out));
|
||||
|
||||
serv_mem_if
|
||||
#(.WITH_CSR (WITH_CSR[0:0]),
|
||||
.W (W))
|
||||
#(.WITH_CSR (WITH_CSR[0:0]))
|
||||
mem_if
|
||||
(
|
||||
.i_clk (clk),
|
||||
//State
|
||||
.i_bytecnt (mem_bytecnt),
|
||||
.i_lsb (lsb),
|
||||
.o_byte_valid (byte_valid),
|
||||
.o_misalign (mem_misalign),
|
||||
//Control
|
||||
.i_mdu_op (mdu_op),
|
||||
|
@ -541,8 +535,7 @@ module serv_top
|
|||
generate
|
||||
if (|WITH_CSR) begin : gen_csr
|
||||
serv_csr
|
||||
#(.RESET_STRATEGY (RESET_STRATEGY),
|
||||
.W(W))
|
||||
#(.RESET_STRATEGY (RESET_STRATEGY))
|
||||
csr
|
||||
(
|
||||
.i_clk (clk),
|
||||
|
@ -553,8 +546,6 @@ module serv_top
|
|||
.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),
|
||||
|
@ -577,76 +568,81 @@ module serv_top
|
|||
.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 csr_in = 1'b0;
|
||||
assign csr_rd = 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
|
||||
|
||||
`ifdef RISCV_FORMAL
|
||||
reg [31:0] pc = RESET_PC;
|
||||
|
||||
wire rs_en = two_stage_op ? init : ctrl_pc_en;
|
||||
|
||||
always @(posedge clk) begin
|
||||
/* End of instruction */
|
||||
rvfi_valid <= cnt_done & ctrl_pc_en & !i_rst;
|
||||
rvfi_order <= rvfi_order + {63'd0,rvfi_valid};
|
||||
|
||||
/* Get instruction word when it's fetched from ibus */
|
||||
if (wb_ibus_cyc & wb_ibus_ack)
|
||||
rvfi_insn <= i_wb_rdt;
|
||||
|
||||
/* Store data written to rd */
|
||||
if (o_wen0)
|
||||
rvfi_rd_wdata <= {o_wdata0,rvfi_rd_wdata[31:1]};
|
||||
|
||||
if (cnt_done & ctrl_pc_en) begin
|
||||
rvfi_pc_rdata <= pc;
|
||||
if (!(rd_en & (|rd_addr))) begin
|
||||
rvfi_rd_addr <= 5'd0;
|
||||
rvfi_rd_wdata <= 32'd0;
|
||||
end
|
||||
end
|
||||
rvfi_trap <= trap;
|
||||
if (rvfi_valid) begin
|
||||
rvfi_trap <= 1'b0;
|
||||
pc <= rvfi_pc_wdata;
|
||||
end
|
||||
|
||||
/* Not used */
|
||||
rvfi_halt <= 1'b0;
|
||||
rvfi_intr <= 1'b0;
|
||||
rvfi_mode <= 2'd3;
|
||||
rvfi_ixl = 2'd1;
|
||||
|
||||
/* RS1 not valid during J, U instructions (immdec_en[1]) */
|
||||
/* RS2 not valid during I, J, U instructions (immdec_en[2]) */
|
||||
if (i_rf_ready) begin
|
||||
rvfi_rs1_addr <= !immdec_en[1] ? rs1_addr : 5'd0;
|
||||
rvfi_rs2_addr <= !immdec_en[2] /*rs2_valid*/ ? rs2_addr : 5'd0;
|
||||
rvfi_rd_addr <= rd_addr;
|
||||
end
|
||||
if (rs_en) begin
|
||||
rvfi_rs1_rdata <= {!immdec_en[1] & rs1,rvfi_rs1_rdata[31:1]};
|
||||
rvfi_rs2_rdata <= {!immdec_en[2] & 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 (wb_ibus_ack) begin
|
||||
rvfi_mem_rmask <= 4'b0000;
|
||||
rvfi_mem_wmask <= 4'b0000;
|
||||
end
|
||||
end
|
||||
/* verilator lint_off COMBDLY */
|
||||
always @(wb_ibus_adr)
|
||||
rvfi_pc_wdata <= wb_ibus_adr;
|
||||
/* verilator lint_on COMBDLY */
|
||||
|
||||
|
||||
`endif
|
||||
|
||||
generate
|
||||
if (MDU) begin: gen_mdu
|
||||
|
|
|
@ -18,7 +18,6 @@ filesets:
|
|||
- rtl/serv_rf_ram_if.v
|
||||
- rtl/serv_rf_ram.v
|
||||
- rtl/serv_state.v
|
||||
- rtl/serv_debug.v
|
||||
- rtl/serv_top.v
|
||||
- rtl/serv_rf_top.v
|
||||
- rtl/serv_aligner.v
|
||||
|
|
23
servant.core
23
servant.core
|
@ -218,12 +218,6 @@ filesets:
|
|||
- servant/servive_clock_gen.v : {file_type : verilogSource}
|
||||
- servant/servive.v : {file_type : verilogSource}
|
||||
|
||||
te0802:
|
||||
files:
|
||||
- servant/servant_te0802_clock_gen.v : {file_type : verilogSource}
|
||||
- servant/servant_te0802.v : {file_type : verilogSource}
|
||||
- data/te0802.xdc : {file_type : xdc}
|
||||
|
||||
tinyfpga_bx: {files: [data/tinyfpga_bx.pcf : {file_type : PCF}]}
|
||||
|
||||
ulx3s:
|
||||
|
@ -490,6 +484,7 @@ targets:
|
|||
description : Machdyne Kolibri FPGA Dongle
|
||||
filesets : [mem_files, soc, machdyne_kolibri]
|
||||
parameters : [memfile, memsize]
|
||||
tools:
|
||||
tools:
|
||||
icestorm:
|
||||
nextpnr_options : [--hx4k, --package, bg121, --freq, 48]
|
||||
|
@ -585,7 +580,6 @@ targets:
|
|||
filesets : [soc, servant_tb]
|
||||
parameters :
|
||||
- RISCV_FORMAL
|
||||
- width
|
||||
- "mdu? (MDU=1)"
|
||||
- SERV_CLEAR_RAM=true
|
||||
- firmware
|
||||
|
@ -603,15 +597,6 @@ targets:
|
|||
device : 5CSXFC6D6F31C6
|
||||
toplevel: servive
|
||||
|
||||
te0802:
|
||||
default_tool: vivado
|
||||
description : Trenz Electronic TE0802
|
||||
filesets : [mem_files, soc, te0802]
|
||||
parameters : [memfile, memsize]
|
||||
tools:
|
||||
vivado: {part : xczu2cg-sbva484-1-e}
|
||||
toplevel : servant_te0802
|
||||
|
||||
tinyfpga_bx:
|
||||
description: TinyFPGA BX
|
||||
filesets : [mem_files, soc, service, tinyfpga_bx]
|
||||
|
@ -664,7 +649,6 @@ targets:
|
|||
- uart_baudrate
|
||||
- vcd
|
||||
- vcd_start
|
||||
- width
|
||||
- compressed
|
||||
- align
|
||||
- with_csr=1
|
||||
|
@ -760,11 +744,6 @@ parameters:
|
|||
description : Delay start of VCD dumping until the specified time
|
||||
paramtype : plusarg
|
||||
|
||||
width:
|
||||
datatype : int
|
||||
description : Interal datapath width (1=SERV, 4=QERV)
|
||||
paramtype : vlogparam
|
||||
|
||||
with_csr:
|
||||
datatype : int
|
||||
description : Enable/Disable CSR support
|
||||
|
|
|
@ -8,9 +8,7 @@ module servant
|
|||
parameter memfile = "zephyr_hello.hex";
|
||||
parameter memsize = 8192;
|
||||
parameter reset_strategy = "MINI";
|
||||
parameter width = 1;
|
||||
parameter sim = 0;
|
||||
parameter [0:0] debug = 1'b0;
|
||||
parameter with_csr = 1;
|
||||
parameter [0:0] compress = 0;
|
||||
parameter [0:0] align = compress;
|
||||
|
@ -25,7 +23,7 @@ module servant
|
|||
localparam aw = $clog2(memsize);
|
||||
localparam csr_regs = with_csr*4;
|
||||
|
||||
localparam rf_width = width * 2;
|
||||
localparam rf_width = 2;
|
||||
localparam rf_l2d = $clog2((32+csr_regs)*32/rf_width);
|
||||
|
||||
wire timer_irq;
|
||||
|
@ -135,9 +133,8 @@ module servant
|
|||
.o_rdata (rf_rdata));
|
||||
|
||||
servile
|
||||
#(.width (width),
|
||||
#(.rf_width (rf_width),
|
||||
.sim (sim[0]),
|
||||
.debug (debug),
|
||||
.with_c (compress[0]),
|
||||
.with_csr (with_csr[0]),
|
||||
.with_mdu (with_mdu))
|
||||
|
@ -162,7 +159,7 @@ module servant
|
|||
.o_wb_ext_stb (wb_ext_stb),
|
||||
.i_wb_ext_rdt (wb_ext_rdt),
|
||||
.i_wb_ext_ack (wb_ext_ack),
|
||||
|
||||
|
||||
.o_rf_waddr (rf_waddr),
|
||||
.o_rf_wdata (rf_wdata),
|
||||
.o_rf_wen (rf_wen),
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
`default_nettype none
|
||||
module servant_te0802
|
||||
(
|
||||
input wire i_clk,
|
||||
output wire o_uart_tx,
|
||||
output wire o_led_0
|
||||
);
|
||||
|
||||
parameter memfile = "zephyr_hello.hex";
|
||||
parameter memsize = 8192;
|
||||
|
||||
wire clk;
|
||||
wire rst;
|
||||
wire q;
|
||||
|
||||
assign o_uart_tx = q;
|
||||
assign o_led_0 = q;
|
||||
|
||||
servant_te0802_clock_gen
|
||||
clock_gen
|
||||
(.i_clk (i_clk),
|
||||
.o_clk (clk),
|
||||
.o_rst (rst));
|
||||
|
||||
servant
|
||||
#(.memfile (memfile),
|
||||
.memsize (memsize))
|
||||
servant
|
||||
(.wb_clk (clk),
|
||||
.wb_rst (rst),
|
||||
.q (q));
|
||||
|
||||
endmodule
|
|
@ -1,45 +0,0 @@
|
|||
`default_nettype none
|
||||
module servant_te0802_clock_gen
|
||||
(input wire i_clk,
|
||||
output wire o_clk,
|
||||
output reg o_rst);
|
||||
|
||||
wire clkfb;
|
||||
wire locked;
|
||||
reg locked_r;
|
||||
|
||||
// Generate a 32 MHz clock from the 25MHz clock input
|
||||
MMCME4_ADV
|
||||
#(.DIVCLK_DIVIDE (1),
|
||||
.CLKFBOUT_MULT_F (48.000),
|
||||
.CLKOUT0_DIVIDE_F (37.5),
|
||||
.CLKIN1_PERIOD (40.0), //25MHz
|
||||
.STARTUP_WAIT ("FALSE"))
|
||||
mmcm
|
||||
(.CLKFBOUT (clkfb),
|
||||
.CLKFBOUTB (),
|
||||
.CLKOUT0 (o_clk),
|
||||
.CLKOUT0B (),
|
||||
.CLKOUT1 (),
|
||||
.CLKOUT1B (),
|
||||
.CLKOUT2 (),
|
||||
.CLKOUT2B (),
|
||||
.CLKOUT3 (),
|
||||
.CLKOUT3B (),
|
||||
.CLKOUT4 (),
|
||||
.CLKOUT5 (),
|
||||
.CLKOUT6 (),
|
||||
.CLKIN1 (i_clk),
|
||||
.CLKIN2 (1'b0),
|
||||
.CLKINSEL (1'b1),
|
||||
.LOCKED (locked),
|
||||
.PWRDWN (1'b0),
|
||||
.RST (1'b0),
|
||||
.CLKFBIN (clkfb));
|
||||
|
||||
always @(posedge o_clk) begin
|
||||
locked_r <= locked;
|
||||
o_rst <= !locked_r;
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -8,17 +8,14 @@
|
|||
`default_nettype none
|
||||
module servile
|
||||
#(
|
||||
parameter width = 1,
|
||||
parameter reset_pc = 32'h00000000,
|
||||
parameter reset_strategy = "MINI",
|
||||
parameter rf_width = 2*width,
|
||||
parameter rf_width = 8,
|
||||
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))
|
||||
(
|
||||
|
@ -81,13 +78,13 @@ module servile
|
|||
wire [$clog2(regs)-1:0] wreg1;
|
||||
wire wen0;
|
||||
wire wen1;
|
||||
wire [B:0] wdata0;
|
||||
wire [B:0] wdata1;
|
||||
wire wdata0;
|
||||
wire 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 rdata0;
|
||||
wire rdata1;
|
||||
|
||||
wire [31:0] mdu_rs1;
|
||||
wire [31:0] mdu_rs2;
|
||||
|
@ -152,7 +149,6 @@ module servile
|
|||
|
||||
serv_rf_ram_if
|
||||
#(.width (rf_width),
|
||||
.W (width),
|
||||
.reset_strategy (reset_strategy),
|
||||
.csr_regs (with_csr*4))
|
||||
rf_ram_if
|
||||
|
@ -200,11 +196,9 @@ module servile
|
|||
serv_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
|
||||
|
|
|
@ -61,12 +61,11 @@ module servile_mux
|
|||
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;
|
||||
integer f = 0;
|
||||
|
||||
initial
|
||||
/* verilator lint_off WIDTH */
|
||||
|
|
|
@ -109,7 +109,6 @@ module serving
|
|||
servile
|
||||
#(.reset_pc (32'h0000_0000),
|
||||
.reset_strategy (RESET_STRATEGY),
|
||||
.rf_width (rf_width),
|
||||
.sim (sim),
|
||||
.with_csr (WITH_CSR))
|
||||
servile
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
TOOLCHAIN_PREFIX?=riscv64-unknown-elf-
|
||||
|
||||
%.elf: %.S link.ld
|
||||
$(TOOLCHAIN_PREFIX)gcc -nostartfiles -nostdlib -march=rv32i_zicsr -mabi=ilp32 -Tlink.ld -o$@ $<
|
||||
$(TOOLCHAIN_PREFIX)gcc -nostartfiles -nostdlib -march=rv32i -mabi=ilp32 -Tlink.ld -o$@ $<
|
||||
%.bin: %.elf
|
||||
$(TOOLCHAIN_PREFIX)objcopy -O binary $< $@
|
||||
%.hex: %.bin
|
||||
|
|
5
verif/plugin-serv/env/link.ld
vendored
5
verif/plugin-serv/env/link.ld
vendored
|
@ -1,12 +1,15 @@
|
|||
OUTPUT_ARCH( "riscv" )
|
||||
ENTRY(rvtest_entry_point)
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x00000000;
|
||||
.text.init : { *(.text.init) }
|
||||
. = ALIGN(0x1000);
|
||||
.tohost : { *(.tohost) }
|
||||
. = ALIGN(0x1000);
|
||||
.text : { *(.text) }
|
||||
. = ALIGN(0x1000);
|
||||
.data : { *(.data) }
|
||||
.data.string : { *(.data.string)}
|
||||
.bss : { *(.bss) }
|
||||
|
|
9
verif/plugin-serv/env/model_test.h
vendored
9
verif/plugin-serv/env/model_test.h
vendored
|
@ -48,7 +48,12 @@
|
|||
.align 4; .global end_signature; end_signature: \
|
||||
|
||||
|
||||
#define RVMODEL_BOOT
|
||||
#define RVMODEL_BOOT \
|
||||
.section .text.init; \
|
||||
.align 4; \
|
||||
.globl _start; \
|
||||
_start:
|
||||
|
||||
|
||||
#define LOCAL_IO_WRITE_STR(_STR) RVMODEL_IO_WRITE_STR(x31, _STR)
|
||||
#define RVMODEL_IO_WRITE_STR(_SP, _STR)
|
||||
|
@ -63,4 +68,4 @@
|
|||
#define RVMODEL_CLEAR_MTIMER_INT
|
||||
#define RVMODEL_CLEAR_MEXT_INT
|
||||
|
||||
#endif // _COMPLIANCE_MODEL_H
|
||||
#endif // _COMPLIANCE_MODEL_H
|
2
west.yml
2
west.yml
|
@ -5,5 +5,5 @@ manifest:
|
|||
projects:
|
||||
- name: zephyr
|
||||
remote: zephyrproject-rtos
|
||||
revision: v4.0.0
|
||||
revision: v3.5.0
|
||||
import: true
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include <zephyr/arch/cpu.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/uart.h>
|
||||
#include <soc.h>
|
||||
|
||||
#define DT_DRV_COMPAT olofk_serial
|
||||
|
||||
|
|
|
@ -4,5 +4,4 @@
|
|||
zephyr_sources(
|
||||
soc_irq.S
|
||||
vector.S
|
||||
cpu_idle.c
|
||||
irq.c)
|
||||
|
|
|
@ -23,16 +23,4 @@ config SERV_TIMER
|
|||
bool
|
||||
default y
|
||||
|
||||
config ARCH_HAS_CUSTOM_CPU_IDLE
|
||||
bool
|
||||
default y
|
||||
|
||||
config ARCH_HAS_CUSTOM_CPU_ATOMIC_IDLE
|
||||
bool
|
||||
default y
|
||||
|
||||
config RISCV_SOC_EXCEPTION_FROM_IRQ
|
||||
bool
|
||||
default y
|
||||
|
||||
endif # SOC_RISCV32_SERVANT
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
#include <zephyr/irq.h>
|
||||
#include <zephyr/tracing/tracing.h>
|
||||
|
||||
// Override arch_cpu_idle() and arch_cpu_atomic_idle() to prevent insertion
|
||||
// of `wfi` instructions, which lock up our system. This was introduced in
|
||||
// Zephyr 3.6.0 with commit 5fb6e267f629dedb8382da6bcad8018b1bb8930a.
|
||||
//
|
||||
// This is probably a hardware bug in SERV. This issue is tracked as #131.
|
||||
// https://github.com/olofk/serv/issues/131
|
||||
|
||||
void arch_cpu_idle(void)
|
||||
{
|
||||
sys_trace_idle();
|
||||
irq_unlock(MSTATUS_IEN);
|
||||
}
|
||||
|
||||
void arch_cpu_atomic_idle(unsigned int key)
|
||||
{
|
||||
sys_trace_idle();
|
||||
irq_unlock(key);
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue