Add demo for veilator and fpga.
This commit is contained in:
parent
2bc0985afd
commit
896011449d
|
@ -0,0 +1,22 @@
|
|||
design/project/target/
|
||||
design/project/project/
|
||||
design/.idea/
|
||||
|
||||
design/target/
|
||||
design/snapshots/
|
||||
|
||||
design/dmi_wrapper.sv
|
||||
design/firrtl_black_box_resource_files.f
|
||||
design/gated_latch.sv
|
||||
design/mem.sv
|
||||
design/quasar_wrapper.anno.json
|
||||
design/quasar_wrapper.fir
|
||||
|
||||
design/src/main/scala/lib/param.scala
|
||||
|
||||
generated_rtl/
|
||||
|
||||
# soc/
|
||||
# demo/
|
||||
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
export RV_ROOT = ${PWD}/../..
|
||||
GDB_PREFIX = /opt/riscv/bin/riscv32-unknown-elf-gdb
|
||||
|
||||
|
||||
TEST_CFLAGS = -g -O3 -funroll-all-loops
|
||||
ABI = -mabi=ilp32 -march=rv32imc
|
||||
|
||||
DEMODIR = ${PWD}
|
||||
BUILD_DIR = ${DEMODIR}/build
|
||||
RV_SOC = ${RV_ROOT}/quasar
|
||||
|
||||
TEST = jtag
|
||||
|
||||
ifdef debug
|
||||
DEBUG_PLUS = +dumpon
|
||||
VERILATOR_DEBUG = --trace
|
||||
endif
|
||||
|
||||
LINK = $(DEMODIR)/link.ld
|
||||
|
||||
# CFLAGS for verilator generated Makefiles. Without -std=c++11 it complains for `auto` variables
|
||||
CFLAGS += "-std=c++11"
|
||||
# Optimization for better performance; alternative is nothing for slower runtime (faster compiles)
|
||||
# -O2 for faster runtime (slower compiles), or -O for balance.
|
||||
VERILATOR_MAKE_FLAGS = OPT_FAST="-Os"
|
||||
|
||||
# Targets
|
||||
all: clean verilator
|
||||
|
||||
clean:
|
||||
rm -rf build obj_dir
|
||||
|
||||
swerv_define :
|
||||
BUILD_PATH=${BUILD_DIR} PERLLIB=${RV_SOC} ${RV_SOC}/swerv.config -target=default -set iccm_enable
|
||||
|
||||
##################### Verilog Builds #####################################
|
||||
|
||||
verilator-build: swerv_define
|
||||
echo '`undef ASSERT_ON' >> ${BUILD_DIR}/common_defines.vh
|
||||
verilator --cc -CFLAGS ${CFLAGS} \
|
||||
$(BUILD_DIR)/common_defines.vh \
|
||||
-I${BUILD_DIR} \
|
||||
-Wno-UNOPTFLAT \
|
||||
-Wno-WIDTH \
|
||||
-Wno-LATCH \
|
||||
-Wno-IMPLICIT \
|
||||
-F ${RV_SOC}/soc_top.mk \
|
||||
-F ${RV_SOC}/soc_sim.mk \
|
||||
$(RV_SOC)/soc_sim.sv \
|
||||
--top-module soc_sim -exe test_soc_sim.cpp --autoflush $(VERILATOR_DEBUG)
|
||||
cp ${DEMODIR}/test_soc_sim.cpp obj_dir
|
||||
$(MAKE) -j -C obj_dir/ -f Vsoc_sim.mk $(VERILATOR_MAKE_FLAGS)
|
||||
|
||||
##################### Simulation Runs #####################################
|
||||
|
||||
verilator: program verilator-build
|
||||
cd build && ../obj_dir/Vsoc_sim ${DEBUG_PLUS}
|
||||
|
||||
##################### Test hex Build #####################################
|
||||
|
||||
program:
|
||||
@mkdir build
|
||||
@cp program.hex build/program.hex
|
||||
@cp jtag.bin build/jtag.bin
|
||||
|
||||
##################### openocd #####################################
|
||||
|
||||
openocd:
|
||||
openocd -f swerv.cfg
|
||||
|
||||
gdb:
|
||||
$(GDB_PREFIX) -x gdbinit ./build/jtag.bin
|
||||
|
||||
help:
|
||||
@echo Possible targets: verilator help clean all verilator-build program.hex
|
||||
|
||||
.PHONY: help clean verilator
|
|
@ -0,0 +1,29 @@
|
|||
# jtag simulation
|
||||
|
||||
## gen SweRV module from scala
|
||||
|
||||
```bash
|
||||
cd Quasar
|
||||
export RV_ROOT=${PWD}
|
||||
cd tools
|
||||
make clean
|
||||
make conf
|
||||
make -f $RV_ROOT/tools/Makefile sbt_
|
||||
# Quasar/generated_rtl/quasar_wrapper.sv
|
||||
```
|
||||
|
||||
## start openocd
|
||||
|
||||
`openocd -d -f swerv.cfg`
|
||||
|
||||
## start gdb
|
||||
|
||||
`/opt/riscv/bin/riscv32-unknown-elf-gdb -ex "target extended-remote :3333"`
|
||||
|
||||
## quick start
|
||||
|
||||
At demo/jtag/
|
||||
|
||||
1. `make all`
|
||||
2. `make openocd`
|
||||
3. `make gdb`
|
|
@ -0,0 +1,3 @@
|
|||
# set debug remote 1
|
||||
target remote :3333
|
||||
set remotetimeout 2000
|
Binary file not shown.
|
@ -0,0 +1,28 @@
|
|||
@00000000
|
||||
73 10 20 B0 73 10 20 B8 B7 00 00 EE 73 90 50 30
|
||||
B7 50 55 5F 93 80 50 55 73 90 00 7C B7 01 58 D0
|
||||
17 42 00 00 13 02 02 FE 83 02 02 00 23 80 51 00
|
||||
05 02 E3 9B 02 FE B7 01 58 D0 17 42 00 00 13 02
|
||||
62 FC 83 02 02 00 23 80 51 00 05 02 E3 9B 02 FE
|
||||
63 00 00 00 B7 01 58 D0 93 02 F0 0F 23 80 51 00
|
||||
E3 0A 00 FE 01 00 01 00 01 00 01 00 01 00 01 00
|
||||
01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00
|
||||
01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00
|
||||
01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00
|
||||
01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00
|
||||
01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00
|
||||
01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00
|
||||
01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00
|
||||
01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00
|
||||
01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00
|
||||
01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00
|
||||
01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00
|
||||
01 00 01 00 01 00 01 00 01 00 01 00
|
||||
@00004000
|
||||
2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D
|
||||
2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D
|
||||
2D 2D 0A 48 65 6C 6C 6F 20 57 6F 72 6C 64 20 43
|
||||
6F 6C 69 6E 2E 6C 69 61 6E 67 20 45 4C 32 40 57
|
||||
44 43 20 21 21 0A 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D
|
||||
2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D
|
||||
2D 2D 2D 2D 2D 2D 2D 2D 0A 00
|
|
@ -0,0 +1,34 @@
|
|||
# "JTAG adapter" for simulation, exposed to OpenOCD through a TCP socket
|
||||
# speaking the remote_bitbang protocol. The adapter is implemented as
|
||||
# SystemVerilog DPI module.
|
||||
|
||||
adapter driver remote_bitbang
|
||||
remote_bitbang host localhost
|
||||
remote_bitbang port 44853
|
||||
|
||||
# Target configuration for the riscv chip
|
||||
|
||||
set _CHIPNAME riscv
|
||||
set _TARGETNAME $_CHIPNAME.cpu
|
||||
|
||||
jtag newtap $_CHIPNAME tap -irlen 5 -expected-id 0x1000008b
|
||||
set _TARGETNAME $_CHIPNAME.tap
|
||||
target create $_TARGETNAME riscv -chain-position $_TARGETNAME
|
||||
|
||||
# Configure work area in on-chip SRAM
|
||||
# $_TARGETNAME configure -work-area-phys 0x1000e000 -work-area-size 1000 -work-area-backup 0
|
||||
|
||||
riscv expose_csrs 1988
|
||||
|
||||
# Be verbose about GDB errors
|
||||
gdb_report_data_abort enable
|
||||
gdb_report_register_access_error enable
|
||||
|
||||
# Increase timeouts in simulation
|
||||
riscv set_command_timeout_sec 1200
|
||||
|
||||
# Conclude OpenOCD configuration
|
||||
init
|
||||
|
||||
# Halt the target
|
||||
halt
|
|
@ -0,0 +1,65 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2019 Western Digital Corporation or its affiliates.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#include <stdlib.h>
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include "Vsoc_sim.h"
|
||||
#include "verilated.h"
|
||||
#include "verilated_vcd_c.h"
|
||||
|
||||
|
||||
vluint64_t main_time = 0;
|
||||
|
||||
double sc_time_stamp () {
|
||||
return main_time;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
std::cout << "\nVerilatorTB: Start of sim\n" << std::endl;
|
||||
|
||||
Verilated::commandArgs(argc, argv);
|
||||
|
||||
Vsoc_sim* soc = new Vsoc_sim;
|
||||
|
||||
// init trace dump
|
||||
VerilatedVcdC* tfp = NULL;
|
||||
|
||||
#if VM_TRACE
|
||||
Verilated::traceEverOn(true);
|
||||
tfp = new VerilatedVcdC;
|
||||
soc->trace (tfp, 24);
|
||||
tfp->open ("sim.vcd");
|
||||
#endif
|
||||
// Simulate
|
||||
while(!Verilated::gotFinish()){
|
||||
#if VM_TRACE
|
||||
tfp->dump (main_time);
|
||||
#endif
|
||||
main_time += 5;
|
||||
soc->core_clk = !soc->core_clk;
|
||||
soc->eval();
|
||||
}
|
||||
|
||||
#if VM_TRACE
|
||||
tfp->close();
|
||||
#endif
|
||||
|
||||
std::cout << "\nVerilatorTB: End of sim" << std::endl;
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,110 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2019 Western Digital Corporation or its affiliates.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
module axi_slv #(
|
||||
TAGW = 1
|
||||
) (
|
||||
input aclk,
|
||||
input rst_l,
|
||||
input arvalid,
|
||||
output reg arready,
|
||||
input [ 31:0] araddr,
|
||||
input [TAGW-1:0] arid,
|
||||
input [ 7:0] arlen,
|
||||
input [ 1:0] arburst,
|
||||
input [ 2:0] arsize,
|
||||
|
||||
output reg rvalid,
|
||||
input rready,
|
||||
output reg [ 63:0] rdata,
|
||||
output reg [ 1:0] rresp,
|
||||
output reg [TAGW-1:0] rid,
|
||||
output rlast,
|
||||
|
||||
input awvalid,
|
||||
output awready,
|
||||
input [ 31:0] awaddr,
|
||||
input [TAGW-1:0] awid,
|
||||
input [ 7:0] awlen,
|
||||
input [ 1:0] awburst,
|
||||
input [ 2:0] awsize,
|
||||
|
||||
input [63:0] wdata,
|
||||
input [ 7:0] wstrb,
|
||||
input wvalid,
|
||||
output wready,
|
||||
|
||||
output reg bvalid,
|
||||
input bready,
|
||||
output reg [ 1:0] bresp,
|
||||
output reg [TAGW-1:0] bid
|
||||
);
|
||||
|
||||
parameter MEM_DEPTH = 15; // memory size = 0x8000 = 32k
|
||||
|
||||
bit [7:0] mem[(1<<MEM_DEPTH)-1:0];
|
||||
|
||||
bit [63:0] memdata;
|
||||
|
||||
wire [MEM_DEPTH-1:0] saraddr = araddr[MEM_DEPTH-1:0];
|
||||
wire [MEM_DEPTH-1:0] sawaddr = awaddr[MEM_DEPTH-1:0];
|
||||
|
||||
always @(posedge aclk or negedge rst_l) begin
|
||||
if (!rst_l) begin
|
||||
rvalid <= 0;
|
||||
bvalid <= 0;
|
||||
end else begin
|
||||
bid <= awid;
|
||||
rid <= arid;
|
||||
rvalid <= arvalid;
|
||||
bvalid <= awvalid;
|
||||
rdata <= memdata;
|
||||
end
|
||||
end
|
||||
|
||||
always @(negedge aclk) begin
|
||||
if (arvalid)
|
||||
memdata <= {
|
||||
mem[saraddr+7],
|
||||
mem[saraddr+6],
|
||||
mem[saraddr+5],
|
||||
mem[saraddr+4],
|
||||
mem[saraddr+3],
|
||||
mem[saraddr+2],
|
||||
mem[saraddr+1],
|
||||
mem[saraddr]
|
||||
};
|
||||
if (awvalid) begin
|
||||
if (wstrb[7]) mem[sawaddr+7] = wdata[63:56];
|
||||
if (wstrb[6]) mem[sawaddr+6] = wdata[55:48];
|
||||
if (wstrb[5]) mem[sawaddr+5] = wdata[47:40];
|
||||
if (wstrb[4]) mem[sawaddr+4] = wdata[39:32];
|
||||
if (wstrb[3]) mem[sawaddr+3] = wdata[31:24];
|
||||
if (wstrb[2]) mem[sawaddr+2] = wdata[23:16];
|
||||
if (wstrb[1]) mem[sawaddr+1] = wdata[15:08];
|
||||
if (wstrb[0]) mem[sawaddr+0] = wdata[07:00];
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
assign arready = 1'b1;
|
||||
assign awready = 1'b1;
|
||||
assign wready = 1'b1;
|
||||
assign rresp = 2'b0;
|
||||
assign bresp = 2'b0;
|
||||
assign rlast = 1'b1;
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,196 @@
|
|||
|
||||
// connects LSI master to external AXI slave and DMA slave
|
||||
module axi_lsu_dma_bridge #(
|
||||
parameter M_ID_WIDTH = 8,
|
||||
parameter S0_ID_WIDTH = 8
|
||||
) (
|
||||
input clk,
|
||||
input reset_l,
|
||||
|
||||
// master read bus
|
||||
input m_arvalid,
|
||||
input [M_ID_WIDTH-1:0] m_arid,
|
||||
input [ 31:0] m_araddr,
|
||||
output m_arready,
|
||||
|
||||
output m_rvalid,
|
||||
input m_rready,
|
||||
output [ 63:0] m_rdata,
|
||||
output [M_ID_WIDTH-1:0] m_rid,
|
||||
output [ 1:0] m_rresp,
|
||||
output m_rlast,
|
||||
|
||||
// master write bus
|
||||
input m_awvalid,
|
||||
input [M_ID_WIDTH-1:0] m_awid,
|
||||
input [ 31:0] m_awaddr,
|
||||
output m_awready,
|
||||
|
||||
input m_wvalid,
|
||||
output m_wready,
|
||||
|
||||
output [ 1:0] m_bresp,
|
||||
output m_bvalid,
|
||||
output [M_ID_WIDTH-1:0] m_bid,
|
||||
input m_bready,
|
||||
|
||||
// slave 0 if general ext memory
|
||||
output s0_arvalid,
|
||||
input s0_arready,
|
||||
|
||||
input s0_rvalid,
|
||||
input [S0_ID_WIDTH-1:0] s0_rid,
|
||||
input [ 1:0] s0_rresp,
|
||||
input [ 63:0] s0_rdata,
|
||||
input s0_rlast,
|
||||
output s0_rready,
|
||||
|
||||
output s0_awvalid,
|
||||
input s0_awready,
|
||||
|
||||
output s0_wvalid,
|
||||
input s0_wready,
|
||||
|
||||
input [ 1:0] s0_bresp,
|
||||
input s0_bvalid,
|
||||
input [S0_ID_WIDTH-1:0] s0_bid,
|
||||
output s0_bready,
|
||||
|
||||
// slave 1 if DMA port
|
||||
output s1_arvalid,
|
||||
input s1_arready,
|
||||
|
||||
input s1_rvalid,
|
||||
input [ 1:0] s1_rresp,
|
||||
input [63:0] s1_rdata,
|
||||
input s1_rlast,
|
||||
output s1_rready,
|
||||
|
||||
output s1_awvalid,
|
||||
input s1_awready,
|
||||
|
||||
output s1_wvalid,
|
||||
input s1_wready,
|
||||
|
||||
input [1:0] s1_bresp,
|
||||
input s1_bvalid,
|
||||
output s1_bready
|
||||
);
|
||||
|
||||
parameter ICCM_BASE = `RV_ICCM_BITS; // in LSBs
|
||||
localparam IDFIFOSZ = $clog2(`RV_DMA_BUF_DEPTH);
|
||||
bit [31:0] iccm_real_base_addr = `RV_ICCM_SADR;
|
||||
|
||||
wire ar_slave_select;
|
||||
wire aw_slave_select;
|
||||
wire w_slave_select;
|
||||
|
||||
wire rresp_select;
|
||||
wire bresp_select;
|
||||
wire ar_iccm_select;
|
||||
wire aw_iccm_select;
|
||||
|
||||
reg [1:0] wsel_iptr, wsel_optr;
|
||||
reg [2:0] wsel_count;
|
||||
reg [3:0] wsel;
|
||||
|
||||
|
||||
reg [M_ID_WIDTH-1:0] arid[1<<IDFIFOSZ];
|
||||
reg [M_ID_WIDTH-1:0] awid[1<<IDFIFOSZ];
|
||||
reg [IDFIFOSZ-1:0] arid_cnt;
|
||||
reg [IDFIFOSZ-1:0] awid_cnt;
|
||||
reg [IDFIFOSZ-1:0] rid_cnt;
|
||||
reg [IDFIFOSZ-1:0] bid_cnt;
|
||||
|
||||
|
||||
// 1 select slave 1; 0 - slave 0
|
||||
assign ar_slave_select = ar_iccm_select;
|
||||
assign aw_slave_select = aw_iccm_select;
|
||||
|
||||
assign ar_iccm_select = m_araddr[31:ICCM_BASE] == iccm_real_base_addr[31:ICCM_BASE];
|
||||
assign aw_iccm_select = m_awaddr[31:ICCM_BASE] == iccm_real_base_addr[31:ICCM_BASE];
|
||||
|
||||
assign s0_arvalid = m_arvalid & ~ar_slave_select;
|
||||
assign s1_arvalid = m_arvalid & ar_slave_select;
|
||||
assign m_arready = ar_slave_select ? s1_arready : s0_arready;
|
||||
|
||||
|
||||
assign s0_awvalid = m_awvalid & ~aw_slave_select;
|
||||
assign s1_awvalid = m_awvalid & aw_slave_select;
|
||||
assign m_awready = aw_slave_select ? s1_awready : s0_awready;
|
||||
|
||||
|
||||
assign s0_wvalid = m_wvalid & ~w_slave_select;
|
||||
assign s1_wvalid = m_wvalid & w_slave_select;
|
||||
assign m_wready = w_slave_select ? s1_wready : s0_wready;
|
||||
assign w_slave_select = (wsel_count == 0 || wsel_count[2]) ? aw_slave_select : wsel[wsel_optr];
|
||||
|
||||
assign m_rvalid = s0_rvalid | s1_rvalid;
|
||||
assign s0_rready = m_rready & ~rresp_select;
|
||||
assign s1_rready = m_rready & rresp_select;
|
||||
assign m_rdata = rresp_select ? s1_rdata : s0_rdata;
|
||||
assign m_rresp = rresp_select ? s1_rresp : s0_rresp;
|
||||
assign m_rid = rresp_select ? arid[rid_cnt] : s0_rid;
|
||||
assign m_rlast = rresp_select ? s1_rlast : s0_rlast;
|
||||
|
||||
assign rresp_select = s1_rvalid & ~s0_rvalid;
|
||||
|
||||
assign m_bvalid = s0_bvalid | s1_bvalid;
|
||||
assign s0_bready = m_bready & ~bresp_select;
|
||||
assign s1_bready = m_bready & bresp_select;
|
||||
assign m_bid = bresp_select ? awid[bid_cnt] : s0_bid;
|
||||
assign m_bresp = bresp_select ? s1_bresp : s0_bresp;
|
||||
|
||||
|
||||
assign bresp_select = s1_bvalid & ~s0_bvalid;
|
||||
|
||||
|
||||
// W-channel select fifo
|
||||
always @(posedge clk or negedge reset_l)
|
||||
if (!reset_l) begin
|
||||
wsel_count <= '0;
|
||||
wsel_iptr <= '0;
|
||||
wsel_optr <= '0;
|
||||
end else begin
|
||||
if (m_awvalid & m_awready) begin
|
||||
wsel[wsel_iptr] <= aw_slave_select;
|
||||
if (!(m_wready & m_wvalid)) wsel_count <= wsel_count + 1;
|
||||
wsel_iptr <= wsel_iptr + 1;
|
||||
end
|
||||
if (m_wvalid & m_wready) begin
|
||||
if (!(m_awready & m_awvalid)) wsel_count <= wsel_count - 1;
|
||||
wsel_optr <= wsel_optr + 1;
|
||||
end
|
||||
end
|
||||
|
||||
// id replacement for narrow ID slave
|
||||
always @(posedge clk or negedge reset_l)
|
||||
if (!reset_l) begin
|
||||
arid_cnt <= '0;
|
||||
rid_cnt <= '0;
|
||||
end else begin
|
||||
if (ar_slave_select & m_arready & m_arvalid) begin
|
||||
arid[arid_cnt] <= m_arid;
|
||||
arid_cnt <= arid_cnt + 1;
|
||||
end
|
||||
if (rresp_select & m_rready & m_rvalid) begin
|
||||
rid_cnt <= rid_cnt + 1;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
always @(posedge clk or negedge reset_l)
|
||||
if (!reset_l) begin
|
||||
awid_cnt <= '0;
|
||||
bid_cnt <= '0;
|
||||
end else begin
|
||||
if (aw_slave_select & m_awready & m_awvalid) begin
|
||||
awid[awid_cnt] <= m_awid;
|
||||
awid_cnt <= awid_cnt + 1;
|
||||
end
|
||||
if (bresp_select & m_bready & m_bvalid) begin
|
||||
bid_cnt <= bid_cnt + 1;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,395 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2019 Western Digital Corporation or its affiliates.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
// Run time disassembler functions
|
||||
// supports RISCV extentions I, C, M, A
|
||||
`ifndef RV_NUM_THREADS
|
||||
`define RV_NUM_THREADS 1
|
||||
`endif
|
||||
|
||||
bit[31:0] [31:0] gpr[`RV_NUM_THREADS];
|
||||
|
||||
// main DASM function
|
||||
function string dasm(input[31:0] opcode, input[31:0] pc, input[4:0] regn, input[31:0] regv, input tid=0);
|
||||
dasm = (opcode[1:0] == 2'b11) ? dasm32(opcode, pc, tid) : dasm16(opcode, pc, tid);
|
||||
if(regn) gpr[tid][regn] = regv;
|
||||
endfunction
|
||||
|
||||
|
||||
///////////////// 16 bits instructions ///////////////////////
|
||||
|
||||
function string dasm16( input[31:0] opcode, input[31:0] pc, input tid=0);
|
||||
case(opcode[1:0])
|
||||
0: return dasm16_0(opcode, tid);
|
||||
1: return dasm16_1(opcode, pc);
|
||||
2: return dasm16_2(opcode);
|
||||
endcase
|
||||
return $sformatf(".short 0x%h", opcode[15:0]);
|
||||
endfunction
|
||||
|
||||
function string dasm16_0( input[31:0] opcode, tid);
|
||||
case(opcode[15:13])
|
||||
3'b000: return dasm16_ciw(opcode);
|
||||
3'b001: return {"c.fld ", dasm16_cl(opcode, tid)};
|
||||
3'b010: return {"c.lw ", dasm16_cl(opcode, tid)};
|
||||
3'b011: return {"c.flw ", dasm16_cl(opcode, tid)};
|
||||
3'b101: return {"c.fsd ", dasm16_cl(opcode, tid)};
|
||||
3'b110: return {"c.sw ", dasm16_cl(opcode, tid)};
|
||||
3'b111: return {"c.fsw ", dasm16_cl(opcode, tid)};
|
||||
endcase
|
||||
return $sformatf(".short 0x%h", opcode[15:0]);
|
||||
endfunction
|
||||
|
||||
function string dasm16_ciw( input[31:0] opcode);
|
||||
int imm;
|
||||
imm=0;
|
||||
if(opcode[15:0] == 0) return ".short 0";
|
||||
{imm[5:4],imm[9:6],imm[2],imm[3]} = opcode[12:5];
|
||||
return $sformatf("c.addi4spn %s,0x%0h", abi_reg[opcode[4:2]+8], imm);
|
||||
endfunction
|
||||
|
||||
function string dasm16_cl( input[31:0] opcode, input tid=0);
|
||||
int imm;
|
||||
imm=0;
|
||||
imm[5:3] = opcode[12:10];
|
||||
imm[7:6] = opcode[6:5];
|
||||
|
||||
return $sformatf(" %s,%0d(%s) [%h]", abi_reg[opcode[4:2]+8], imm, abi_reg[opcode[9:7]+8], gpr[tid][opcode[9:7]+8]+imm);
|
||||
endfunction
|
||||
|
||||
function string dasm16_1( input[31:0] opcode, input[31:0] pc);
|
||||
case(opcode[15:13])
|
||||
3'b000: return opcode[11:7]==0 ? "c.nop" : {"c.addi ",dasm16_ci(opcode)};
|
||||
3'b001: return {"c.jal ", dasm16_cj(opcode, pc)};
|
||||
3'b010: return {"c.li ", dasm16_ci(opcode)};
|
||||
3'b011: return dasm16_1_3(opcode);
|
||||
3'b100: return dasm16_cr(opcode);
|
||||
3'b101: return {"c.j ", dasm16_cj(opcode, pc)};
|
||||
3'b110: return {"c.beqz ", dasm16_cb(opcode, pc)};
|
||||
3'b111: return {"c.bnez ", dasm16_cb(opcode, pc)};
|
||||
endcase
|
||||
endfunction
|
||||
|
||||
function string dasm16_ci( input[31:0] opcode);
|
||||
int imm;
|
||||
imm=0;
|
||||
imm[4:0] = opcode[6:2];
|
||||
if(opcode[12]) imm [31:5] = '1;
|
||||
return $sformatf("%s,%0d", abi_reg[opcode[11:7]], imm);
|
||||
endfunction
|
||||
|
||||
function string dasm16_cj( input[31:0] opcode, input[31:0] pc);
|
||||
bit[31:0] imm;
|
||||
imm=0;
|
||||
{imm[11],imm[4],imm[9:8],imm[10],imm[6], imm[7],imm[3:1], imm[5]} = opcode[12:2];
|
||||
if(opcode[12]) imm [31:12] = '1;
|
||||
return $sformatf("0x%0h", imm+pc);
|
||||
endfunction
|
||||
|
||||
function string dasm16_cb( input[31:0] opcode, input[31:0] pc);
|
||||
bit[31:0] imm;
|
||||
imm=0;
|
||||
{imm[8],imm[4:3]} = opcode[12:10];
|
||||
{imm[7:6],imm[2:1], imm[5]} = opcode[6:2];
|
||||
if(opcode[12]) imm [31:9] = '1;
|
||||
return $sformatf("%s,0x%0h",abi_reg[opcode[9:7]+8], imm+pc);
|
||||
endfunction
|
||||
|
||||
function string dasm16_cr( input[31:0] opcode);
|
||||
bit[31:0] imm;
|
||||
|
||||
imm = 0;
|
||||
imm[4:0] = opcode[6:2];
|
||||
if(opcode[5]) imm [31:5] = '1;
|
||||
case(opcode[11:10])
|
||||
0: return $sformatf("c.srli %s,%0d", abi_reg[opcode[9:7]+8], imm[5:0]);
|
||||
1: return $sformatf("c.srai %s,%0d", abi_reg[opcode[9:7]+8], imm[5:0]);
|
||||
2: return $sformatf("c.andi %s,0x%0h", abi_reg[opcode[9:7]+8], imm);
|
||||
endcase
|
||||
|
||||
case(opcode[6:5])
|
||||
0: return $sformatf("c.sub %s,%s", abi_reg[opcode[9:7]+8], abi_reg[opcode[4:2]+8]);
|
||||
1: return $sformatf("c.xor %s,%s", abi_reg[opcode[9:7]+8], abi_reg[opcode[4:2]+8]);
|
||||
2: return $sformatf("c.or %s,%s", abi_reg[opcode[9:7]+8], abi_reg[opcode[4:2]+8]);
|
||||
3: return $sformatf("c.and %s,%s", abi_reg[opcode[9:7]+8], abi_reg[opcode[4:2]+8]);
|
||||
endcase
|
||||
endfunction
|
||||
|
||||
function string dasm16_1_3( input[31:0] opcode);
|
||||
int imm;
|
||||
|
||||
imm=0;
|
||||
if(opcode[11:7] == 2) begin
|
||||
{imm[4], imm[6],imm[8:7], imm[5]} = opcode[6:2];
|
||||
if(opcode[12]) imm [31:9] = '1;
|
||||
return $sformatf("c.addi16sp %0d", imm);
|
||||
end
|
||||
else begin
|
||||
imm[16:12] = opcode[6:2];
|
||||
if(opcode[12]) imm [31:17] = '1;
|
||||
return $sformatf("c.lui %s,0x%0h", abi_reg[opcode[11:7]], imm);
|
||||
|
||||
end
|
||||
endfunction
|
||||
|
||||
function string dasm16_2( input[31:0] opcode, input tid=0);
|
||||
case(opcode[15:13])
|
||||
3'b000: return {"c.slli ", dasm16_ci(opcode)};
|
||||
3'b001: return {"c.fldsp ", dasm16_cls(opcode,1,tid)};
|
||||
3'b010: return {"c.lwsp ", dasm16_cls(opcode,0,tid)};
|
||||
3'b011: return {"c.flwsp ", dasm16_cls(opcode,0,tid)};
|
||||
3'b101: return {"c.fsdsp ", dasm16_css(opcode,1,tid)};
|
||||
3'b110: return {"c.swsp ", dasm16_css(opcode,0,tid)};
|
||||
3'b111: return {"c.fswsp ", dasm16_css(opcode,0,tid)};
|
||||
endcase
|
||||
if(opcode[12]) begin
|
||||
if(opcode[12:2] == 0) return "c.ebreak";
|
||||
else if(opcode[6:2] == 0) return $sformatf("c.jalr %s", abi_reg[opcode[11:7]]);
|
||||
else return $sformatf("c.add %s,%s", abi_reg[opcode[11:7]], abi_reg[opcode[6:2]]);
|
||||
end
|
||||
else begin
|
||||
if(opcode[6:2] == 0) return $sformatf("c.jr %s", abi_reg[opcode[11:7]]);
|
||||
else return $sformatf("c.mv %s,%s", abi_reg[opcode[11:7]], abi_reg[opcode[6:2]]);
|
||||
end
|
||||
endfunction
|
||||
|
||||
|
||||
function string dasm16_cls( input[31:0] opcode, input sh1=0, tid=0);
|
||||
bit[31:0] imm;
|
||||
imm=0;
|
||||
if(sh1) {imm[4:3],imm[8:6]} = opcode[6:2];
|
||||
else {imm[4:2],imm[7:6]} = opcode[6:2];
|
||||
imm[5] = opcode[12];
|
||||
return $sformatf("%s,0x%0h [%h]", abi_reg[opcode[11:7]], imm, gpr[tid][2]+imm);
|
||||
endfunction
|
||||
|
||||
function string dasm16_css( input[31:0] opcode, input sh1=0, tid=0);
|
||||
bit[31:0] imm;
|
||||
imm=0;
|
||||
if(sh1) {imm[5:3],imm[8:6]} = opcode[12:7];
|
||||
else {imm[5:2],imm[7:6]} = opcode[12:7];
|
||||
return $sformatf("%s,0x%0h [%h]", abi_reg[opcode[6:2]], imm, gpr[tid][2]+imm);
|
||||
endfunction
|
||||
|
||||
///////////////// 32 bit instructions ///////////////////////
|
||||
|
||||
function string dasm32( input[31:0] opcode, input[31:0] pc, input tid=0);
|
||||
case(opcode[6:0])
|
||||
7'b0110111: return {"lui ", dasm32_u(opcode)};
|
||||
7'b0010111: return {"auipc ", dasm32_u(opcode)};
|
||||
7'b1101111: return {"jal ", dasm32_j(opcode,pc)};
|
||||
7'b1100111: return {"jalr ", dasm32_jr(opcode,pc)};
|
||||
7'b1100011: return dasm32_b(opcode,pc);
|
||||
7'b0000011: return dasm32_l(opcode,tid);
|
||||
7'b0100011: return dasm32_s(opcode,tid);
|
||||
7'b0010011: return dasm32_ai(opcode);
|
||||
7'b0110011: return dasm32_ar(opcode);
|
||||
7'b0001111: return {"fence", dasm32_fence(opcode)};
|
||||
7'b1110011: return dasm32_e(opcode);
|
||||
7'b0101111: return dasm32_a(opcode,tid);
|
||||
|
||||
endcase
|
||||
return $sformatf(".long 0x%h", opcode);
|
||||
endfunction
|
||||
|
||||
function string dasm32_u( input[31:0] opcode);
|
||||
bit[31:0] imm;
|
||||
imm=0;
|
||||
imm[31:12] = opcode[31:12];
|
||||
return $sformatf("%s,0x%0h", abi_reg[opcode[11:7]], imm);
|
||||
endfunction
|
||||
|
||||
function string dasm32_j( input[31:0] opcode, input[31:0] pc);
|
||||
int imm;
|
||||
imm=0;
|
||||
{imm[20], imm[10:1], imm[11], imm[19:12]} = opcode[31:12];
|
||||
if(opcode[31]) imm[31:20] = '1;
|
||||
return $sformatf("%s,0x%0h",abi_reg[opcode[11:7]], imm+pc);
|
||||
endfunction
|
||||
|
||||
function string dasm32_jr( input[31:0] opcode, input[31:0] pc);
|
||||
int imm;
|
||||
imm=0;
|
||||
imm[11:1] = opcode[31:19];
|
||||
if(opcode[31]) imm[31:12] = '1;
|
||||
return $sformatf("%s,%s,0x%0h",abi_reg[opcode[11:7]], abi_reg[opcode[19:15]], imm+pc);
|
||||
endfunction
|
||||
|
||||
function string dasm32_b( input[31:0] opcode, input[31:0] pc);
|
||||
int imm;
|
||||
string mn;
|
||||
imm=0;
|
||||
{imm[12],imm[10:5]} = opcode[31:25];
|
||||
{imm[4:1],imm[11]} = opcode[11:7];
|
||||
if(opcode[31]) imm[31:12] = '1;
|
||||
case(opcode[14:12])
|
||||
0: mn = "beq ";
|
||||
1: mn = "bne ";
|
||||
2,3 : return $sformatf(".long 0x%h", opcode);
|
||||
4: mn = "blt ";
|
||||
5: mn = "bge ";
|
||||
6: mn = "bltu ";
|
||||
7: mn = "bgeu ";
|
||||
endcase
|
||||
return $sformatf("%s%s,%s,0x%0h", mn, abi_reg[opcode[19:15]], abi_reg[opcode[24:20]], imm+pc);
|
||||
endfunction
|
||||
|
||||
function string dasm32_l( input[31:0] opcode, input tid=0);
|
||||
int imm;
|
||||
string mn;
|
||||
imm=0;
|
||||
imm[11:0] = opcode[31:20];
|
||||
if(opcode[31]) imm[31:12] = '1;
|
||||
case(opcode[14:12])
|
||||
0: mn = "lb ";
|
||||
1: mn = "lh ";
|
||||
2: mn = "lw ";
|
||||
4: mn = "lbu ";
|
||||
5: mn = "lhu ";
|
||||
default : return $sformatf(".long 0x%h", opcode);
|
||||
endcase
|
||||
return $sformatf("%s%s,%0d(%s) [%h]", mn, abi_reg[opcode[11:7]], imm, abi_reg[opcode[19:15]], imm+gpr[tid][opcode[19:15]]);
|
||||
endfunction
|
||||
|
||||
function string dasm32_s( input[31:0] opcode, input tid=0);
|
||||
int imm;
|
||||
string mn;
|
||||
imm=0;
|
||||
imm[11:5] = opcode[31:25];
|
||||
imm[4:0] = opcode[11:7];
|
||||
if(opcode[31]) imm[31:12] = '1;
|
||||
case(opcode[14:12])
|
||||
0: mn = "sb ";
|
||||
1: mn = "sh ";
|
||||
2: mn = "sw ";
|
||||
default : return $sformatf(".long 0x%h", opcode);
|
||||
endcase
|
||||
return $sformatf("%s%s,%0d(%s) [%h]", mn, abi_reg[opcode[24:20]], imm, abi_reg[opcode[19:15]], imm+gpr[tid][opcode[19:15]]);
|
||||
endfunction
|
||||
|
||||
function string dasm32_ai( input[31:0] opcode);
|
||||
int imm;
|
||||
string mn;
|
||||
imm=0;
|
||||
imm[11:0] = opcode[31:20];
|
||||
if(opcode[31]) imm[31:12] = '1;
|
||||
case(opcode[14:12])
|
||||
0: mn = "addi ";
|
||||
2: mn = "slti ";
|
||||
3: mn = "sltiu ";
|
||||
4: mn = "xori ";
|
||||
6: mn = "ori ";
|
||||
7: mn = "andi ";
|
||||
default: return dasm32_si(opcode);
|
||||
endcase
|
||||
|
||||
return $sformatf("%s%s,%s,%0d", mn, abi_reg[opcode[11:7]], abi_reg[opcode[19:15]], imm);
|
||||
endfunction
|
||||
|
||||
function string dasm32_si( input[31:0] opcode);
|
||||
int imm;
|
||||
string mn;
|
||||
imm = opcode[24:20];
|
||||
case(opcode[14:12])
|
||||
1: mn = "slli";
|
||||
5: mn = opcode[30] ? "srli": "srai";
|
||||
endcase
|
||||
|
||||
return $sformatf("%s %s,%s,%0d", mn, abi_reg[opcode[11:7]], abi_reg[opcode[19:15]], imm);
|
||||
endfunction
|
||||
|
||||
|
||||
|
||||
function string dasm32_ar( input[31:0] opcode);
|
||||
string mn;
|
||||
if(opcode[25])
|
||||
case(opcode[14:12])
|
||||
0: mn = "mul ";
|
||||
1: mn = "mulh ";
|
||||
2: mn = "mulhsu ";
|
||||
3: mn = "mulhu ";
|
||||
4: mn = "div ";
|
||||
5: mn = "divu ";
|
||||
6: mn = "rem ";
|
||||
7: mn = "remu ";
|
||||
endcase
|
||||
else
|
||||
case(opcode[14:12])
|
||||
0: mn = opcode[30]? "sub ":"add ";
|
||||
1: mn = "sll ";
|
||||
2: mn = "slt ";
|
||||
3: mn = "sltu ";
|
||||
4: mn = "xor ";
|
||||
5: mn = opcode[30]? "sra ":"srl ";
|
||||
6: mn = "or ";
|
||||
7: mn = "and ";
|
||||
endcase
|
||||
return $sformatf("%s%s,%s,%s", mn, abi_reg[opcode[11:7]], abi_reg[opcode[19:15]], abi_reg[opcode[24:20]]);
|
||||
endfunction
|
||||
|
||||
function string dasm32_fence( input[31:0] opcode);
|
||||
return opcode[12] ? ".i" : "";
|
||||
endfunction
|
||||
|
||||
function string dasm32_e(input[31:0] opcode);
|
||||
if(opcode[31:7] == 0) return "ecall";
|
||||
else if({opcode[31:21],opcode [19:7]} == 0) return "ebreak";
|
||||
else
|
||||
case(opcode[14:12])
|
||||
1: return {"csrrw ", dasm32_csr(opcode)};
|
||||
2: return {"csrrs ", dasm32_csr(opcode)};
|
||||
3: return {"csrrc ", dasm32_csr(opcode)};
|
||||
5: return {"csrrwi ", dasm32_csr(opcode, 1)};
|
||||
6: return {"csrrsi ", dasm32_csr(opcode, 1)};
|
||||
7: return {"csrrci ", dasm32_csr(opcode, 1)};
|
||||
endcase
|
||||
|
||||
endfunction
|
||||
|
||||
|
||||
function string dasm32_csr(input[31:0] opcode, input im=0);
|
||||
bit[11:0] csr;
|
||||
csr = opcode[31:20];
|
||||
if(im) begin
|
||||
return $sformatf("%s,csr_%0h,0x%h", abi_reg[opcode[11:7]], csr, opcode[19:15]);
|
||||
end
|
||||
else begin
|
||||
return $sformatf("%s,csr_%0h,%s", abi_reg[opcode[11:7]], csr, abi_reg[opcode[19:15]]);
|
||||
end
|
||||
|
||||
endfunction
|
||||
|
||||
//atomics
|
||||
function string dasm32_a(input[31:0] opcode, input tid=0);
|
||||
case(opcode[31:27])
|
||||
'b00010: return $sformatf("lr.w %s,(%s) [%h]", abi_reg[opcode[11:7]], abi_reg[opcode[19:15]], gpr[tid][opcode[19:15]]);
|
||||
'b00011: return $sformatf("sc.w %s,%s,(%s) [%h]", abi_reg[opcode[11:7]], abi_reg[opcode[24:20]], abi_reg[opcode[19:15]], gpr[tid][opcode[19:15]]);
|
||||
'b00001: return {"amoswap.w", dasm32_amo(opcode, tid)};
|
||||
'b00000: return {"amoadd.w", dasm32_amo(opcode, tid)};
|
||||
'b00100: return {"amoxor.w", dasm32_amo(opcode, tid)};
|
||||
'b01100: return {"amoand.w", dasm32_amo(opcode, tid)};
|
||||
'b01000: return {"amoor.w", dasm32_amo(opcode, tid)};
|
||||
'b10000: return {"amomin.w", dasm32_amo(opcode, tid)};
|
||||
'b10100: return {"amomax.w", dasm32_amo(opcode, tid)};
|
||||
'b11000: return {"amominu.w", dasm32_amo(opcode, tid)};
|
||||
'b11100: return {"amomaxu.w", dasm32_amo(opcode, tid)};
|
||||
endcase
|
||||
return $sformatf(".long 0x%h", opcode);
|
||||
endfunction
|
||||
|
||||
function string dasm32_amo( input[31:0] opcode, input tid=0);
|
||||
return $sformatf(" %s,%s,(%s) [%h]", abi_reg[opcode[11:7]], abi_reg[opcode[24:20]], abi_reg[opcode[19:15]], gpr[tid][opcode[19:15]]);
|
||||
endfunction
|
|
@ -0,0 +1,437 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#include "tcp_server.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/**
|
||||
* Simple buffer for passing data between TCP sockets and DPI modules
|
||||
*/
|
||||
const int BUFSIZE_BYTE = 25600;
|
||||
|
||||
struct tcp_buf {
|
||||
unsigned int rptr;
|
||||
unsigned int wptr;
|
||||
char buf[BUFSIZE_BYTE];
|
||||
};
|
||||
|
||||
/**
|
||||
* TCP Server thread context structure
|
||||
*/
|
||||
struct tcp_server_ctx {
|
||||
// Writeable by the host thread
|
||||
char *display_name;
|
||||
uint16_t listen_port;
|
||||
volatile bool socket_run;
|
||||
// Writeable by the server thread
|
||||
tcp_buf *buf_in;
|
||||
tcp_buf *buf_out;
|
||||
int sfd; // socket fd
|
||||
int cfd; // client fd
|
||||
pthread_t sock_thread;
|
||||
};
|
||||
|
||||
static bool tcp_buffer_is_full(struct tcp_buf *buf) {
|
||||
if (buf->wptr >= buf->rptr) {
|
||||
return (buf->wptr - buf->rptr) == (BUFSIZE_BYTE - 1);
|
||||
} else {
|
||||
return (buf->rptr - buf->wptr) == 1;
|
||||
}
|
||||
}
|
||||
|
||||
static bool tcp_buffer_is_empty(struct tcp_buf *buf) {
|
||||
return (buf->wptr == buf->rptr);
|
||||
}
|
||||
|
||||
static void tcp_buffer_put_byte(struct tcp_buf *buf, char dat) {
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
if (!tcp_buffer_is_full(buf)) {
|
||||
buf->buf[buf->wptr++] = dat;
|
||||
buf->wptr %= BUFSIZE_BYTE;
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool tcp_buffer_get_byte(struct tcp_buf *buf, char *dat) {
|
||||
if (tcp_buffer_is_empty(buf)) {
|
||||
return false;
|
||||
}
|
||||
*dat = buf->buf[buf->rptr++];
|
||||
buf->rptr %= BUFSIZE_BYTE;
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct tcp_buf *tcp_buffer_new(void) {
|
||||
struct tcp_buf *buf_new;
|
||||
buf_new = (struct tcp_buf *)malloc(sizeof(struct tcp_buf));
|
||||
buf_new->rptr = 0;
|
||||
buf_new->wptr = 0;
|
||||
return buf_new;
|
||||
}
|
||||
|
||||
static void tcp_buffer_free(struct tcp_buf **buf) {
|
||||
free(*buf);
|
||||
*buf = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a TCP server
|
||||
*
|
||||
* This function creates attempts to create a new TCP socket instance. The
|
||||
* socket is a non-blocking stream socket, with buffering disabled.
|
||||
*
|
||||
* @param ctx context object
|
||||
* @return 0 on success, -1 in case of an error
|
||||
*/
|
||||
static int start(struct tcp_server_ctx *ctx) {
|
||||
int rv;
|
||||
|
||||
assert(ctx->sfd == 0 && "Server already started.");
|
||||
|
||||
// create socket
|
||||
int sfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sfd == -1) {
|
||||
fprintf(stderr, "%s: Unable to create socket: %s (%d)\n", ctx->display_name,
|
||||
strerror(errno), errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rv = fcntl(sfd, F_SETFL, O_NONBLOCK);
|
||||
if (rv != 0) {
|
||||
fprintf(stderr, "%s: Unable to make socket non-blocking: %s (%d)\n",
|
||||
ctx->display_name, strerror(errno), errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// reuse existing socket (if existing)
|
||||
int reuse_socket = 1;
|
||||
rv = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse_socket, sizeof(int));
|
||||
if (rv != 0) {
|
||||
fprintf(stderr, "%s: Unable to set socket options: %s (%d)\n",
|
||||
ctx->display_name, strerror(errno), errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// stop tcp socket from buffering (buffering prevents timely responses to
|
||||
// OpenOCD which severly limits debugging performance)
|
||||
int tcp_nodelay = 1;
|
||||
rv = setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, &tcp_nodelay, sizeof(int));
|
||||
if (rv != 0) {
|
||||
fprintf(stderr, "%s: Unable to set socket nodelay: %s (%d)\n",
|
||||
ctx->display_name, strerror(errno), errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// bind server
|
||||
struct sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
addr.sin_port = htons(ctx->listen_port);
|
||||
|
||||
rv = bind(sfd, (struct sockaddr *)&addr, sizeof(addr));
|
||||
if (rv != 0) {
|
||||
fprintf(stderr, "%s: Failed to bind socket: %s (%d)\n", ctx->display_name,
|
||||
strerror(errno), errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// listen for incoming connections
|
||||
rv = listen(sfd, 1);
|
||||
if (rv != 0) {
|
||||
fprintf(stderr, "%s: Failed to listen on socket: %s (%d)\n",
|
||||
ctx->display_name, strerror(errno), errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->sfd = sfd;
|
||||
assert(ctx->sfd > 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept an incoming connection from a client (nonblocking)
|
||||
*
|
||||
* The resulting client fd is made non-blocking.
|
||||
*
|
||||
* @param ctx context object
|
||||
* @return 0 on success, any other value indicates an error
|
||||
*/
|
||||
static int client_tryaccept(struct tcp_server_ctx *ctx) {
|
||||
int rv;
|
||||
|
||||
assert(ctx->sfd > 0);
|
||||
assert(ctx->cfd == 0);
|
||||
|
||||
int cfd = accept(ctx->sfd, NULL, NULL);
|
||||
|
||||
if (cfd == -1 && errno == EAGAIN) {
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (cfd == -1) {
|
||||
fprintf(stderr, "%s: Unable to accept incoming connection: %s (%d)\n",
|
||||
ctx->display_name, strerror(errno), errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rv = fcntl(cfd, F_SETFL, O_NONBLOCK);
|
||||
if (rv != 0) {
|
||||
fprintf(stderr, "%s: Unable to make client socket non-blocking: %s (%d)\n",
|
||||
ctx->display_name, strerror(errno), errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->cfd = cfd;
|
||||
assert(ctx->cfd > 0);
|
||||
|
||||
printf("%s: Accepted client connection\n", ctx->display_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the TCP server
|
||||
*
|
||||
* @param ctx context object
|
||||
*/
|
||||
static void stop(struct tcp_server_ctx *ctx) {
|
||||
assert(ctx);
|
||||
if (!ctx->sfd) {
|
||||
return;
|
||||
}
|
||||
close(ctx->sfd);
|
||||
ctx->sfd = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive a byte from a connected client
|
||||
*
|
||||
* @param ctx context object
|
||||
* @param cmd byte received
|
||||
* @return true if a byte was read
|
||||
*/
|
||||
static bool get_byte(struct tcp_server_ctx *ctx, char *cmd) {
|
||||
assert(ctx);
|
||||
|
||||
ssize_t num_read = read(ctx->cfd, cmd, 1);
|
||||
|
||||
if (num_read == 0) {
|
||||
return false;
|
||||
}
|
||||
if (num_read == -1) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
return false;
|
||||
} else if (errno == EBADF) {
|
||||
// Possibly client went away? Accept a new connection.
|
||||
fprintf(stderr, "%s: Client disappeared.\n", ctx->display_name);
|
||||
tcp_server_client_close(ctx);
|
||||
return false;
|
||||
} else {
|
||||
fprintf(stderr, "%s: Error while reading from client: %s (%d)\n",
|
||||
ctx->display_name, strerror(errno), errno);
|
||||
assert(0 && "Error reading from client");
|
||||
}
|
||||
}
|
||||
assert(num_read == 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a byte to a connected client
|
||||
*
|
||||
* @param ctx context object
|
||||
* @param cmd byte to send
|
||||
*/
|
||||
static void put_byte(struct tcp_server_ctx *ctx, char cmd) {
|
||||
while (1) {
|
||||
ssize_t num_written = send(ctx->cfd, &cmd, sizeof(cmd), MSG_NOSIGNAL);
|
||||
if (num_written == -1) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
continue;
|
||||
} else if (errno == EPIPE) {
|
||||
printf("%s: Remote disconnected.\n", ctx->display_name);
|
||||
tcp_server_client_close(ctx);
|
||||
break;
|
||||
} else {
|
||||
fprintf(stderr, "%s: Error while writing to client: %s (%d)\n",
|
||||
ctx->display_name, strerror(errno), errno);
|
||||
assert(0 && "Error writing to client.");
|
||||
}
|
||||
}
|
||||
if (num_written >= 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup server context
|
||||
*
|
||||
* @param ctx context object
|
||||
*/
|
||||
static void ctx_free(struct tcp_server_ctx *ctx) {
|
||||
// Free the buffers
|
||||
tcp_buffer_free(&ctx->buf_in);
|
||||
tcp_buffer_free(&ctx->buf_out);
|
||||
// Free the display name
|
||||
free(ctx->display_name);
|
||||
// Free the ctx
|
||||
free(ctx);
|
||||
ctx = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread function to create a new server instance
|
||||
*
|
||||
* @param ctx_void context object
|
||||
* @return Always returns NULL
|
||||
*/
|
||||
static void *server_create(void *ctx_void) {
|
||||
// Cast to a server struct
|
||||
struct tcp_server_ctx *ctx = (struct tcp_server_ctx *)ctx_void;
|
||||
struct timeval timeout;
|
||||
|
||||
// Start the server
|
||||
int rv = start(ctx);
|
||||
if (rv != 0) {
|
||||
fprintf(stderr, "%s: Unable to create TCP server on port %d\n",
|
||||
ctx->display_name, ctx->listen_port);
|
||||
goto err_cleanup_return;
|
||||
}
|
||||
|
||||
// Initialise timeout
|
||||
timeout.tv_sec = 0;
|
||||
|
||||
// Initialise fd_set
|
||||
|
||||
// Start waiting for connection / data
|
||||
char xfer_data;
|
||||
while (ctx->socket_run) {
|
||||
// Initialise structure of fds
|
||||
fd_set read_fds;
|
||||
FD_ZERO(&read_fds);
|
||||
if (ctx->sfd) {
|
||||
FD_SET(ctx->sfd, &read_fds);
|
||||
}
|
||||
if (ctx->cfd) {
|
||||
FD_SET(ctx->cfd, &read_fds);
|
||||
}
|
||||
// max fd num
|
||||
int mfd = (ctx->cfd > ctx->sfd) ? ctx->cfd : ctx->sfd;
|
||||
|
||||
// Set timeout - 50us gives good performance
|
||||
timeout.tv_usec = 50;
|
||||
|
||||
// Wait for socket activity or timeout
|
||||
rv = select(mfd + 1, &read_fds, NULL, NULL, &timeout);
|
||||
|
||||
if (rv < 0) {
|
||||
printf("%s: Socket read failed, port: %d\n", ctx->display_name,
|
||||
ctx->listen_port);
|
||||
tcp_server_client_close(ctx);
|
||||
}
|
||||
|
||||
// New connection
|
||||
if (FD_ISSET(ctx->sfd, &read_fds)) {
|
||||
client_tryaccept(ctx);
|
||||
}
|
||||
|
||||
// New client data
|
||||
if (FD_ISSET(ctx->cfd, &read_fds)) {
|
||||
while (get_byte(ctx, &xfer_data)) {
|
||||
tcp_buffer_put_byte(ctx->buf_in, xfer_data);
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->cfd != 0) {
|
||||
while (tcp_buffer_get_byte(ctx->buf_out, &xfer_data)) {
|
||||
put_byte(ctx, xfer_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err_cleanup_return:
|
||||
|
||||
// Simulation done - clean up
|
||||
tcp_server_client_close(ctx);
|
||||
stop(ctx);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Abstract interface functions
|
||||
tcp_server_ctx *tcp_server_create(const char *display_name, int listen_port) {
|
||||
struct tcp_server_ctx *ctx =
|
||||
(struct tcp_server_ctx *)calloc(1, sizeof(struct tcp_server_ctx));
|
||||
assert(ctx);
|
||||
|
||||
// Create the buffers
|
||||
struct tcp_buf *buf_in = tcp_buffer_new();
|
||||
struct tcp_buf *buf_out = tcp_buffer_new();
|
||||
assert(buf_in);
|
||||
assert(buf_out);
|
||||
|
||||
// Populate the struct with buffer pointers
|
||||
ctx->buf_in = buf_in;
|
||||
ctx->buf_out = buf_out;
|
||||
|
||||
// Set up socket details
|
||||
ctx->socket_run = true;
|
||||
ctx->listen_port = listen_port;
|
||||
ctx->display_name = strdup(display_name);
|
||||
assert(ctx->display_name);
|
||||
|
||||
if (pthread_create(&ctx->sock_thread, NULL, server_create, (void *)ctx) !=
|
||||
0) {
|
||||
fprintf(stderr, "%s: Unable to create TCP socket thread\n",
|
||||
ctx->display_name);
|
||||
ctx_free(ctx);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
bool tcp_server_read(struct tcp_server_ctx *ctx, char *dat) {
|
||||
return tcp_buffer_get_byte(ctx->buf_in, dat);
|
||||
}
|
||||
|
||||
void tcp_server_write(struct tcp_server_ctx *ctx, char dat) {
|
||||
tcp_buffer_put_byte(ctx->buf_out, dat);
|
||||
}
|
||||
|
||||
void tcp_server_close(struct tcp_server_ctx *ctx) {
|
||||
// Shut down the socket thread
|
||||
ctx->socket_run = false;
|
||||
pthread_join(ctx->sock_thread, NULL);
|
||||
ctx_free(ctx);
|
||||
}
|
||||
|
||||
void tcp_server_client_close(struct tcp_server_ctx *ctx) {
|
||||
assert(ctx);
|
||||
|
||||
if (!ctx->cfd) {
|
||||
return;
|
||||
}
|
||||
|
||||
close(ctx->cfd);
|
||||
ctx->cfd = 0;
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/**
|
||||
* Functions to create and interact with a threaded TCP server
|
||||
*
|
||||
* This is intended to be used by simulation add-on DPI modules to provide
|
||||
* basic TCP socket communication between a host and simulated peripherals.
|
||||
*/
|
||||
|
||||
#ifndef TCP_SERVER_H_
|
||||
#define TCP_SERVER_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct tcp_server_ctx;
|
||||
|
||||
/**
|
||||
* Non-blocking read of a byte from a connected client
|
||||
*
|
||||
* @param ctx tcp server context object
|
||||
* @param dat byte received
|
||||
* @return true if a byte was read
|
||||
*/
|
||||
bool tcp_server_read(struct tcp_server_ctx *ctx, char *dat);
|
||||
|
||||
/**
|
||||
* Write a byte to a connected client
|
||||
*
|
||||
* The write is internally buffered and so does not block if the client is not
|
||||
* ready to accept data, but does block if the buffer is full.
|
||||
*
|
||||
* @param ctx tcp server context object
|
||||
* @param dat byte to send
|
||||
*/
|
||||
void tcp_server_write(struct tcp_server_ctx *ctx, char dat);
|
||||
|
||||
/**
|
||||
* Create a new TCP server instance
|
||||
*
|
||||
* @param display_name C string description of server
|
||||
* @param listen_port On which port the server should listen
|
||||
* @return A pointer to the created context struct
|
||||
*/
|
||||
tcp_server_ctx *tcp_server_create(const char *display_name, int listen_port);
|
||||
|
||||
/**
|
||||
* Shut down the server and free all reserved memory
|
||||
*
|
||||
* @param ctx tcp server context object
|
||||
*/
|
||||
void tcp_server_close(struct tcp_server_ctx *ctx);
|
||||
|
||||
/**
|
||||
* Instruct the server to disconnect a client
|
||||
*
|
||||
* @param ctx tcp server context object
|
||||
*/
|
||||
void tcp_server_client_close(struct tcp_server_ctx *ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
#endif // TCP_SERVER_H_
|
|
@ -0,0 +1,154 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#include "jtagdpi.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../common/tcp_server.h"
|
||||
|
||||
struct jtagdpi_ctx {
|
||||
// Server context
|
||||
struct tcp_server_ctx *sock;
|
||||
// Signals
|
||||
uint8_t tck;
|
||||
uint8_t tms;
|
||||
uint8_t tdi;
|
||||
uint8_t tdo;
|
||||
uint8_t trst_n;
|
||||
uint8_t srst_n;
|
||||
};
|
||||
|
||||
/**
|
||||
* Reset the JTAG signals to a "dongle unplugged" state
|
||||
*/
|
||||
static void reset_jtag_signals(struct jtagdpi_ctx *ctx) {
|
||||
assert(ctx);
|
||||
|
||||
ctx->tck = 0;
|
||||
ctx->tms = 0;
|
||||
ctx->tdi = 0;
|
||||
|
||||
// trst_n is pulled down (reset active) by default
|
||||
ctx->trst_n = 0;
|
||||
|
||||
// srst_n is pulled up (reset not active) by default
|
||||
ctx->srst_n = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the JTAG signals in the context structure
|
||||
*/
|
||||
static void update_jtag_signals(struct jtagdpi_ctx *ctx) {
|
||||
assert(ctx);
|
||||
|
||||
/*
|
||||
* Documentation pointer:
|
||||
* The remote_bitbang protocol implemented below is documented in the OpenOCD
|
||||
* source tree at doc/manual/jtag/drivers/remote_bitbang.txt, or online at
|
||||
* https://repo.or.cz/openocd.git/blob/HEAD:/doc/manual/jtag/drivers/remote_bitbang.txt
|
||||
*/
|
||||
|
||||
// read a command byte
|
||||
char cmd;
|
||||
if (!tcp_server_read(ctx->sock, &cmd)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool act_send_resp = false;
|
||||
bool act_quit = false;
|
||||
|
||||
// parse received command byte
|
||||
if (cmd >= '0' && cmd <= '7') {
|
||||
// JTAG write
|
||||
char cmd_bit = cmd - '0';
|
||||
ctx->tdi = (cmd_bit >> 0) & 0x1;
|
||||
ctx->tms = (cmd_bit >> 1) & 0x1;
|
||||
ctx->tck = (cmd_bit >> 2) & 0x1;
|
||||
} else if (cmd >= 'r' && cmd <= 'u') {
|
||||
// JTAG reset (active high from OpenOCD)
|
||||
char cmd_bit = cmd - 'r';
|
||||
ctx->srst_n = !((cmd_bit >> 0) & 0x1);
|
||||
ctx->trst_n = !((cmd_bit >> 1) & 0x1);
|
||||
} else if (cmd == 'R') {
|
||||
// JTAG read
|
||||
act_send_resp = true;
|
||||
} else if (cmd == 'B') {
|
||||
// printf("%s: BLINK ON!\n", ctx->display_name);
|
||||
} else if (cmd == 'b') {
|
||||
// printf("%s: BLINK OFF!\n", ctx->display_name);
|
||||
} else if (cmd == 'Q') {
|
||||
// quit (client disconnect)
|
||||
act_quit = true;
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"JTAG DPI Protocol violation detected: unsupported command %c\n",
|
||||
cmd);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// send tdo as response
|
||||
if (act_send_resp) {
|
||||
char tdo_ascii = ctx->tdo + '0';
|
||||
tcp_server_write(ctx->sock, tdo_ascii);
|
||||
}
|
||||
|
||||
if (act_quit) {
|
||||
printf("JTAG DPI: Remote disconnected.\n");
|
||||
tcp_server_client_close(ctx->sock);
|
||||
}
|
||||
}
|
||||
|
||||
void *jtagdpi_create(const char *display_name, int listen_port) {
|
||||
struct jtagdpi_ctx *ctx =
|
||||
(struct jtagdpi_ctx *)calloc(1, sizeof(struct jtagdpi_ctx));
|
||||
assert(ctx);
|
||||
|
||||
// Create socket
|
||||
ctx->sock = tcp_server_create(display_name, listen_port);
|
||||
|
||||
reset_jtag_signals(ctx);
|
||||
|
||||
printf(
|
||||
"\n"
|
||||
"JTAG: Virtual JTAG interface %s is listening on port %d. Use\n"
|
||||
"OpenOCD and the following configuration to connect:\n"
|
||||
" interface remote_bitbang\n"
|
||||
" remote_bitbang_host localhost\n"
|
||||
" remote_bitbang_port %d\n",
|
||||
display_name, listen_port, listen_port);
|
||||
|
||||
return (void *)ctx;
|
||||
}
|
||||
|
||||
void jtagdpi_close(void *ctx_void) {
|
||||
struct jtagdpi_ctx *ctx = (struct jtagdpi_ctx *)ctx_void;
|
||||
if (!ctx) {
|
||||
return;
|
||||
}
|
||||
tcp_server_close(ctx->sock);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
void jtagdpi_tick(void *ctx_void, svBit *tck, svBit *tms, svBit *tdi,
|
||||
svBit *trst_n, svBit *srst_n, const svBit tdo) {
|
||||
struct jtagdpi_ctx *ctx = (struct jtagdpi_ctx *)ctx_void;
|
||||
|
||||
ctx->tdo = tdo;
|
||||
|
||||
// TODO: Evaluate moving this functionality into a separate thread
|
||||
if (ctx) {
|
||||
update_jtag_signals(ctx);
|
||||
}
|
||||
|
||||
*tdi = ctx->tdi;
|
||||
*tms = ctx->tms;
|
||||
*tck = ctx->tck;
|
||||
*srst_n = ctx->srst_n;
|
||||
*trst_n = ctx->trst_n;
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#ifndef JTAGDPI_H_
|
||||
#define JTAGDPI_H_
|
||||
|
||||
#include <svdpi.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct jtagdpi_ctx;
|
||||
|
||||
/**
|
||||
* Constructor: Create and initialize jtagdpi context object
|
||||
*
|
||||
* Call from a initial block.
|
||||
*
|
||||
* @param display_name Name of the JTAG interface (for display purposes only)
|
||||
* @param listen_port Port to listen on
|
||||
* @return an initialized struct jtagdpi_ctx context object
|
||||
*/
|
||||
void *jtagdpi_create(const char *display_name, int listen_port);
|
||||
|
||||
/**
|
||||
* Destructor: Close all connections and free all resources
|
||||
*
|
||||
* Call from a finish block.
|
||||
*
|
||||
* @param ctx_void a struct jtagdpi_ctx context object
|
||||
*/
|
||||
void jtagdpi_close(void *ctx_void);
|
||||
|
||||
/**
|
||||
* Drive JTAG signals
|
||||
*
|
||||
* Call this function from the simulation at every clock tick to read/write
|
||||
* from/to the JTAG signals.
|
||||
*
|
||||
* @param ctx_void a struct jtagdpi_ctx context object
|
||||
* @param tck JTAG test clock signal
|
||||
* @param tms JTAG test mode select signal
|
||||
* @param tdi JTAG test data input signal
|
||||
* @param trst_n JTAG test reset signal (active low)
|
||||
* @param srst_n JTAG system reset signal (active low)
|
||||
* @param tdo JTAG test data out
|
||||
*/
|
||||
void jtagdpi_tick(void *ctx_void, svBit *tck, svBit *tms, svBit *tdi,
|
||||
svBit *trst_n, svBit *srst_n, const svBit tdo);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
#endif // JTAGDPI_H_
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
module jtagdpi #(
|
||||
parameter string Name = "jtag0", // name of the JTAG interface (display only)
|
||||
parameter int ListenPort = 44853 // TCP port to listen on
|
||||
)(
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
output logic jtag_tck,
|
||||
output logic jtag_tms,
|
||||
output logic jtag_tdi,
|
||||
input logic jtag_tdo,
|
||||
output logic jtag_trst_n,
|
||||
output logic jtag_srst_n
|
||||
);
|
||||
|
||||
import "DPI-C"
|
||||
function chandle jtagdpi_create(input string name, input int listen_port);
|
||||
|
||||
import "DPI-C"
|
||||
function void jtagdpi_tick(input chandle ctx, output bit tck, output bit tms,
|
||||
output bit tdi, output bit trst_n,
|
||||
output bit srst_n, input bit tdo);
|
||||
|
||||
import "DPI-C"
|
||||
function void jtagdpi_close(input chandle ctx);
|
||||
|
||||
chandle ctx;
|
||||
|
||||
initial begin
|
||||
ctx = jtagdpi_create(Name, ListenPort);
|
||||
end
|
||||
|
||||
final begin
|
||||
jtagdpi_close(ctx);
|
||||
ctx = 0;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i, negedge rst_ni) begin
|
||||
jtagdpi_tick(ctx, jtag_tck, jtag_tms, jtag_tdi, jtag_trst_n, jtag_srst_n,
|
||||
jtag_tdo);
|
||||
end
|
||||
|
||||
endmodule
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,9 @@
|
|||
-I../design/include
|
||||
-I./
|
||||
|
||||
-CFLAGS -lpthread
|
||||
-LDFLAGS -lpthread
|
||||
|
||||
./dpi/common/tcp_server.c
|
||||
./dpi/jtagdpi/jtagdpi.sv
|
||||
./dpi/jtagdpi/jtagdpi.c
|
|
@ -0,0 +1,416 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 Western Digital Corporation or its affiliates.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
module soc_sim (
|
||||
input bit core_clk
|
||||
);
|
||||
|
||||
logic rst_l;
|
||||
logic dbg_rst_l;
|
||||
|
||||
wire jtag_tdo;
|
||||
wire jtag_tck;
|
||||
wire jtag_tms;
|
||||
wire jtag_tdi;
|
||||
wire jtag_trst_n;
|
||||
|
||||
bit [31:0] cycleCnt;
|
||||
logic mailbox_data_val;
|
||||
int commit_count;
|
||||
|
||||
logic wb_valid;
|
||||
logic [ 4:0] wb_dest;
|
||||
logic [31:0] wb_data;
|
||||
|
||||
wire [63:0] WriteData;
|
||||
string abi_reg [32]; // ABI register names
|
||||
|
||||
assign WriteData = rvsoc.lsu_axi_wdata;
|
||||
assign mailbox_data_val = WriteData[7:0] > 8'h5 && WriteData[7:0] < 8'h7f;
|
||||
|
||||
parameter MAILBOX_ADDR = 32'hD0580000;
|
||||
logic write;
|
||||
logic [31:0] laddr;
|
||||
|
||||
wire mailbox_write = rvsoc.lmem_axi_awvalid && rvsoc.lsu_axi_awaddr == MAILBOX_ADDR && rst_l;
|
||||
always @(posedge core_clk or negedge rst_l) begin
|
||||
if (~rst_l) begin
|
||||
laddr <= 32'b0;
|
||||
write <= 1'b0;
|
||||
end else begin
|
||||
if (rvsoc.lsu_hready) begin
|
||||
laddr <= rvsoc.lsu_haddr;
|
||||
write <= rvsoc.lsu_hwrite & |rvsoc.lsu_htrans;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
parameter MAX_CYCLES = 10_000_000_0;
|
||||
|
||||
integer fd, tp, el, pic, lsu, ifu, dec, exu;
|
||||
|
||||
always @(posedge core_clk) begin
|
||||
cycleCnt <= cycleCnt + 1;
|
||||
|
||||
if (cycleCnt == MAX_CYCLES) begin
|
||||
$display("Hit max cycle count (%0d) .. stopping", cycleCnt);
|
||||
$finish;
|
||||
end
|
||||
if (mailbox_data_val & mailbox_write) begin
|
||||
$fwrite(fd, "%c", WriteData[7:0]);
|
||||
$write("%c", WriteData[7:0]);
|
||||
end
|
||||
if (mailbox_write && WriteData[7:0] == 8'hff) begin
|
||||
$display("\nFinished : minstret = %0d, mcycle = %0d",
|
||||
rvsoc.rvtop.core.dec.tlu.csr.minstretl[31:0],
|
||||
rvsoc.rvtop.core.dec.tlu.csr.mcyclel[31:0]);
|
||||
$display(
|
||||
"See \"exec.log\" for execution trace with register updates..\n");
|
||||
$display("TEST_PASSED");
|
||||
$finish;
|
||||
end else if (mailbox_write && WriteData[7:0] == 8'h1) begin
|
||||
$display("TEST_FAILED");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
// trace monitor
|
||||
always @(posedge core_clk) begin
|
||||
wb_valid <= rvsoc.rvtop.core.dec.decode_io_dec_i0_wen_r;
|
||||
wb_dest <= rvsoc.rvtop.core.dec.decode_io_dec_i0_waddr_r;
|
||||
wb_data <= rvsoc.rvtop.core.dec.decode_io_dec_i0_wdata_r;
|
||||
if (rvsoc.trace_rv_i_valid_ip) begin
|
||||
$fwrite(tp, "%b,%h,%h,%0h,%0h,3,%b,%h,%h,%b\n", rvsoc.trace_rv_i_valid_ip,
|
||||
0, rvsoc.trace_rv_i_address_ip, 0, rvsoc.trace_rv_i_insn_ip,
|
||||
rvsoc.trace_rv_i_exception_ip, rvsoc.trace_rv_i_ecause_ip,
|
||||
rvsoc.trace_rv_i_tval_ip, rvsoc.trace_rv_i_interrupt_ip);
|
||||
// Basic trace - no exception register updates
|
||||
// #1 0 ee000000 b0201073 c 0b02 00000000
|
||||
commit_count++;
|
||||
$fwrite(el, "%10d : %8s 0 %h %h%13s ; %s\n", cycleCnt, $sformatf(
|
||||
"#%0d", commit_count), rvsoc.trace_rv_i_address_ip,
|
||||
rvsoc.trace_rv_i_insn_ip, (wb_dest != 0 && wb_valid) ? $sformatf(
|
||||
"%s=%h", abi_reg[wb_dest], wb_data) : " ", dasm(
|
||||
rvsoc.trace_rv_i_insn_ip,
|
||||
rvsoc.trace_rv_i_address_ip,
|
||||
wb_dest & {5{wb_valid}},
|
||||
wb_data
|
||||
));
|
||||
end
|
||||
if (rvsoc.rvtop.core.dec.decode_io_dec_nonblock_load_wen)
|
||||
$fwrite(el, "%10d : %32s=%h ; nbL\n", cycleCnt,
|
||||
abi_reg[rvsoc.rvtop.core.dec.decode_io_dec_nonblock_load_waddr],
|
||||
rvsoc.rvtop.core.dec.io_lsu_nonblock_load_data);
|
||||
if (rvsoc.rvtop.core.dec.io_exu_div_wren)
|
||||
$fwrite(el, "%10d : %32s=%h ; nbD\n", cycleCnt,
|
||||
abi_reg[rvsoc.rvtop.core.dec.decode_io_div_waddr_wb],
|
||||
rvsoc.rvtop.core.dec.io_exu_div_result);
|
||||
end
|
||||
|
||||
|
||||
//////////////////////////////////////////////////pic tracer///////////////////////////////////////////////////////
|
||||
always @(posedge core_clk) begin
|
||||
|
||||
if (rvsoc.rvtop.core.pic_ctrl_inst.io_lsu_pic_picm_wren == 1) begin
|
||||
$fwrite(pic, "%0d,%0d,%h\t",
|
||||
rvsoc.rvtop.core.pic_ctrl_inst.io_lsu_pic_picm_wren,
|
||||
rvsoc.rvtop.core.pic_ctrl_inst.io_lsu_pic_picm_wraddr,
|
||||
rvsoc.rvtop.core.pic_ctrl_inst.io_lsu_pic_picm_wr_data);
|
||||
|
||||
end else if (rvsoc.rvtop.core.pic_ctrl_inst.io_lsu_pic_picm_rden == 1)
|
||||
$fwrite(pic, "x\tx\tx\t");
|
||||
|
||||
if (rvsoc.rvtop.core.pic_ctrl_inst.io_lsu_pic_picm_rden == 1) begin
|
||||
$fwrite(pic, "%0d,%0d,%h\n",
|
||||
rvsoc.rvtop.core.pic_ctrl_inst.io_lsu_pic_picm_rden,
|
||||
rvsoc.rvtop.core.pic_ctrl_inst.io_lsu_pic_picm_rdaddr,
|
||||
rvsoc.rvtop.core.pic_ctrl_inst.io_lsu_pic_picm_rd_data);
|
||||
|
||||
end else if (rvsoc.rvtop.core.pic_ctrl_inst.io_lsu_pic_picm_wren == 1)
|
||||
$fwrite(pic, "x\tx\tx\t\n");
|
||||
end
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////LSU tracer///////////////////////////////////////////////////////
|
||||
always @(posedge core_clk) begin
|
||||
|
||||
if (rvsoc.rvtop.core.lsu.io_dccm_wren == 1) begin
|
||||
$fwrite(lsu, "%0h,%0h,%0h,%0h,%0h\t", rvsoc.rvtop.core.lsu.io_dccm_wren,
|
||||
rvsoc.rvtop.core.lsu.io_dccm_wr_addr_hi,
|
||||
rvsoc.rvtop.core.lsu.io_dccm_wr_addr_lo,
|
||||
rvsoc.rvtop.core.lsu.io_dccm_wr_data_hi,
|
||||
rvsoc.rvtop.core.lsu.io_dccm_wr_data_lo);
|
||||
|
||||
end
|
||||
else if(rvsoc.rvtop.core.lsu.io_dccm_rden == 1 || rvsoc.rvtop.core.lsu.io_lsu_dma_dma_dccm_ctl_dccm_dma_rvalid)
|
||||
$fwrite(lsu, "x\tx\tx\tx\tx\t");
|
||||
|
||||
if (rvsoc.rvtop.core.lsu.io_dccm_rden == 1) begin
|
||||
$fwrite(lsu, "%0h,%0h,%0h,%0h,%0h\t", rvsoc.rvtop.core.lsu.io_dccm_rden,
|
||||
rvsoc.rvtop.core.lsu.io_dccm_rd_addr_hi,
|
||||
rvsoc.rvtop.core.lsu.io_dccm_rd_addr_lo,
|
||||
rvsoc.rvtop.core.lsu.io_dccm_rd_data_hi,
|
||||
rvsoc.rvtop.core.lsu.io_dccm_rd_data_lo);
|
||||
|
||||
end
|
||||
else if(rvsoc.rvtop.core.lsu.io_dccm_wren == 1 || rvsoc.rvtop.core.lsu.io_lsu_dma_dma_dccm_ctl_dccm_dma_rvalid)
|
||||
$fwrite(lsu, "x\tx\tx\tx\tx\t");
|
||||
|
||||
if (rvsoc.rvtop.core.lsu.io_lsu_dma_dma_dccm_ctl_dccm_dma_rvalid == 1) begin
|
||||
$fwrite(lsu, "%0h,%0h\n",
|
||||
rvsoc.rvtop.core.lsu.io_lsu_dma_dma_dccm_ctl_dccm_dma_rvalid,
|
||||
rvsoc.rvtop.core.lsu.io_lsu_dma_dma_dccm_ctl_dccm_dma_rdata);
|
||||
end
|
||||
else if (rvsoc.rvtop.core.lsu.io_dccm_wren == 1 || rvsoc.rvtop.core.lsu.io_dccm_rden== 1)
|
||||
$fwrite(lsu, "x\tx\n");
|
||||
end
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////IFU tracer////////////////////////////////////////////////////////
|
||||
always @(posedge core_clk) begin
|
||||
|
||||
if (rvsoc.rvtop.core.ifu.aln_ctl_io_dec_aln_aln_ib_ifu_i0_valid == 1 && cycleCnt != 0) begin
|
||||
$fwrite(ifu, "%5d,%0h,%0h,%0h\t", cycleCnt,
|
||||
rvsoc.rvtop.core.ifu.aln_ctl_io_dec_aln_aln_ib_ifu_i0_valid,
|
||||
rvsoc.rvtop.core.ifu.aln_ctl_io_dec_aln_aln_ib_ifu_i0_instr,
|
||||
rvsoc.rvtop.core.ifu.aln_ctl_io_dec_aln_aln_ib_ifu_i0_pc);
|
||||
end
|
||||
|
||||
else if((rvsoc.rvtop.core.ifu.io_iccm_wren == 1 || rvsoc.rvtop.core.ifu.io_iccm_rden==1 || rvsoc.rvtop.core.ifu.io_ic_wr_en !==0 || rvsoc.rvtop.core.ifu.io_ic_rd_en ==1 || rvsoc.rvtop.core.ifu.io_iccm_dma_rvalid == 1) && cycleCnt != 0)
|
||||
$fwrite(ifu, "%5d,x\tx\tx\t", cycleCnt);
|
||||
|
||||
if (rvsoc.rvtop.core.ifu.io_iccm_wren == 1 && cycleCnt != 0) begin
|
||||
$fwrite(ifu, "%0h,%0h,%0h\t", rvsoc.rvtop.core.ifu.io_iccm_wren,
|
||||
rvsoc.rvtop.core.ifu.io_iccm_rw_addr,
|
||||
rvsoc.rvtop.core.ifu.io_iccm_wr_data);
|
||||
end
|
||||
|
||||
else if((rvsoc.rvtop.core.ifu.aln_ctl_io_dec_aln_aln_ib_ifu_i0_valid == 1 || rvsoc.rvtop.core.ifu.io_iccm_rden==1 || rvsoc.rvtop.core.ifu.io_ic_wr_en !==0 || rvsoc.rvtop.core.ifu.io_ic_rd_en ==1 || rvsoc.rvtop.core.ifu.io_iccm_dma_rvalid == 1) && cycleCnt != 0)
|
||||
$fwrite(ifu, "\tx\tx\tx\t");
|
||||
|
||||
if (rvsoc.rvtop.core.ifu.io_iccm_rden == 1 && cycleCnt != 0) begin
|
||||
$fwrite(ifu, "%0h,%0h,%0h\t", rvsoc.rvtop.core.ifu.io_iccm_rden,
|
||||
rvsoc.rvtop.core.ifu.io_iccm_rw_addr,
|
||||
rvsoc.rvtop.core.ifu.io_iccm_rd_data_ecc);
|
||||
end
|
||||
|
||||
else if((rvsoc.rvtop.core.ifu.aln_ctl_io_dec_aln_aln_ib_ifu_i0_valid == 1 || rvsoc.rvtop.core.ifu.io_iccm_wren==1 || rvsoc.rvtop.core.ifu.io_ic_wr_en !==0 || rvsoc.rvtop.core.ifu.io_ic_rd_en ==1 || rvsoc.rvtop.core.ifu.io_iccm_dma_rvalid == 1)&& cycleCnt != 0)
|
||||
$fwrite(ifu, "\tx\tx\tx\t");
|
||||
|
||||
if (rvsoc.rvtop.core.ifu.io_ic_wr_en !== 0 && cycleCnt != 0) begin
|
||||
$fwrite(ifu, "%0h,%0h,%0h\t", rvsoc.rvtop.core.ifu.io_ic_wr_en,
|
||||
rvsoc.rvtop.core.ifu.io_ic_rw_addr,
|
||||
rvsoc.rvtop.core.ifu.io_ic_wr_data_0,
|
||||
rvsoc.rvtop.core.ifu.io_ic_wr_data_1);
|
||||
end
|
||||
|
||||
else if((rvsoc.rvtop.core.ifu.aln_ctl_io_dec_aln_aln_ib_ifu_i0_valid == 1 || rvsoc.rvtop.core.ifu.io_iccm_wren==1 || rvsoc.rvtop.core.ifu.io_iccm_rden ==1 || rvsoc.rvtop.core.ifu.io_ic_rd_en ==1 || rvsoc.rvtop.core.ifu.io_iccm_dma_rvalid == 1)&& cycleCnt != 0)
|
||||
$fwrite(ifu, "\tx\tx\tx\tx\t");
|
||||
|
||||
if (rvsoc.rvtop.core.ifu.io_ic_rd_en == 1 && cycleCnt != 0) begin
|
||||
$fwrite(ifu, "%0h,%0h,%0h\t", rvsoc.rvtop.core.ifu.io_ic_rd_en,
|
||||
rvsoc.rvtop.core.ifu.io_ic_rw_addr,
|
||||
rvsoc.rvtop.core.ifu.io_ic_rd_data);
|
||||
end
|
||||
|
||||
else if((rvsoc.rvtop.core.ifu.aln_ctl_io_dec_aln_aln_ib_ifu_i0_valid == 1 || rvsoc.rvtop.core.ifu.io_iccm_wren==1 || rvsoc.rvtop.core.ifu.io_iccm_rden ==1 || rvsoc.rvtop.core.ifu.io_ic_wr_en !== 0 ||rvsoc.rvtop.core.ifu.io_iccm_dma_rvalid == 1)&& cycleCnt != 0)
|
||||
$fwrite(ifu, "\tx\tx\tx\t");
|
||||
|
||||
if (rvsoc.rvtop.core.ifu.io_iccm_dma_rvalid == 1 && cycleCnt != 0) begin
|
||||
$fwrite(ifu, "%h,%0h\n", rvsoc.rvtop.core.ifu.io_iccm_dma_rvalid,
|
||||
rvsoc.rvtop.core.ifu.io_iccm_dma_rdata);
|
||||
end
|
||||
|
||||
else if((rvsoc.rvtop.core.ifu.aln_ctl_io_dec_aln_aln_ib_ifu_i0_valid == 1 || rvsoc.rvtop.core.ifu.io_iccm_wren==1 || rvsoc.rvtop.core.ifu.io_iccm_rden ==1 || rvsoc.rvtop.core.ifu.io_ic_wr_en !== 0 || rvsoc.rvtop.core.ifu.io_ic_rd_en)&& cycleCnt != 0)
|
||||
$fwrite(ifu, "\tx\tx\n");
|
||||
end
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////DEC tracer////////////////////////////////////////////////////////
|
||||
always @(posedge core_clk) begin
|
||||
|
||||
if (rvsoc.rvtop.core.dma_ctrl.io_dma_dbg_cmd_done == 1) begin
|
||||
$fwrite(dec, "%5d,\t%0h,%0h\t", cycleCnt,
|
||||
rvsoc.rvtop.core.dma_ctrl.io_dma_dbg_cmd_done,
|
||||
rvsoc.rvtop.core.dec.io_dec_dbg_rddata);
|
||||
end
|
||||
|
||||
else if(rvsoc.rvtop.core.dec.io_dec_exu_dec_alu_dec_i0_alu_decode_d == 1 || rvsoc.rvtop.core.dec.decode_io_dec_csr_wen_r==1)
|
||||
$fwrite(dec, "%5d,\tx\tx\t", cycleCnt);
|
||||
|
||||
if (rvsoc.rvtop.core.dec.io_dec_exu_dec_alu_dec_i0_alu_decode_d == 1) begin
|
||||
$fwrite(dec, "%0h,%0h,%0h,%0h,%0h,%0h\t",
|
||||
rvsoc.rvtop.core.dec.io_dec_exu_dec_alu_dec_i0_alu_decode_d,
|
||||
rvsoc.rvtop.core.dec.decode_io_decode_exu_dec_i0_rs1_en_d,
|
||||
rvsoc.rvtop.core.exu.i0_rs1_d,
|
||||
rvsoc.rvtop.core.dec.decode_io_decode_exu_dec_i0_rs2_en_d,
|
||||
rvsoc.rvtop.core.exu.i0_rs2_d,
|
||||
rvsoc.rvtop.core.exu.io_dec_exu_decode_exu_exu_i0_result_x);
|
||||
end
|
||||
|
||||
else if(rvsoc.rvtop.core.dma_ctrl.io_dma_dbg_cmd_done == 1 || rvsoc.rvtop.core.dec.decode_io_dec_csr_wen_r==1)
|
||||
$fwrite(dec, "x\t,x\t,x\t,x\tx\tx\t");
|
||||
|
||||
if (rvsoc.rvtop.core.dec.decode_io_dec_csr_wen_r == 1) begin
|
||||
$fwrite(dec, "%0h,%0h,%0h,%0h,%0h\n",
|
||||
rvsoc.rvtop.core.dec.decode_io_dec_csr_wen_r,
|
||||
rvsoc.rvtop.core.dec.decode_io_dec_csr_wraddr_r,
|
||||
rvsoc.rvtop.core.dec.decode_io_dec_csr_wrdata_r,
|
||||
rvsoc.rvtop.core.dec.decode_io_dec_csr_rdaddr_d,
|
||||
rvsoc.rvtop.core.dec.decode_io_dec_csr_rddata_d);
|
||||
end
|
||||
|
||||
else if(rvsoc.rvtop.core.dma_ctrl.io_dma_dbg_cmd_done == 1 || rvsoc.rvtop.core.dec.io_dec_exu_dec_alu_dec_i0_alu_decode_d == 1 )
|
||||
$fwrite(dec, "x\t,x\t,x\t,x\t,x\n");
|
||||
|
||||
end
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////exu tracer///////////////////////////////////////////////////
|
||||
always @(posedge core_clk) begin
|
||||
|
||||
if (rvsoc.rvtop.core.exu.io_exu_div_wren == 1) begin
|
||||
$fwrite(exu, "%5d,\t%0h,%0h,%0h,%0h,%0h\t", cycleCnt,
|
||||
rvsoc.rvtop.core.exu.io_exu_div_wren,
|
||||
rvsoc.rvtop.core.exu.io_exu_div_result,
|
||||
rvsoc.rvtop.core.exu.i_div.io_dividend,
|
||||
rvsoc.rvtop.core.exu.i_div.io_divisor,
|
||||
rvsoc.rvtop.core.exu.i_div.io_exu_div_result);
|
||||
end
|
||||
|
||||
else if(rvsoc.rvtop.core.exu.i0_rs1_bypass_en_d == 1 || rvsoc.rvtop.core.exu.i0_rs2_bypass_en_d == 1)
|
||||
$fwrite(exu, "%5d,\tx\tx\tx\tx\tx,\t", cycleCnt);
|
||||
|
||||
if (rvsoc.rvtop.core.exu.i0_rs1_bypass_en_d == 1) begin
|
||||
$fwrite(exu, "\t%0h,%0h\t", rvsoc.rvtop.core.exu.i0_rs1_bypass_en_d,
|
||||
rvsoc.rvtop.core.exu.i0_rs1_bypass_data_d);
|
||||
end
|
||||
|
||||
else if(rvsoc.rvtop.core.exu.io_exu_div_wren == 1 || rvsoc.rvtop.core.exu.i0_rs2_bypass_en_d == 1)
|
||||
$fwrite(exu, "\tx\tx\t");
|
||||
|
||||
if (rvsoc.rvtop.core.exu.i0_rs2_bypass_en_d == 1) begin
|
||||
$fwrite(exu, "\t%0h,%0h\n", rvsoc.rvtop.core.exu.i0_rs2_bypass_en_d,
|
||||
rvsoc.rvtop.core.exu.i0_rs2_bypass_data_d);
|
||||
end
|
||||
|
||||
else if(rvsoc.rvtop.core.exu.io_exu_div_wren == 1 || rvsoc.rvtop.core.exu.i0_rs1_bypass_en_d == 1)
|
||||
$fwrite(exu, "\tx\tx\n");
|
||||
end
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
initial begin
|
||||
abi_reg[0] = "zero";
|
||||
abi_reg[1] = "ra";
|
||||
abi_reg[2] = "sp";
|
||||
abi_reg[3] = "gp";
|
||||
abi_reg[4] = "tp";
|
||||
abi_reg[5] = "t0";
|
||||
abi_reg[6] = "t1";
|
||||
abi_reg[7] = "t2";
|
||||
abi_reg[8] = "s0";
|
||||
abi_reg[9] = "s1";
|
||||
abi_reg[10] = "a0";
|
||||
abi_reg[11] = "a1";
|
||||
abi_reg[12] = "a2";
|
||||
abi_reg[13] = "a3";
|
||||
abi_reg[14] = "a4";
|
||||
abi_reg[15] = "a5";
|
||||
abi_reg[16] = "a6";
|
||||
abi_reg[17] = "a7";
|
||||
abi_reg[18] = "s2";
|
||||
abi_reg[19] = "s3";
|
||||
abi_reg[20] = "s4";
|
||||
abi_reg[21] = "s5";
|
||||
abi_reg[22] = "s6";
|
||||
abi_reg[23] = "s7";
|
||||
abi_reg[24] = "s8";
|
||||
abi_reg[25] = "s9";
|
||||
abi_reg[26] = "s10";
|
||||
abi_reg[27] = "s11";
|
||||
abi_reg[28] = "t3";
|
||||
abi_reg[29] = "t4";
|
||||
abi_reg[30] = "t5";
|
||||
abi_reg[31] = "t6";
|
||||
|
||||
tp = $fopen("trace_port.csv", "w");
|
||||
el = $fopen("exec.log", "w");
|
||||
//////////////////////////////////////////////////////////////////
|
||||
pic = $fopen("pic.log", "w");
|
||||
$fwrite(pic,
|
||||
" write enable, write addr , write data ,read enable, read address, read data \n");
|
||||
///////////////////////////////////////////////////////////////////
|
||||
lsu = $fopen("lsu.log", "w");
|
||||
$fwrite(lsu,
|
||||
"write en, write addrs hi,write addrs lo, write data hi,write data lo, read_en, read addrs hi,read addrs lo, read data hi,read data lo, dma valid, dma read data \n");
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
ifu = $fopen("ifu.log", "w");
|
||||
$fwrite(ifu,
|
||||
"cycleCnt,inst_valid,inst,inst_pc\ticcm wen,iccm waddr,iccm wdata, iccm ren,iccm raddr, iccm rdata\tic wen,ic waddr,ic wdata0,ic wdata1\tic ren,ic raddr,ic rdata\ticcm dma rvalid,iccm dma rdata\n");
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
dec = $fopen("dec.log", "w");
|
||||
$fwrite(dec,
|
||||
"clock cycle dbg cmd, dbg rd data\talu decode, rs1 en, rs1, rs2 en, rs2, result, csr wen, csr wr addr, csr wrdata, csr rd addr, csr rd data\n");
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
exu = $fopen("exu.log", "w");
|
||||
$fwrite(exu,
|
||||
"clock cycle div enable, div result, dividend, divisor, out\t,rs1 bypassen, rs1 bypassdata\t, rs2 bypassen, rs2 bypassdata\n");
|
||||
$fwrite(el, "//Cycle : #inst 0 pc opcode reg regnum value\n");
|
||||
fd = $fopen("console.log", "w");
|
||||
commit_count = 0;
|
||||
|
||||
end
|
||||
|
||||
assign rst_l = cycleCnt > 5;
|
||||
assign dbg_rst_l = cycleCnt > 2;
|
||||
|
||||
soc_top rvsoc (
|
||||
.clk(core_clk),
|
||||
.rst(rst_l),
|
||||
.dbg_rst(dbg_rst_l),
|
||||
|
||||
.jtag_tdo(jtag_tdo),
|
||||
.jtag_tck(jtag_tck),
|
||||
.jtag_tms(jtag_tms),
|
||||
.jtag_tdi(jtag_tdi),
|
||||
.jtag_trst_n(jtag_trst_n)
|
||||
);
|
||||
|
||||
jtagdpi jtagdpi (
|
||||
.clk_i (core_clk),
|
||||
.rst_ni(rst_l),
|
||||
|
||||
.jtag_tck(jtag_tck),
|
||||
.jtag_tms(jtag_tms),
|
||||
.jtag_tdi(jtag_tdi),
|
||||
.jtag_tdo(jtag_tdo),
|
||||
.jtag_trst_n(jtag_trst_n),
|
||||
.jtag_srst_n()
|
||||
);
|
||||
|
||||
`define DRAM(bank) \
|
||||
rvsoc.rvtop.mem.Gen_dccm_enable.dccm.mem_bank[bank].dccm_bank.ram_core
|
||||
|
||||
`define ICCM_PATH `RV_TOP.mem.iccm
|
||||
`define IRAM0(bk) `ICCM_PATH.mem_bank[bk].iccm_bank_lo0.ram_core
|
||||
`define IRAM1(bk) `ICCM_PATH.mem_bank[bk].iccm_bank_lo1.ram_core
|
||||
`define IRAM2(bk) `ICCM_PATH.mem_bank[bk].iccm_bank_hi0.ram_core
|
||||
`define IRAM3(bk) `ICCM_PATH.mem_bank[bk].iccm_bank_hi1.ram_core
|
||||
|
||||
/* verilator lint_off WIDTH */
|
||||
/* verilator lint_off CASEINCOMPLETE */
|
||||
`include "dasm.svi"
|
||||
/* verilator lint_on CASEINCOMPLETE */
|
||||
/* verilator lint_on WIDTH */
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,16 @@
|
|||
./quasar_wrapper.sv
|
||||
|
||||
vsrc/mem.sv
|
||||
vsrc/ifu_ic_mem.sv
|
||||
vsrc/ifu_iccm_mem.sv
|
||||
vsrc/lsu_dccm_mem.sv
|
||||
vsrc/dmi_wrapper.sv
|
||||
vsrc/dmi_jtag_to_core_sync.sv
|
||||
vsrc/rvjtag_tap.sv
|
||||
vsrc/gated_latch.sv
|
||||
vsrc/beh_lib.sv
|
||||
vsrc/mem_lib.sv
|
||||
|
||||
./ahb_sif.sv
|
||||
./axi_lsu_dma_bridge.sv
|
||||
./soc_top.sv
|
|
@ -0,0 +1,843 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 Western Digital Corporation or its affiliates.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
module soc_top (
|
||||
input clk,
|
||||
input dbg_rst,
|
||||
input rst,
|
||||
output jtag_tdo,
|
||||
input jtag_tck,
|
||||
input jtag_tms,
|
||||
input jtag_tdi,
|
||||
input jtag_trst_n
|
||||
);
|
||||
logic nmi_int;
|
||||
|
||||
logic [31:0] reset_vector;
|
||||
logic [31:0] nmi_vector;
|
||||
logic [31:1] jtag_id;
|
||||
|
||||
logic [31:0] ic_haddr ;
|
||||
logic [2:0] ic_hburst ;
|
||||
logic ic_hmastlock ;
|
||||
logic [3:0] ic_hprot ;
|
||||
logic [2:0] ic_hsize ;
|
||||
logic [1:0] ic_htrans ;
|
||||
logic ic_hwrite ;
|
||||
logic [63:0] ic_hrdata ;
|
||||
logic ic_hready ;
|
||||
logic ic_hresp ;
|
||||
|
||||
logic [31:0] lsu_haddr ;
|
||||
logic [2:0] lsu_hburst ;
|
||||
logic lsu_hmastlock ;
|
||||
logic [3:0] lsu_hprot ;
|
||||
logic [2:0] lsu_hsize ;
|
||||
logic [1:0] lsu_htrans ;
|
||||
logic lsu_hwrite ;
|
||||
logic [63:0] lsu_hrdata ;
|
||||
logic [63:0] lsu_hwdata ;
|
||||
logic lsu_hready ;
|
||||
logic lsu_hresp ;
|
||||
|
||||
logic [31:0] sb_haddr ;
|
||||
logic [2:0] sb_hburst ;
|
||||
logic sb_hmastlock ;
|
||||
logic [3:0] sb_hprot ;
|
||||
logic [2:0] sb_hsize ;
|
||||
logic [1:0] sb_htrans ;
|
||||
logic sb_hwrite ;
|
||||
|
||||
logic [63:0] sb_hrdata ;
|
||||
logic [63:0] sb_hwdata ;
|
||||
logic sb_hready ;
|
||||
logic sb_hresp ;
|
||||
|
||||
logic [31:0] trace_rv_i_insn_ip;
|
||||
logic [31:0] trace_rv_i_address_ip;
|
||||
logic trace_rv_i_valid_ip;
|
||||
logic trace_rv_i_exception_ip;
|
||||
logic [4:0] trace_rv_i_ecause_ip;
|
||||
logic trace_rv_i_interrupt_ip;
|
||||
logic [31:0] trace_rv_i_tval_ip;
|
||||
|
||||
logic o_debug_mode_status;
|
||||
|
||||
|
||||
logic o_cpu_halt_ack;
|
||||
logic o_cpu_halt_status;
|
||||
logic o_cpu_run_ack;
|
||||
|
||||
logic mailbox_write;
|
||||
logic [63:0] dma_hrdata ;
|
||||
logic [63:0] dma_hwdata ;
|
||||
logic dma_hready ;
|
||||
logic dma_hresp ;
|
||||
|
||||
logic mpc_debug_halt_req;
|
||||
logic mpc_debug_run_req;
|
||||
logic mpc_reset_run_req;
|
||||
logic mpc_debug_halt_ack;
|
||||
logic mpc_debug_run_ack;
|
||||
logic debug_brkpt_status;
|
||||
|
||||
int cycleCnt;
|
||||
logic mailbox_data_val;
|
||||
|
||||
wire dma_hready_out;
|
||||
int commit_count;
|
||||
|
||||
logic wb_valid;
|
||||
logic [4:0] wb_dest;
|
||||
logic [31:0] wb_data;
|
||||
|
||||
//-------------------------- LSU AXI signals--------------------------
|
||||
// AXI Write Channels
|
||||
wire lsu_axi_awvalid;
|
||||
wire lsu_axi_awready;
|
||||
wire [`RV_LSU_BUS_TAG-1:0] lsu_axi_awid;
|
||||
wire [31:0] lsu_axi_awaddr;
|
||||
wire [3:0] lsu_axi_awregion;
|
||||
wire [7:0] lsu_axi_awlen;
|
||||
wire [2:0] lsu_axi_awsize;
|
||||
wire [1:0] lsu_axi_awburst;
|
||||
wire lsu_axi_awlock;
|
||||
wire [3:0] lsu_axi_awcache;
|
||||
wire [2:0] lsu_axi_awprot;
|
||||
wire [3:0] lsu_axi_awqos;
|
||||
|
||||
wire lsu_axi_wvalid;
|
||||
wire lsu_axi_wready;
|
||||
wire [63:0] lsu_axi_wdata;
|
||||
wire [7:0] lsu_axi_wstrb;
|
||||
wire lsu_axi_wlast;
|
||||
|
||||
wire lsu_axi_bvalid;
|
||||
wire lsu_axi_bready;
|
||||
wire [1:0] lsu_axi_bresp;
|
||||
wire [`RV_LSU_BUS_TAG-1:0] lsu_axi_bid;
|
||||
|
||||
// AXI Read Channels
|
||||
wire lsu_axi_arvalid;
|
||||
wire lsu_axi_arready;
|
||||
wire [`RV_LSU_BUS_TAG-1:0] lsu_axi_arid;
|
||||
wire [31:0] lsu_axi_araddr;
|
||||
wire [3:0] lsu_axi_arregion;
|
||||
wire [7:0] lsu_axi_arlen;
|
||||
wire [2:0] lsu_axi_arsize;
|
||||
wire [1:0] lsu_axi_arburst;
|
||||
wire lsu_axi_arlock;
|
||||
wire [3:0] lsu_axi_arcache;
|
||||
wire [2:0] lsu_axi_arprot;
|
||||
wire [3:0] lsu_axi_arqos;
|
||||
|
||||
wire lsu_axi_rvalid;
|
||||
wire lsu_axi_rready;
|
||||
wire [`RV_LSU_BUS_TAG-1:0] lsu_axi_rid;
|
||||
wire [63:0] lsu_axi_rdata;
|
||||
wire [1:0] lsu_axi_rresp;
|
||||
wire lsu_axi_rlast;
|
||||
|
||||
//-------------------------- IFU AXI signals--------------------------
|
||||
// AXI Write Channels
|
||||
wire ifu_axi_awvalid;
|
||||
wire ifu_axi_awready;
|
||||
wire [`RV_IFU_BUS_TAG-1:0] ifu_axi_awid;
|
||||
wire [31:0] ifu_axi_awaddr;
|
||||
wire [3:0] ifu_axi_awregion;
|
||||
wire [7:0] ifu_axi_awlen;
|
||||
wire [2:0] ifu_axi_awsize;
|
||||
wire [1:0] ifu_axi_awburst;
|
||||
wire ifu_axi_awlock;
|
||||
wire [3:0] ifu_axi_awcache;
|
||||
wire [2:0] ifu_axi_awprot;
|
||||
wire [3:0] ifu_axi_awqos;
|
||||
|
||||
wire ifu_axi_wvalid;
|
||||
wire ifu_axi_wready;
|
||||
wire [63:0] ifu_axi_wdata;
|
||||
wire [7:0] ifu_axi_wstrb;
|
||||
wire ifu_axi_wlast;
|
||||
|
||||
wire ifu_axi_bvalid;
|
||||
wire ifu_axi_bready;
|
||||
wire [1:0] ifu_axi_bresp;
|
||||
wire [`RV_IFU_BUS_TAG-1:0] ifu_axi_bid;
|
||||
|
||||
// AXI Read Channels
|
||||
wire ifu_axi_arvalid;
|
||||
wire ifu_axi_arready;
|
||||
wire [`RV_IFU_BUS_TAG-1:0] ifu_axi_arid;
|
||||
wire [31:0] ifu_axi_araddr;
|
||||
wire [3:0] ifu_axi_arregion;
|
||||
wire [7:0] ifu_axi_arlen;
|
||||
wire [2:0] ifu_axi_arsize;
|
||||
wire [1:0] ifu_axi_arburst;
|
||||
wire ifu_axi_arlock;
|
||||
wire [3:0] ifu_axi_arcache;
|
||||
wire [2:0] ifu_axi_arprot;
|
||||
wire [3:0] ifu_axi_arqos;
|
||||
|
||||
wire ifu_axi_rvalid;
|
||||
wire ifu_axi_rready;
|
||||
wire [`RV_IFU_BUS_TAG-1:0] ifu_axi_rid;
|
||||
wire [63:0] ifu_axi_rdata;
|
||||
wire [1:0] ifu_axi_rresp;
|
||||
wire ifu_axi_rlast;
|
||||
|
||||
//-------------------------- SB AXI signals--------------------------
|
||||
// AXI Write Channels
|
||||
wire sb_axi_awvalid;
|
||||
wire sb_axi_awready;
|
||||
wire [`RV_SB_BUS_TAG-1:0] sb_axi_awid;
|
||||
wire [31:0] sb_axi_awaddr;
|
||||
wire [3:0] sb_axi_awregion;
|
||||
wire [7:0] sb_axi_awlen;
|
||||
wire [2:0] sb_axi_awsize;
|
||||
wire [1:0] sb_axi_awburst;
|
||||
wire sb_axi_awlock;
|
||||
wire [3:0] sb_axi_awcache;
|
||||
wire [2:0] sb_axi_awprot;
|
||||
wire [3:0] sb_axi_awqos;
|
||||
|
||||
wire sb_axi_wvalid;
|
||||
wire sb_axi_wready;
|
||||
wire [63:0] sb_axi_wdata;
|
||||
wire [7:0] sb_axi_wstrb;
|
||||
wire sb_axi_wlast;
|
||||
|
||||
wire sb_axi_bvalid;
|
||||
wire sb_axi_bready;
|
||||
wire [1:0] sb_axi_bresp;
|
||||
wire [`RV_SB_BUS_TAG-1:0] sb_axi_bid;
|
||||
|
||||
// AXI Read Channels
|
||||
wire sb_axi_arvalid;
|
||||
wire sb_axi_arready;
|
||||
wire [`RV_SB_BUS_TAG-1:0] sb_axi_arid;
|
||||
wire [31:0] sb_axi_araddr;
|
||||
wire [3:0] sb_axi_arregion;
|
||||
wire [7:0] sb_axi_arlen;
|
||||
wire [2:0] sb_axi_arsize;
|
||||
wire [1:0] sb_axi_arburst;
|
||||
wire sb_axi_arlock;
|
||||
wire [3:0] sb_axi_arcache;
|
||||
wire [2:0] sb_axi_arprot;
|
||||
wire [3:0] sb_axi_arqos;
|
||||
|
||||
wire sb_axi_rvalid;
|
||||
wire sb_axi_rready;
|
||||
wire [`RV_SB_BUS_TAG-1:0] sb_axi_rid;
|
||||
wire [63:0] sb_axi_rdata;
|
||||
wire [1:0] sb_axi_rresp;
|
||||
wire sb_axi_rlast;
|
||||
|
||||
//-------------------------- DMA AXI signals--------------------------
|
||||
// AXI Write Channels
|
||||
wire dma_axi_awvalid;
|
||||
wire dma_axi_awready;
|
||||
wire [`RV_DMA_BUS_TAG-1:0] dma_axi_awid;
|
||||
wire [31:0] dma_axi_awaddr;
|
||||
wire [2:0] dma_axi_awsize;
|
||||
wire [2:0] dma_axi_awprot;
|
||||
wire [7:0] dma_axi_awlen;
|
||||
wire [1:0] dma_axi_awburst;
|
||||
|
||||
|
||||
wire dma_axi_wvalid;
|
||||
wire dma_axi_wready;
|
||||
wire [63:0] dma_axi_wdata;
|
||||
wire [7:0] dma_axi_wstrb;
|
||||
wire dma_axi_wlast;
|
||||
|
||||
wire dma_axi_bvalid;
|
||||
wire dma_axi_bready;
|
||||
wire [1:0] dma_axi_bresp;
|
||||
wire [`RV_DMA_BUS_TAG-1:0] dma_axi_bid;
|
||||
|
||||
// AXI Read Channels
|
||||
wire dma_axi_arvalid;
|
||||
wire dma_axi_arready;
|
||||
wire [`RV_DMA_BUS_TAG-1:0] dma_axi_arid;
|
||||
wire [31:0] dma_axi_araddr;
|
||||
wire [2:0] dma_axi_arsize;
|
||||
wire [2:0] dma_axi_arprot;
|
||||
wire [7:0] dma_axi_arlen;
|
||||
wire [1:0] dma_axi_arburst;
|
||||
|
||||
wire dma_axi_rvalid;
|
||||
wire dma_axi_rready;
|
||||
wire [`RV_DMA_BUS_TAG-1:0] dma_axi_rid;
|
||||
wire [63:0] dma_axi_rdata;
|
||||
wire [1:0] dma_axi_rresp;
|
||||
wire dma_axi_rlast;
|
||||
|
||||
wire lmem_axi_arvalid;
|
||||
wire lmem_axi_arready;
|
||||
|
||||
wire lmem_axi_rvalid;
|
||||
wire [`RV_LSU_BUS_TAG-1:0] lmem_axi_rid;
|
||||
wire [1:0] lmem_axi_rresp;
|
||||
wire [63:0] lmem_axi_rdata;
|
||||
wire lmem_axi_rlast;
|
||||
wire lmem_axi_rready;
|
||||
|
||||
wire lmem_axi_awvalid;
|
||||
wire lmem_axi_awready;
|
||||
|
||||
wire lmem_axi_wvalid;
|
||||
wire lmem_axi_wready;
|
||||
|
||||
wire [1:0] lmem_axi_bresp;
|
||||
wire lmem_axi_bvalid;
|
||||
wire [`RV_LSU_BUS_TAG-1:0] lmem_axi_bid;
|
||||
wire lmem_axi_bready;
|
||||
|
||||
initial begin
|
||||
jtag_id[31:28] = 4'b1;
|
||||
jtag_id[27:12] = '0;
|
||||
jtag_id[11:1] = 11'h45;
|
||||
reset_vector = 32'h0;
|
||||
nmi_vector = 32'hee000000;
|
||||
nmi_int = 0;
|
||||
|
||||
$readmemh("program.hex", lmem.mem);
|
||||
$readmemh("program.hex", imem.mem);
|
||||
|
||||
end
|
||||
|
||||
quasar_wrapper rvtop (
|
||||
.reset (rst),
|
||||
.io_dbg_rst_l(dbg_rst),
|
||||
.clock (clk),
|
||||
.io_rst_vec (reset_vector[31:1]),
|
||||
.io_nmi_int (nmi_int),
|
||||
.io_nmi_vec (nmi_vector[31:1]),
|
||||
.io_jtag_id (jtag_id[31:1]),
|
||||
|
||||
//-------------------------- LSU AXI signals--------------------------
|
||||
// AXI Write Channels
|
||||
.io_lsu_brg_aw_valid (lsu_axi_awvalid),
|
||||
.io_lsu_brg_aw_ready (lsu_axi_awready),
|
||||
.io_lsu_brg_aw_bits_id (lsu_axi_awid),
|
||||
.io_lsu_brg_aw_bits_addr (lsu_axi_awaddr),
|
||||
.io_lsu_brg_aw_bits_region(lsu_axi_awregion),
|
||||
.io_lsu_brg_aw_bits_len (lsu_axi_awlen),
|
||||
.io_lsu_brg_aw_bits_size (lsu_axi_awsize),
|
||||
.io_lsu_brg_aw_bits_burst (lsu_axi_awburst),
|
||||
.io_lsu_brg_aw_bits_lock (lsu_axi_awlock),
|
||||
.io_lsu_brg_aw_bits_cache (lsu_axi_awcache),
|
||||
.io_lsu_brg_aw_bits_prot (lsu_axi_awprot),
|
||||
.io_lsu_brg_aw_bits_qos (lsu_axi_awqos),
|
||||
|
||||
.io_lsu_brg_w_valid (lsu_axi_wvalid),
|
||||
.io_lsu_brg_w_ready (lsu_axi_wready),
|
||||
.io_lsu_brg_w_bits_data(lsu_axi_wdata),
|
||||
.io_lsu_brg_w_bits_strb(lsu_axi_wstrb),
|
||||
.io_lsu_brg_w_bits_last(lsu_axi_wlast),
|
||||
|
||||
.io_lsu_brg_b_valid (lsu_axi_bvalid),
|
||||
.io_lsu_brg_b_ready (lsu_axi_bready),
|
||||
.io_lsu_brg_b_bits_resp(lsu_axi_bresp),
|
||||
.io_lsu_brg_b_bits_id (lsu_axi_bid),
|
||||
|
||||
|
||||
.io_lsu_brg_ar_valid (lsu_axi_arvalid),
|
||||
.io_lsu_brg_ar_ready (lsu_axi_arready),
|
||||
.io_lsu_brg_ar_bits_id (lsu_axi_arid),
|
||||
.io_lsu_brg_ar_bits_addr (lsu_axi_araddr),
|
||||
.io_lsu_brg_ar_bits_region(lsu_axi_arregion),
|
||||
.io_lsu_brg_ar_bits_len (lsu_axi_arlen),
|
||||
.io_lsu_brg_ar_bits_size (lsu_axi_arsize),
|
||||
.io_lsu_brg_ar_bits_burst (lsu_axi_arburst),
|
||||
.io_lsu_brg_ar_bits_lock (lsu_axi_arlock),
|
||||
.io_lsu_brg_ar_bits_cache (lsu_axi_arcache),
|
||||
.io_lsu_brg_ar_bits_prot (lsu_axi_arprot),
|
||||
.io_lsu_brg_ar_bits_qos (lsu_axi_arqos),
|
||||
|
||||
.io_lsu_brg_r_valid (lsu_axi_rvalid),
|
||||
.io_lsu_brg_r_ready (lsu_axi_rready),
|
||||
.io_lsu_brg_r_bits_id (lsu_axi_rid),
|
||||
.io_lsu_brg_r_bits_data(lsu_axi_rdata),
|
||||
.io_lsu_brg_r_bits_resp(lsu_axi_rresp),
|
||||
.io_lsu_brg_r_bits_last(lsu_axi_rlast),
|
||||
|
||||
//-------------------------- IFU AXI signals--------------------------
|
||||
// AXI Write Channels
|
||||
.io_ifu_brg_aw_valid (ifu_axi_awvalid),
|
||||
.io_ifu_brg_aw_ready (ifu_axi_awready),
|
||||
.io_ifu_brg_aw_bits_id (ifu_axi_awid),
|
||||
.io_ifu_brg_aw_bits_addr (ifu_axi_awaddr),
|
||||
.io_ifu_brg_aw_bits_region(ifu_axi_awregion),
|
||||
.io_ifu_brg_aw_bits_len (ifu_axi_awlen),
|
||||
.io_ifu_brg_aw_bits_size (ifu_axi_awsize),
|
||||
.io_ifu_brg_aw_bits_burst (ifu_axi_awburst),
|
||||
.io_ifu_brg_aw_bits_lock (ifu_axi_awlock),
|
||||
.io_ifu_brg_aw_bits_cache (ifu_axi_awcache),
|
||||
.io_ifu_brg_aw_bits_prot (ifu_axi_awprot),
|
||||
.io_ifu_brg_aw_bits_qos (ifu_axi_awqos),
|
||||
|
||||
.io_ifu_brg_w_valid (ifu_axi_wvalid),
|
||||
.io_ifu_brg_w_ready (ifu_axi_wready),
|
||||
.io_ifu_brg_w_bits_data(ifu_axi_wdata),
|
||||
.io_ifu_brg_w_bits_strb(ifu_axi_wstrb),
|
||||
.io_ifu_brg_w_bits_last(ifu_axi_wlast),
|
||||
|
||||
.io_ifu_brg_b_valid (ifu_axi_bvalid),
|
||||
.io_ifu_brg_b_ready (ifu_axi_bready),
|
||||
.io_ifu_brg_b_bits_resp(ifu_axi_bresp),
|
||||
.io_ifu_brg_b_bits_id (ifu_axi_bid),
|
||||
|
||||
.io_ifu_brg_ar_valid (ifu_axi_arvalid),
|
||||
.io_ifu_brg_ar_ready (ifu_axi_arready),
|
||||
.io_ifu_brg_ar_bits_id (ifu_axi_arid),
|
||||
.io_ifu_brg_ar_bits_addr (ifu_axi_araddr),
|
||||
.io_ifu_brg_ar_bits_region(ifu_axi_arregion),
|
||||
.io_ifu_brg_ar_bits_len (ifu_axi_arlen),
|
||||
.io_ifu_brg_ar_bits_size (ifu_axi_arsize),
|
||||
.io_ifu_brg_ar_bits_burst (ifu_axi_arburst),
|
||||
.io_ifu_brg_ar_bits_lock (ifu_axi_arlock),
|
||||
.io_ifu_brg_ar_bits_cache (ifu_axi_arcache),
|
||||
.io_ifu_brg_ar_bits_prot (ifu_axi_arprot),
|
||||
.io_ifu_brg_ar_bits_qos (ifu_axi_arqos),
|
||||
|
||||
.io_ifu_brg_r_valid (ifu_axi_rvalid),
|
||||
.io_ifu_brg_r_ready (ifu_axi_rready),
|
||||
.io_ifu_brg_r_bits_id (ifu_axi_rid),
|
||||
.io_ifu_brg_r_bits_data(ifu_axi_rdata),
|
||||
.io_ifu_brg_r_bits_resp(ifu_axi_rresp),
|
||||
.io_ifu_brg_r_bits_last(ifu_axi_rlast),
|
||||
|
||||
//-------------------------- SB AXI signals--------------------------
|
||||
// AXI Write Channels
|
||||
.io_sb_brg_aw_valid (sb_axi_awvalid),
|
||||
.io_sb_brg_aw_ready (sb_axi_awready),
|
||||
.io_sb_brg_aw_bits_id (sb_axi_awid),
|
||||
.io_sb_brg_aw_bits_addr (sb_axi_awaddr),
|
||||
.io_sb_brg_aw_bits_region(sb_axi_awregion),
|
||||
.io_sb_brg_aw_bits_len (sb_axi_awlen),
|
||||
.io_sb_brg_aw_bits_size (sb_axi_awsize),
|
||||
.io_sb_brg_aw_bits_burst (sb_axi_awburst),
|
||||
.io_sb_brg_aw_bits_lock (sb_axi_awlock),
|
||||
.io_sb_brg_aw_bits_cache (sb_axi_awcache),
|
||||
.io_sb_brg_aw_bits_prot (sb_axi_awprot),
|
||||
.io_sb_brg_aw_bits_qos (sb_axi_awqos),
|
||||
|
||||
.io_sb_brg_w_valid (sb_axi_wvalid),
|
||||
.io_sb_brg_w_ready (sb_axi_wready),
|
||||
.io_sb_brg_w_bits_data(sb_axi_wdata),
|
||||
.io_sb_brg_w_bits_strb(sb_axi_wstrb),
|
||||
.io_sb_brg_w_bits_last(sb_axi_wlast),
|
||||
|
||||
.io_sb_brg_b_valid (sb_axi_bvalid),
|
||||
.io_sb_brg_b_ready (sb_axi_bready),
|
||||
.io_sb_brg_b_bits_resp(sb_axi_bresp),
|
||||
.io_sb_brg_b_bits_id (sb_axi_bid),
|
||||
|
||||
|
||||
.io_sb_brg_ar_valid (sb_axi_arvalid),
|
||||
.io_sb_brg_ar_ready (sb_axi_arready),
|
||||
.io_sb_brg_ar_bits_id (sb_axi_arid),
|
||||
.io_sb_brg_ar_bits_addr (sb_axi_araddr),
|
||||
.io_sb_brg_ar_bits_region(sb_axi_arregion),
|
||||
.io_sb_brg_ar_bits_len (sb_axi_arlen),
|
||||
.io_sb_brg_ar_bits_size (sb_axi_arsize),
|
||||
.io_sb_brg_ar_bits_burst (sb_axi_arburst),
|
||||
.io_sb_brg_ar_bits_lock (sb_axi_arlock),
|
||||
.io_sb_brg_ar_bits_cache (sb_axi_arcache),
|
||||
.io_sb_brg_ar_bits_prot (sb_axi_arprot),
|
||||
.io_sb_brg_ar_bits_qos (sb_axi_arqos),
|
||||
|
||||
.io_sb_brg_r_valid (sb_axi_rvalid),
|
||||
.io_sb_brg_r_ready (sb_axi_rready),
|
||||
.io_sb_brg_r_bits_id (sb_axi_rid),
|
||||
.io_sb_brg_r_bits_data(sb_axi_rdata),
|
||||
.io_sb_brg_r_bits_resp(sb_axi_rresp),
|
||||
.io_sb_brg_r_bits_last(sb_axi_rlast),
|
||||
|
||||
//-------------------------- DMA AXI signals--------------------------
|
||||
// AXI Write Channels
|
||||
.io_dma_brg_aw_valid (dma_axi_awvalid),
|
||||
.io_dma_brg_aw_ready (dma_axi_awready),
|
||||
.io_dma_brg_aw_bits_id ('0),
|
||||
.io_dma_brg_aw_bits_addr (lsu_axi_awaddr),
|
||||
.io_dma_brg_aw_bits_size (lsu_axi_awsize),
|
||||
.io_dma_brg_aw_bits_prot (lsu_axi_awprot),
|
||||
.io_dma_brg_aw_bits_len (lsu_axi_awlen),
|
||||
.io_dma_brg_aw_bits_burst (lsu_axi_awburst),
|
||||
.io_dma_brg_aw_bits_region(lsu_axi_awregion),
|
||||
.io_dma_brg_aw_bits_lock (lsu_axi_awlock),
|
||||
.io_dma_brg_aw_bits_cache (lsu_axi_awcache),
|
||||
.io_dma_brg_aw_bits_qos (lsu_axi_awqos),
|
||||
|
||||
.io_dma_brg_w_valid (dma_axi_wvalid),
|
||||
.io_dma_brg_w_ready (dma_axi_wready),
|
||||
.io_dma_brg_w_bits_data(lsu_axi_wdata),
|
||||
.io_dma_brg_w_bits_strb(lsu_axi_wstrb),
|
||||
.io_dma_brg_w_bits_last(lsu_axi_wlast),
|
||||
|
||||
.io_dma_brg_b_valid (dma_axi_bvalid),
|
||||
.io_dma_brg_b_ready (dma_axi_bready),
|
||||
.io_dma_brg_b_bits_resp(dma_axi_bresp),
|
||||
.io_dma_brg_b_bits_id (),
|
||||
|
||||
.io_dma_brg_ar_valid (dma_axi_arvalid),
|
||||
.io_dma_brg_ar_ready (dma_axi_arready),
|
||||
.io_dma_brg_ar_bits_id ('0),
|
||||
.io_dma_brg_ar_bits_addr (lsu_axi_araddr),
|
||||
.io_dma_brg_ar_bits_size (lsu_axi_arsize),
|
||||
.io_dma_brg_ar_bits_prot (lsu_axi_arprot),
|
||||
.io_dma_brg_ar_bits_len (lsu_axi_arlen),
|
||||
.io_dma_brg_ar_bits_burst (lsu_axi_arburst),
|
||||
.io_dma_brg_ar_bits_region(lsu_axi_arregion),
|
||||
.io_dma_brg_ar_bits_lock (lsu_axi_arlock),
|
||||
.io_dma_brg_ar_bits_cache (lsu_axi_arcache),
|
||||
.io_dma_brg_ar_bits_qos (lsu_axi_arqos),
|
||||
|
||||
.io_dma_brg_r_valid (dma_axi_rvalid),
|
||||
.io_dma_brg_r_ready (dma_axi_rready),
|
||||
.io_dma_brg_r_bits_id (),
|
||||
.io_dma_brg_r_bits_data(dma_axi_rdata),
|
||||
.io_dma_brg_r_bits_resp(dma_axi_rresp),
|
||||
.io_dma_brg_r_bits_last(dma_axi_rlast),
|
||||
|
||||
.io_timer_int (1'b0),
|
||||
.io_extintsrc_req('0),
|
||||
|
||||
.io_lsu_bus_clk_en ( 1'b1 ),// Clock ratio b/w cpu core clk & AHB master interface
|
||||
.io_ifu_bus_clk_en ( 1'b1 ),// Clock ratio b/w cpu core clk & AHB master interface
|
||||
.io_dbg_bus_clk_en ( 1'b1 ),// Clock ratio b/w cpu core clk & AHB Debug master interface
|
||||
.io_dma_bus_clk_en ( 1'b1 ),// Clock ratio b/w cpu core clk & AHB slave interface
|
||||
|
||||
.io_rv_trace_pkt_rv_i_insn_ip (trace_rv_i_insn_ip),
|
||||
.io_rv_trace_pkt_rv_i_address_ip (trace_rv_i_address_ip),
|
||||
.io_rv_trace_pkt_rv_i_valid_ip (trace_rv_i_valid_ip),
|
||||
.io_rv_trace_pkt_rv_i_exception_ip(trace_rv_i_exception_ip),
|
||||
.io_rv_trace_pkt_rv_i_ecause_ip (trace_rv_i_ecause_ip),
|
||||
.io_rv_trace_pkt_rv_i_interrupt_ip(trace_rv_i_interrupt_ip),
|
||||
.io_rv_trace_pkt_rv_i_tval_ip (trace_rv_i_tval_ip),
|
||||
|
||||
.io_jtag_tck (jtag_tck),
|
||||
.io_jtag_tms (jtag_tms),
|
||||
.io_jtag_tdi (jtag_tdi),
|
||||
.io_jtag_trst_n(jtag_trst_n),
|
||||
.io_jtag_tdo (jtag_tdo),
|
||||
|
||||
.io_mpc_debug_halt_ack(mpc_debug_halt_ack),
|
||||
.io_mpc_debug_halt_req(1'b0),
|
||||
.io_mpc_debug_run_ack (mpc_debug_run_ack),
|
||||
.io_mpc_debug_run_req (1'b1),
|
||||
.io_mpc_reset_run_req (1'b1), // Start running after reset
|
||||
.io_debug_brkpt_status(debug_brkpt_status),
|
||||
|
||||
.io_i_cpu_halt_req(1'b0), // Async halt req to CPU
|
||||
.io_o_cpu_halt_ack(o_cpu_halt_ack), // core response to halt
|
||||
.io_o_cpu_halt_status ( o_cpu_halt_status ), // 1'b1 indicates core is halted
|
||||
.io_i_cpu_run_req(1'b0), // Async restart req to CPU
|
||||
.io_o_debug_mode_status(o_debug_mode_status),
|
||||
.io_o_cpu_run_ack(o_cpu_run_ack), // Core response to run req
|
||||
|
||||
.io_dccm_ext_in_pkt_TEST1_0('0),
|
||||
.io_dccm_ext_in_pkt_TEST1_1('0),
|
||||
.io_dccm_ext_in_pkt_TEST1_2('0),
|
||||
.io_dccm_ext_in_pkt_TEST1_3('0),
|
||||
.io_dccm_ext_in_pkt_RME_0('0),
|
||||
.io_dccm_ext_in_pkt_RME_1('0),
|
||||
.io_dccm_ext_in_pkt_RME_2('0),
|
||||
.io_dccm_ext_in_pkt_RME_3('0),
|
||||
.io_dccm_ext_in_pkt_RM_0('0),
|
||||
.io_dccm_ext_in_pkt_RM_1('0),
|
||||
.io_dccm_ext_in_pkt_RM_2('0),
|
||||
.io_dccm_ext_in_pkt_RM_3('0),
|
||||
.io_dccm_ext_in_pkt_LS_0('0),
|
||||
.io_dccm_ext_in_pkt_LS_1('0),
|
||||
.io_dccm_ext_in_pkt_LS_2('0),
|
||||
.io_dccm_ext_in_pkt_LS_3('0),
|
||||
.io_dccm_ext_in_pkt_DS_0('0),
|
||||
.io_dccm_ext_in_pkt_DS_1('0),
|
||||
.io_dccm_ext_in_pkt_DS_2('0),
|
||||
.io_dccm_ext_in_pkt_DS_3('0),
|
||||
.io_dccm_ext_in_pkt_SD_0('0),
|
||||
.io_dccm_ext_in_pkt_SD_1('0),
|
||||
.io_dccm_ext_in_pkt_SD_2('0),
|
||||
.io_dccm_ext_in_pkt_SD_3('0),
|
||||
.io_dccm_ext_in_pkt_TEST_RNM_0('0),
|
||||
.io_dccm_ext_in_pkt_TEST_RNM_1('0),
|
||||
.io_dccm_ext_in_pkt_TEST_RNM_2('0),
|
||||
.io_dccm_ext_in_pkt_TEST_RNM_3('0),
|
||||
.io_dccm_ext_in_pkt_BC1_0('0),
|
||||
.io_dccm_ext_in_pkt_BC1_1('0),
|
||||
.io_dccm_ext_in_pkt_BC1_2('0),
|
||||
.io_dccm_ext_in_pkt_BC1_3('0),
|
||||
.io_dccm_ext_in_pkt_BC2_0('0),
|
||||
.io_dccm_ext_in_pkt_BC2_1('0),
|
||||
.io_dccm_ext_in_pkt_BC2_2('0),
|
||||
.io_dccm_ext_in_pkt_BC2_3('0),
|
||||
.io_iccm_ext_in_pkt_TEST1_0('0),
|
||||
.io_iccm_ext_in_pkt_TEST1_1('0),
|
||||
.io_iccm_ext_in_pkt_TEST1_2('0),
|
||||
.io_iccm_ext_in_pkt_TEST1_3('0),
|
||||
.io_iccm_ext_in_pkt_RME_0('0),
|
||||
.io_iccm_ext_in_pkt_RME_1('0),
|
||||
.io_iccm_ext_in_pkt_RME_2('0),
|
||||
.io_iccm_ext_in_pkt_RME_3('0),
|
||||
.io_iccm_ext_in_pkt_RM_0('0),
|
||||
.io_iccm_ext_in_pkt_RM_1('0),
|
||||
.io_iccm_ext_in_pkt_RM_2('0),
|
||||
.io_iccm_ext_in_pkt_RM_3('0),
|
||||
.io_iccm_ext_in_pkt_LS_0('0),
|
||||
.io_iccm_ext_in_pkt_LS_1('0),
|
||||
.io_iccm_ext_in_pkt_LS_2('0),
|
||||
.io_iccm_ext_in_pkt_LS_3('0),
|
||||
.io_iccm_ext_in_pkt_DS_0('0),
|
||||
.io_iccm_ext_in_pkt_DS_1('0),
|
||||
.io_iccm_ext_in_pkt_DS_2('0),
|
||||
.io_iccm_ext_in_pkt_DS_3('0),
|
||||
.io_iccm_ext_in_pkt_SD_0('0),
|
||||
.io_iccm_ext_in_pkt_SD_1('0),
|
||||
.io_iccm_ext_in_pkt_SD_2('0),
|
||||
.io_iccm_ext_in_pkt_SD_3('0),
|
||||
.io_iccm_ext_in_pkt_TEST_RNM_0('0),
|
||||
.io_iccm_ext_in_pkt_TEST_RNM_1('0),
|
||||
.io_iccm_ext_in_pkt_TEST_RNM_2('0),
|
||||
.io_iccm_ext_in_pkt_TEST_RNM_3('0),
|
||||
.io_iccm_ext_in_pkt_BC1_0('0),
|
||||
.io_iccm_ext_in_pkt_BC1_1('0),
|
||||
.io_iccm_ext_in_pkt_BC1_2('0),
|
||||
.io_iccm_ext_in_pkt_BC1_3('0),
|
||||
.io_iccm_ext_in_pkt_BC2_0('0),
|
||||
.io_iccm_ext_in_pkt_BC2_1('0),
|
||||
.io_iccm_ext_in_pkt_BC2_2('0),
|
||||
.io_iccm_ext_in_pkt_BC2_3('0),
|
||||
.io_ic_data_ext_in_pkt_0_TEST1_0('0),
|
||||
.io_ic_data_ext_in_pkt_0_TEST1_1('0),
|
||||
.io_ic_data_ext_in_pkt_0_RME_0('0),
|
||||
.io_ic_data_ext_in_pkt_0_RME_1('0),
|
||||
.io_ic_data_ext_in_pkt_0_RM_0('0),
|
||||
.io_ic_data_ext_in_pkt_0_RM_1('0),
|
||||
.io_ic_data_ext_in_pkt_0_LS_0('0),
|
||||
.io_ic_data_ext_in_pkt_0_LS_1('0),
|
||||
.io_ic_data_ext_in_pkt_0_DS_0('0),
|
||||
.io_ic_data_ext_in_pkt_0_DS_1('0),
|
||||
.io_ic_data_ext_in_pkt_0_SD_0('0),
|
||||
.io_ic_data_ext_in_pkt_0_SD_1('0),
|
||||
.io_ic_data_ext_in_pkt_0_TEST_RNM_0('0),
|
||||
.io_ic_data_ext_in_pkt_0_TEST_RNM_1('0),
|
||||
.io_ic_data_ext_in_pkt_0_BC1_0('0),
|
||||
.io_ic_data_ext_in_pkt_0_BC1_1('0),
|
||||
.io_ic_data_ext_in_pkt_0_BC2_0('0),
|
||||
.io_ic_data_ext_in_pkt_0_BC2_1('0),
|
||||
.io_ic_data_ext_in_pkt_1_TEST1_0('0),
|
||||
.io_ic_data_ext_in_pkt_1_TEST1_1('0),
|
||||
.io_ic_data_ext_in_pkt_1_RME_0('0),
|
||||
.io_ic_data_ext_in_pkt_1_RME_1('0),
|
||||
.io_ic_data_ext_in_pkt_1_RM_0('0),
|
||||
.io_ic_data_ext_in_pkt_1_RM_1('0),
|
||||
.io_ic_data_ext_in_pkt_1_LS_0('0),
|
||||
.io_ic_data_ext_in_pkt_1_LS_1('0),
|
||||
.io_ic_data_ext_in_pkt_1_DS_0('0),
|
||||
.io_ic_data_ext_in_pkt_1_DS_1('0),
|
||||
.io_ic_data_ext_in_pkt_1_SD_0('0),
|
||||
.io_ic_data_ext_in_pkt_1_SD_1('0),
|
||||
.io_ic_data_ext_in_pkt_1_TEST_RNM_0('0),
|
||||
.io_ic_data_ext_in_pkt_1_TEST_RNM_1('0),
|
||||
.io_ic_data_ext_in_pkt_1_BC1_0('0),
|
||||
.io_ic_data_ext_in_pkt_1_BC1_1('0),
|
||||
.io_ic_data_ext_in_pkt_1_BC2_0('0),
|
||||
.io_ic_data_ext_in_pkt_1_BC2_1('0),
|
||||
.io_ic_tag_ext_in_pkt_TEST1_0('0),
|
||||
.io_ic_tag_ext_in_pkt_TEST1_1('0),
|
||||
.io_ic_tag_ext_in_pkt_RME_0('0),
|
||||
.io_ic_tag_ext_in_pkt_RME_1('0),
|
||||
.io_ic_tag_ext_in_pkt_RM_0('0),
|
||||
.io_ic_tag_ext_in_pkt_RM_1('0),
|
||||
.io_ic_tag_ext_in_pkt_LS_0('0),
|
||||
.io_ic_tag_ext_in_pkt_LS_1('0),
|
||||
.io_ic_tag_ext_in_pkt_DS_0('0),
|
||||
.io_ic_tag_ext_in_pkt_DS_1('0),
|
||||
.io_ic_tag_ext_in_pkt_SD_0('0),
|
||||
.io_ic_tag_ext_in_pkt_SD_1('0),
|
||||
.io_ic_tag_ext_in_pkt_TEST_RNM_0('0),
|
||||
.io_ic_tag_ext_in_pkt_TEST_RNM_1('0),
|
||||
.io_ic_tag_ext_in_pkt_BC1_0('0),
|
||||
.io_ic_tag_ext_in_pkt_BC1_1('0),
|
||||
.io_ic_tag_ext_in_pkt_BC2_0('0),
|
||||
.io_ic_tag_ext_in_pkt_BC2_1('0),
|
||||
|
||||
.io_dec_tlu_perfcnt0(),
|
||||
.io_dec_tlu_perfcnt1(),
|
||||
.io_dec_tlu_perfcnt2(),
|
||||
.io_dec_tlu_perfcnt3(),
|
||||
|
||||
.io_soft_int ('0),
|
||||
.io_core_id ('0),
|
||||
.io_scan_mode (1'b0), // To enable scan mode
|
||||
.io_mbist_mode(1'b0) // to enable mbist
|
||||
|
||||
);
|
||||
|
||||
axi_slv #(
|
||||
.TAGW(`RV_IFU_BUS_TAG)
|
||||
) imem (
|
||||
.aclk(clk),
|
||||
.rst_l(rst),
|
||||
.arvalid(ifu_axi_arvalid),
|
||||
.arready(ifu_axi_arready),
|
||||
.araddr(ifu_axi_araddr),
|
||||
.arid(ifu_axi_arid),
|
||||
.arlen(ifu_axi_arlen),
|
||||
.arburst(ifu_axi_arburst),
|
||||
.arsize(ifu_axi_arsize),
|
||||
|
||||
.rvalid(ifu_axi_rvalid),
|
||||
.rready(ifu_axi_rready),
|
||||
.rdata(ifu_axi_rdata),
|
||||
.rresp(ifu_axi_rresp),
|
||||
.rid(ifu_axi_rid),
|
||||
.rlast(ifu_axi_rlast),
|
||||
|
||||
.awvalid(1'b0),
|
||||
.awready(),
|
||||
.awaddr('0),
|
||||
.awid('0),
|
||||
.awlen('0),
|
||||
.awburst('0),
|
||||
.awsize('0),
|
||||
|
||||
.wdata ('0),
|
||||
.wstrb ('0),
|
||||
.wvalid(1'b0),
|
||||
.wready(),
|
||||
|
||||
.bvalid(),
|
||||
.bready(1'b0),
|
||||
.bresp(),
|
||||
.bid()
|
||||
);
|
||||
|
||||
defparam lmem.TAGW = `RV_LSU_BUS_TAG;
|
||||
|
||||
//axi_slv #(.TAGW(`RV_LSU_BUS_TAG)) lmem(
|
||||
axi_slv lmem (
|
||||
.aclk(clk),
|
||||
.rst_l(rst),
|
||||
.arvalid(lmem_axi_arvalid),
|
||||
.arready(lmem_axi_arready),
|
||||
.araddr(lsu_axi_araddr),
|
||||
.arid(lsu_axi_arid),
|
||||
.arlen(lsu_axi_arlen),
|
||||
.arburst(lsu_axi_arburst),
|
||||
.arsize(lsu_axi_arsize),
|
||||
|
||||
.rvalid(lmem_axi_rvalid),
|
||||
.rready(lmem_axi_rready),
|
||||
.rdata(lmem_axi_rdata),
|
||||
.rresp(lmem_axi_rresp),
|
||||
.rid(lmem_axi_rid),
|
||||
.rlast(lmem_axi_rlast),
|
||||
|
||||
.awvalid(lmem_axi_awvalid),
|
||||
.awready(lmem_axi_awready),
|
||||
.awaddr(lsu_axi_awaddr),
|
||||
.awid(lsu_axi_awid),
|
||||
.awlen(lsu_axi_awlen),
|
||||
.awburst(lsu_axi_awburst),
|
||||
.awsize(lsu_axi_awsize),
|
||||
|
||||
.wdata (lsu_axi_wdata),
|
||||
.wstrb (lsu_axi_wstrb),
|
||||
.wvalid(lmem_axi_wvalid),
|
||||
.wready(lmem_axi_wready),
|
||||
|
||||
.bvalid(lmem_axi_bvalid),
|
||||
.bready(lmem_axi_bready),
|
||||
.bresp(lmem_axi_bresp),
|
||||
.bid(lmem_axi_bid)
|
||||
);
|
||||
|
||||
axi_lsu_dma_bridge #(`RV_LSU_BUS_TAG, `RV_LSU_BUS_TAG) bridge (
|
||||
.clk(clk),
|
||||
.reset_l(rst),
|
||||
|
||||
.m_arvalid(lsu_axi_arvalid),
|
||||
.m_arid(lsu_axi_arid),
|
||||
.m_araddr(lsu_axi_araddr),
|
||||
.m_arready(lsu_axi_arready),
|
||||
|
||||
.m_rvalid(lsu_axi_rvalid),
|
||||
.m_rready(lsu_axi_rready),
|
||||
.m_rdata(lsu_axi_rdata),
|
||||
.m_rid(lsu_axi_rid),
|
||||
.m_rresp(lsu_axi_rresp),
|
||||
.m_rlast(lsu_axi_rlast),
|
||||
|
||||
.m_awvalid(lsu_axi_awvalid),
|
||||
.m_awid(lsu_axi_awid),
|
||||
.m_awaddr(lsu_axi_awaddr),
|
||||
.m_awready(lsu_axi_awready),
|
||||
|
||||
.m_wvalid(lsu_axi_wvalid),
|
||||
.m_wready(lsu_axi_wready),
|
||||
|
||||
.m_bresp(lsu_axi_bresp),
|
||||
.m_bvalid(lsu_axi_bvalid),
|
||||
.m_bid(lsu_axi_bid),
|
||||
.m_bready(lsu_axi_bready),
|
||||
|
||||
.s0_arvalid(lmem_axi_arvalid),
|
||||
.s0_arready(lmem_axi_arready),
|
||||
|
||||
.s0_rvalid(lmem_axi_rvalid),
|
||||
.s0_rid(lmem_axi_rid),
|
||||
.s0_rresp(lmem_axi_rresp),
|
||||
.s0_rdata(lmem_axi_rdata),
|
||||
.s0_rlast(lmem_axi_rlast),
|
||||
.s0_rready(lmem_axi_rready),
|
||||
|
||||
.s0_awvalid(lmem_axi_awvalid),
|
||||
.s0_awready(lmem_axi_awready),
|
||||
|
||||
.s0_wvalid(lmem_axi_wvalid),
|
||||
.s0_wready(lmem_axi_wready),
|
||||
.s0_bresp(lmem_axi_bresp),
|
||||
.s0_bvalid(lmem_axi_bvalid),
|
||||
.s0_bid(lmem_axi_bid),
|
||||
.s0_bready(lmem_axi_bready),
|
||||
|
||||
|
||||
.s1_arvalid(dma_axi_arvalid),
|
||||
.s1_arready(dma_axi_arready),
|
||||
|
||||
.s1_rvalid(dma_axi_rvalid),
|
||||
.s1_rresp (dma_axi_rresp),
|
||||
.s1_rdata (dma_axi_rdata),
|
||||
.s1_rlast (dma_axi_rlast),
|
||||
.s1_rready(dma_axi_rready),
|
||||
|
||||
.s1_awvalid(dma_axi_awvalid),
|
||||
.s1_awready(dma_axi_awready),
|
||||
|
||||
.s1_wvalid(dma_axi_wvalid),
|
||||
.s1_wready(dma_axi_wready),
|
||||
|
||||
.s1_bresp (dma_axi_bresp),
|
||||
.s1_bvalid(dma_axi_bvalid),
|
||||
.s1_bready(dma_axi_bready)
|
||||
|
||||
);
|
||||
|
||||
|
||||
endmodule
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,799 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 Western Digital Corporation or its affiliates.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// all flops call the rvdff flop
|
||||
`define RV_FPGA_OPTIMIZE 1
|
||||
`define RV_PHYSICAL 1
|
||||
|
||||
|
||||
module rvdff #( parameter WIDTH=1, SHORT=0 )
|
||||
(
|
||||
input logic [WIDTH-1:0] din,
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
|
||||
if (SHORT == 1) begin
|
||||
assign dout = din;
|
||||
end
|
||||
else begin
|
||||
`ifdef RV_CLOCKGATE
|
||||
always @(posedge tb_top.clk) begin
|
||||
#0 $strobe("CG: %0t %m din %x dout %x clk %b width %d",$time,din,dout,clk,WIDTH);
|
||||
end
|
||||
`endif
|
||||
|
||||
always_ff @(posedge clk or negedge rst_l) begin
|
||||
if (rst_l == 0)
|
||||
dout[WIDTH-1:0] <= 0;
|
||||
else
|
||||
dout[WIDTH-1:0] <= din[WIDTH-1:0];
|
||||
end
|
||||
|
||||
end
|
||||
endmodule
|
||||
|
||||
// rvdff with 2:1 input mux to flop din iff sel==1
|
||||
module rvdffs #( parameter WIDTH=1, SHORT=0 )
|
||||
(
|
||||
input logic [WIDTH-1:0] din,
|
||||
input logic en,
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
|
||||
if (SHORT == 1) begin : genblock
|
||||
assign dout = din;
|
||||
end
|
||||
else begin : genblock
|
||||
rvdff #(WIDTH) dffs (.din((en) ? din[WIDTH-1:0] : dout[WIDTH-1:0]), .*);
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
// rvdff with en and clear
|
||||
module rvdffsc #( parameter WIDTH=1, SHORT=0 )
|
||||
(
|
||||
input logic [WIDTH-1:0] din,
|
||||
input logic en,
|
||||
input logic clear,
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
|
||||
logic [WIDTH-1:0] din_new;
|
||||
if (SHORT == 1) begin
|
||||
assign dout = din;
|
||||
end
|
||||
else begin
|
||||
assign din_new = {WIDTH{~clear}} & (en ? din[WIDTH-1:0] : dout[WIDTH-1:0]);
|
||||
rvdff #(WIDTH) dffsc (.din(din_new[WIDTH-1:0]), .*);
|
||||
end
|
||||
endmodule
|
||||
|
||||
// _fpga versions
|
||||
module rvdff_fpga #( parameter WIDTH=1, SHORT=0 )
|
||||
(
|
||||
input logic [WIDTH-1:0] din,
|
||||
input logic clk,
|
||||
input logic clken,
|
||||
input logic rawclk,
|
||||
input logic rst_l,
|
||||
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
|
||||
if (SHORT == 1) begin
|
||||
assign dout = din;
|
||||
end
|
||||
else begin
|
||||
`ifdef RV_FPGA_OPTIMIZE
|
||||
rvdffs #(WIDTH) dffs (.clk(rawclk), .en(clken), .*);
|
||||
`else
|
||||
rvdff #(WIDTH) dff (.*);
|
||||
`endif
|
||||
end
|
||||
endmodule
|
||||
|
||||
// rvdff with 2:1 input mux to flop din iff sel==1
|
||||
module rvdffs_fpga #( parameter WIDTH=1, SHORT=0 )
|
||||
(
|
||||
input logic [WIDTH-1:0] din,
|
||||
input logic en,
|
||||
input logic clk,
|
||||
input logic clken,
|
||||
input logic rawclk,
|
||||
input logic rst_l,
|
||||
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
|
||||
if (SHORT == 1) begin : genblock
|
||||
assign dout = din;
|
||||
end
|
||||
else begin : genblock
|
||||
`ifdef RV_FPGA_OPTIMIZE
|
||||
rvdffs #(WIDTH) dffs (.clk(rawclk), .en(clken & en), .*);
|
||||
`else
|
||||
rvdffs #(WIDTH) dffs (.*);
|
||||
`endif
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
// rvdff with en and clear
|
||||
module rvdffsc_fpga #( parameter WIDTH=1, SHORT=0 )
|
||||
(
|
||||
input logic [WIDTH-1:0] din,
|
||||
input logic en,
|
||||
input logic clear,
|
||||
input logic clk,
|
||||
input logic clken,
|
||||
input logic rawclk,
|
||||
input logic rst_l,
|
||||
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
|
||||
logic [WIDTH-1:0] din_new;
|
||||
if (SHORT == 1) begin
|
||||
assign dout = din;
|
||||
end
|
||||
else begin
|
||||
`ifdef RV_FPGA_OPTIMIZE
|
||||
rvdffs #(WIDTH) dffs (.clk(rawclk), .din(din[WIDTH-1:0] & {WIDTH{~clear}}),.en((en | clear) & clken), .*);
|
||||
`else
|
||||
rvdffsc #(WIDTH) dffsc (.*);
|
||||
`endif
|
||||
end
|
||||
endmodule
|
||||
|
||||
|
||||
module rvdffe #( parameter WIDTH=1, SHORT=0, OVERRIDE=0 )
|
||||
(
|
||||
input logic [WIDTH-1:0] din,
|
||||
input logic en,
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
input logic scan_mode,
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
|
||||
logic l1clk;
|
||||
|
||||
if (SHORT == 1) begin : genblock
|
||||
if (1) begin : genblock
|
||||
assign dout = din;
|
||||
end
|
||||
end
|
||||
else begin : genblock
|
||||
|
||||
`ifndef RV_PHYSICAL
|
||||
if (WIDTH >= 8 || OVERRIDE==1) begin: genblock
|
||||
`endif
|
||||
|
||||
`ifdef RV_FPGA_OPTIMIZE
|
||||
rvdffs #(WIDTH) dff ( .* );
|
||||
`else
|
||||
rvclkhdr clkhdr ( .* );
|
||||
rvdff #(WIDTH) dff (.*, .clk(l1clk));
|
||||
`endif
|
||||
|
||||
`ifndef RV_PHYSICAL
|
||||
end
|
||||
else
|
||||
$error("%m: rvdffe must be WIDTH >= 8");
|
||||
`endif
|
||||
end // else: !if(SHORT == 1)
|
||||
|
||||
endmodule // rvdffe
|
||||
|
||||
|
||||
module rvdffpcie #( parameter WIDTH=31 )
|
||||
(
|
||||
input logic [WIDTH-1:0] din,
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
input logic en,
|
||||
input logic scan_mode,
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
|
||||
|
||||
|
||||
`ifndef RV_PHYSICAL
|
||||
if (WIDTH == 31) begin: genblock
|
||||
`endif
|
||||
|
||||
`ifdef RV_FPGA_OPTIMIZE
|
||||
rvdffs #(WIDTH) dff ( .* );
|
||||
`else
|
||||
|
||||
rvdfflie #(.WIDTH(WIDTH), .LEFT(19)) dff (.*);
|
||||
|
||||
`endif
|
||||
|
||||
`ifndef RV_PHYSICAL
|
||||
end
|
||||
else
|
||||
$error("%m: rvdffpcie width must be 31");
|
||||
`endif
|
||||
endmodule
|
||||
|
||||
// format: { LEFT, EXTRA }
|
||||
// LEFT # of bits will be done with rvdffie, all else EXTRA with rvdffe
|
||||
module rvdfflie #( parameter WIDTH=16, LEFT=8 )
|
||||
(
|
||||
input logic [WIDTH-1:0] din,
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
input logic en,
|
||||
input logic scan_mode,
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
|
||||
localparam EXTRA = WIDTH-LEFT;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
localparam LMSB = WIDTH-1;
|
||||
localparam LLSB = LMSB-LEFT+1;
|
||||
localparam XMSB = LLSB-1;
|
||||
localparam XLSB = LLSB-EXTRA;
|
||||
|
||||
|
||||
`ifndef RV_PHYSICAL
|
||||
if (WIDTH >= 16 && LEFT >= 8 && EXTRA >= 8) begin: genblock
|
||||
`endif
|
||||
|
||||
`ifdef RV_FPGA_OPTIMIZE
|
||||
rvdffs #(WIDTH) dff ( .* );
|
||||
`else
|
||||
|
||||
rvdffiee #(LEFT) dff_left (.*, .din(din[LMSB:LLSB]), .dout(dout[LMSB:LLSB]));
|
||||
|
||||
|
||||
rvdffe #(EXTRA) dff_extra (.*, .din(din[XMSB:XLSB]), .dout(dout[XMSB:XLSB]));
|
||||
|
||||
|
||||
|
||||
|
||||
`endif
|
||||
|
||||
`ifndef RV_PHYSICAL
|
||||
end
|
||||
else
|
||||
$error("%m: rvdfflie musb be WIDTH >= 16 && LEFT >= 8 && EXTRA >= 8");
|
||||
`endif
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
|
||||
// special power flop for predict packet
|
||||
// format: { LEFT, RIGHT==31 }
|
||||
// LEFT # of bits will be done with rvdffe; RIGHT is enabled by LEFT[LSB] & en
|
||||
module rvdffppe #( parameter WIDTH=32 )
|
||||
(
|
||||
input logic [WIDTH-1:0] din,
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
input logic en,
|
||||
input logic scan_mode,
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
|
||||
localparam RIGHT = 31;
|
||||
localparam LEFT = WIDTH - RIGHT;
|
||||
|
||||
localparam LMSB = WIDTH-1;
|
||||
localparam LLSB = LMSB-LEFT+1;
|
||||
localparam RMSB = LLSB-1;
|
||||
localparam RLSB = LLSB-RIGHT;
|
||||
|
||||
|
||||
`ifndef RV_PHYSICAL
|
||||
if (WIDTH>=32 && LEFT>=8 && RIGHT>=8) begin: genblock
|
||||
`endif
|
||||
|
||||
`ifdef RV_FPGA_OPTIMIZE
|
||||
rvdffs #(WIDTH) dff ( .* );
|
||||
`else
|
||||
rvdffe #(LEFT) dff_left (.*, .din(din[LMSB:LLSB]), .dout(dout[LMSB:LLSB]));
|
||||
|
||||
rvdffe #(RIGHT) dff_right (.*, .din(din[RMSB:RLSB]), .dout(dout[RMSB:RLSB]), .en(en & din[LLSB])); // qualify with pret
|
||||
|
||||
|
||||
`endif
|
||||
|
||||
`ifndef RV_PHYSICAL
|
||||
end
|
||||
else
|
||||
$error("%m: must be WIDTH>=32 && LEFT>=8 && RIGHT>=8");
|
||||
`endif
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
|
||||
module rvdffie #( parameter WIDTH=1, OVERRIDE=0 )
|
||||
(
|
||||
input logic [WIDTH-1:0] din,
|
||||
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
input logic scan_mode,
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
|
||||
logic l1clk;
|
||||
logic en;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
`ifndef RV_PHYSICAL
|
||||
if (WIDTH >= 8 || OVERRIDE==1) begin: genblock
|
||||
`endif
|
||||
|
||||
assign en = |(din ^ dout);
|
||||
|
||||
`ifdef RV_FPGA_OPTIMIZE
|
||||
rvdffs #(WIDTH) dff ( .* );
|
||||
`else
|
||||
rvclkhdr clkhdr ( .* );
|
||||
rvdff #(WIDTH) dff (.*, .clk(l1clk));
|
||||
`endif
|
||||
|
||||
`ifndef RV_PHYSICAL
|
||||
end
|
||||
else
|
||||
$error("%m: rvdffie must be WIDTH >= 8");
|
||||
`endif
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
// ie flop but it has an .en input
|
||||
module rvdffiee #( parameter WIDTH=1, OVERRIDE=0 )
|
||||
(
|
||||
input logic [WIDTH-1:0] din,
|
||||
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
input logic scan_mode,
|
||||
input logic en,
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
|
||||
logic l1clk;
|
||||
logic final_en;
|
||||
|
||||
`ifndef RV_PHYSICAL
|
||||
if (WIDTH >= 8 || OVERRIDE==1) begin: genblock
|
||||
`endif
|
||||
|
||||
assign final_en = (|(din ^ dout)) & en;
|
||||
|
||||
`ifdef RV_FPGA_OPTIMIZE
|
||||
rvdffs #(WIDTH) dff ( .*, .en(final_en) );
|
||||
`else
|
||||
rvdffe #(WIDTH) dff (.*, .en(final_en));
|
||||
`endif
|
||||
|
||||
`ifndef RV_PHYSICAL
|
||||
end
|
||||
else
|
||||
$error("%m: rvdffie width must be >= 8");
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
module rvsyncss #(parameter WIDTH = 251)
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
input logic [WIDTH-1:0] din,
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
|
||||
logic [WIDTH-1:0] din_ff1;
|
||||
|
||||
rvdff #(WIDTH) sync_ff1 (.*, .din (din[WIDTH-1:0]), .dout(din_ff1[WIDTH-1:0]));
|
||||
rvdff #(WIDTH) sync_ff2 (.*, .din (din_ff1[WIDTH-1:0]), .dout(dout[WIDTH-1:0]));
|
||||
|
||||
endmodule // rvsyncss
|
||||
|
||||
module rvsyncss_fpga #(parameter WIDTH = 251)
|
||||
(
|
||||
input logic gw_clk,
|
||||
input logic rawclk,
|
||||
input logic clken,
|
||||
input logic rst_l,
|
||||
input logic [WIDTH-1:0] din,
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
|
||||
logic [WIDTH-1:0] din_ff1;
|
||||
|
||||
rvdff_fpga #(WIDTH) sync_ff1 (.*, .clk(gw_clk), .rawclk(rawclk), .clken(clken), .din (din[WIDTH-1:0]), .dout(din_ff1[WIDTH-1:0]));
|
||||
rvdff_fpga #(WIDTH) sync_ff2 (.*, .clk(gw_clk), .rawclk(rawclk), .clken(clken), .din (din_ff1[WIDTH-1:0]), .dout(dout[WIDTH-1:0]));
|
||||
|
||||
endmodule // rvsyncss
|
||||
|
||||
module rvlsadder
|
||||
(
|
||||
input logic [31:0] rs1,
|
||||
input logic [11:0] offset,
|
||||
|
||||
output logic [31:0] dout
|
||||
);
|
||||
|
||||
logic cout;
|
||||
logic sign;
|
||||
|
||||
logic [31:12] rs1_inc;
|
||||
logic [31:12] rs1_dec;
|
||||
|
||||
assign {cout,dout[11:0]} = {1'b0,rs1[11:0]} + {1'b0,offset[11:0]};
|
||||
|
||||
assign rs1_inc[31:12] = rs1[31:12] + 1;
|
||||
|
||||
assign rs1_dec[31:12] = rs1[31:12] - 1;
|
||||
|
||||
assign sign = offset[11];
|
||||
|
||||
assign dout[31:12] = ({20{ sign ^~ cout}} & rs1[31:12]) |
|
||||
({20{ ~sign & cout}} & rs1_inc[31:12]) |
|
||||
({20{ sign & ~cout}} & rs1_dec[31:12]);
|
||||
|
||||
endmodule // rvlsadder
|
||||
|
||||
// assume we only maintain pc[31:1] in the pipe
|
||||
|
||||
module rvbradder
|
||||
(
|
||||
input [31:1] pc,
|
||||
input [12:1] offset,
|
||||
|
||||
output [31:1] dout
|
||||
);
|
||||
|
||||
logic cout;
|
||||
logic sign;
|
||||
|
||||
logic [31:13] pc_inc;
|
||||
logic [31:13] pc_dec;
|
||||
|
||||
assign {cout,dout[12:1]} = {1'b0,pc[12:1]} + {1'b0,offset[12:1]};
|
||||
|
||||
assign pc_inc[31:13] = pc[31:13] + 1;
|
||||
|
||||
assign pc_dec[31:13] = pc[31:13] - 1;
|
||||
|
||||
assign sign = offset[12];
|
||||
|
||||
|
||||
assign dout[31:13] = ({19{ sign ^~ cout}} & pc[31:13]) |
|
||||
({19{ ~sign & cout}} & pc_inc[31:13]) |
|
||||
({19{ sign & ~cout}} & pc_dec[31:13]);
|
||||
|
||||
|
||||
endmodule // rvbradder
|
||||
|
||||
|
||||
// 2s complement circuit
|
||||
module rvtwoscomp #( parameter WIDTH=32 )
|
||||
(
|
||||
input logic [WIDTH-1:0] din,
|
||||
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
|
||||
logic [WIDTH-1:1] dout_temp; // holding for all other bits except for the lsb. LSB is always din
|
||||
|
||||
genvar i;
|
||||
|
||||
for ( i = 1; i < WIDTH; i++ ) begin : flip_after_first_one
|
||||
assign dout_temp[i] = (|din[i-1:0]) ? ~din[i] : din[i];
|
||||
end : flip_after_first_one
|
||||
|
||||
assign dout[WIDTH-1:0] = { dout_temp[WIDTH-1:1], din[0] };
|
||||
|
||||
endmodule // 2'scomp
|
||||
|
||||
// find first
|
||||
module rvfindfirst1 #( parameter WIDTH=32, SHIFT=$clog2(WIDTH) )
|
||||
(
|
||||
input logic [WIDTH-1:0] din,
|
||||
|
||||
output logic [SHIFT-1:0] dout
|
||||
);
|
||||
logic done;
|
||||
|
||||
always_comb begin
|
||||
dout[SHIFT-1:0] = {SHIFT{1'b0}};
|
||||
done = 1'b0;
|
||||
|
||||
for ( int i = WIDTH-1; i > 0; i-- ) begin : find_first_one
|
||||
done |= din[i];
|
||||
dout[SHIFT-1:0] += done ? 1'b0 : 1'b1;
|
||||
end : find_first_one
|
||||
end
|
||||
endmodule // rvfindfirst1
|
||||
|
||||
module rvfindfirst1hot #( parameter WIDTH=32 )
|
||||
(
|
||||
input logic [WIDTH-1:0] din,
|
||||
|
||||
output logic [WIDTH-1:0] dout
|
||||
);
|
||||
logic done;
|
||||
|
||||
always_comb begin
|
||||
dout[WIDTH-1:0] = {WIDTH{1'b0}};
|
||||
done = 1'b0;
|
||||
for ( int i = 0; i < WIDTH; i++ ) begin : find_first_one
|
||||
dout[i] = ~done & din[i];
|
||||
done |= din[i];
|
||||
end : find_first_one
|
||||
end
|
||||
endmodule // rvfindfirst1hot
|
||||
|
||||
// mask and match function matches bits after finding the first 0 position
|
||||
// find first starting from LSB. Skip that location and match the rest of the bits
|
||||
module rvmaskandmatch #( parameter WIDTH=32 )
|
||||
(
|
||||
input logic [WIDTH-1:0] mask, // this will have the mask in the lower bit positions
|
||||
input logic [WIDTH-1:0] data, // this is what needs to be matched on the upper bits with the mask's upper bits
|
||||
input logic masken, // when 1 : do mask. 0 : full match
|
||||
output logic match
|
||||
);
|
||||
|
||||
logic [WIDTH-1:0] matchvec;
|
||||
logic masken_or_fullmask;
|
||||
|
||||
assign masken_or_fullmask = masken & ~(&mask[WIDTH-1:0]);
|
||||
|
||||
assign matchvec[0] = masken_or_fullmask | (mask[0] == data[0]);
|
||||
genvar i;
|
||||
|
||||
for ( i = 1; i < WIDTH; i++ ) begin : match_after_first_zero
|
||||
assign matchvec[i] = (&mask[i-1:0] & masken_or_fullmask) ? 1'b1 : (mask[i] == data[i]);
|
||||
end : match_after_first_zero
|
||||
|
||||
assign match = &matchvec[WIDTH-1:0]; // all bits either matched or were masked off
|
||||
|
||||
endmodule // rvmaskandmatch
|
||||
|
||||
|
||||
|
||||
|
||||
// Check if the S_ADDR <= addr < E_ADDR
|
||||
module rvrangecheck #(CCM_SADR = 32'h0,
|
||||
CCM_SIZE = 128) (
|
||||
input logic [31:0] addr, // Address to be checked for range
|
||||
output logic in_range, // S_ADDR <= start_addr < E_ADDR
|
||||
output logic in_region
|
||||
);
|
||||
|
||||
localparam REGION_BITS = 4;
|
||||
localparam MASK_BITS = 10 + $clog2(CCM_SIZE);
|
||||
|
||||
logic [31:0] start_addr;
|
||||
logic [3:0] region;
|
||||
|
||||
assign start_addr[31:0] = CCM_SADR;
|
||||
assign region[REGION_BITS-1:0] = start_addr[31:(32-REGION_BITS)];
|
||||
|
||||
assign in_region = (addr[31:(32-REGION_BITS)] == region[REGION_BITS-1:0]);
|
||||
if (CCM_SIZE == 48)
|
||||
assign in_range = (addr[31:MASK_BITS] == start_addr[31:MASK_BITS]) & ~(&addr[MASK_BITS-1 : MASK_BITS-2]);
|
||||
else
|
||||
assign in_range = (addr[31:MASK_BITS] == start_addr[31:MASK_BITS]);
|
||||
|
||||
endmodule // rvrangechecker
|
||||
|
||||
// 16 bit even parity generator
|
||||
module rveven_paritygen #(WIDTH = 16) (
|
||||
input logic [WIDTH-1:0] data_in, // Data
|
||||
output logic parity_out // generated even parity
|
||||
);
|
||||
|
||||
assign parity_out = ^(data_in[WIDTH-1:0]) ;
|
||||
|
||||
endmodule // rveven_paritygen
|
||||
|
||||
module rveven_paritycheck #(WIDTH = 16) (
|
||||
input logic [WIDTH-1:0] data_in, // Data
|
||||
input logic parity_in,
|
||||
output logic parity_err // Parity error
|
||||
);
|
||||
|
||||
assign parity_err = ^(data_in[WIDTH-1:0]) ^ parity_in ;
|
||||
|
||||
endmodule // rveven_paritycheck
|
||||
|
||||
module rvecc_encode (
|
||||
input [31:0] din,
|
||||
output [6:0] ecc_out
|
||||
);
|
||||
logic [5:0] ecc_out_temp;
|
||||
|
||||
assign ecc_out_temp[0] = din[0]^din[1]^din[3]^din[4]^din[6]^din[8]^din[10]^din[11]^din[13]^din[15]^din[17]^din[19]^din[21]^din[23]^din[25]^din[26]^din[28]^din[30];
|
||||
assign ecc_out_temp[1] = din[0]^din[2]^din[3]^din[5]^din[6]^din[9]^din[10]^din[12]^din[13]^din[16]^din[17]^din[20]^din[21]^din[24]^din[25]^din[27]^din[28]^din[31];
|
||||
assign ecc_out_temp[2] = din[1]^din[2]^din[3]^din[7]^din[8]^din[9]^din[10]^din[14]^din[15]^din[16]^din[17]^din[22]^din[23]^din[24]^din[25]^din[29]^din[30]^din[31];
|
||||
assign ecc_out_temp[3] = din[4]^din[5]^din[6]^din[7]^din[8]^din[9]^din[10]^din[18]^din[19]^din[20]^din[21]^din[22]^din[23]^din[24]^din[25];
|
||||
assign ecc_out_temp[4] = din[11]^din[12]^din[13]^din[14]^din[15]^din[16]^din[17]^din[18]^din[19]^din[20]^din[21]^din[22]^din[23]^din[24]^din[25];
|
||||
assign ecc_out_temp[5] = din[26]^din[27]^din[28]^din[29]^din[30]^din[31];
|
||||
|
||||
assign ecc_out[6:0] = {(^din[31:0])^(^ecc_out_temp[5:0]),ecc_out_temp[5:0]};
|
||||
|
||||
endmodule // rvecc_encode
|
||||
|
||||
module rvecc_decode (
|
||||
input en,
|
||||
input [31:0] din,
|
||||
input [6:0] ecc_in,
|
||||
input sed_ded, // only do detection and no correction. Used for the I$
|
||||
output [31:0] dout,
|
||||
output [6:0] ecc_out,
|
||||
output single_ecc_error,
|
||||
output double_ecc_error
|
||||
|
||||
);
|
||||
|
||||
logic [6:0] ecc_check;
|
||||
logic [38:0] error_mask;
|
||||
logic [38:0] din_plus_parity, dout_plus_parity;
|
||||
|
||||
// Generate the ecc bits
|
||||
assign ecc_check[0] = ecc_in[0]^din[0]^din[1]^din[3]^din[4]^din[6]^din[8]^din[10]^din[11]^din[13]^din[15]^din[17]^din[19]^din[21]^din[23]^din[25]^din[26]^din[28]^din[30];
|
||||
assign ecc_check[1] = ecc_in[1]^din[0]^din[2]^din[3]^din[5]^din[6]^din[9]^din[10]^din[12]^din[13]^din[16]^din[17]^din[20]^din[21]^din[24]^din[25]^din[27]^din[28]^din[31];
|
||||
assign ecc_check[2] = ecc_in[2]^din[1]^din[2]^din[3]^din[7]^din[8]^din[9]^din[10]^din[14]^din[15]^din[16]^din[17]^din[22]^din[23]^din[24]^din[25]^din[29]^din[30]^din[31];
|
||||
assign ecc_check[3] = ecc_in[3]^din[4]^din[5]^din[6]^din[7]^din[8]^din[9]^din[10]^din[18]^din[19]^din[20]^din[21]^din[22]^din[23]^din[24]^din[25];
|
||||
assign ecc_check[4] = ecc_in[4]^din[11]^din[12]^din[13]^din[14]^din[15]^din[16]^din[17]^din[18]^din[19]^din[20]^din[21]^din[22]^din[23]^din[24]^din[25];
|
||||
assign ecc_check[5] = ecc_in[5]^din[26]^din[27]^din[28]^din[29]^din[30]^din[31];
|
||||
|
||||
// This is the parity bit
|
||||
assign ecc_check[6] = ((^din[31:0])^(^ecc_in[6:0])) & ~sed_ded;
|
||||
|
||||
assign single_ecc_error = en & (ecc_check[6:0] != 0) & ecc_check[6]; // this will never be on for sed_ded
|
||||
assign double_ecc_error = en & (ecc_check[6:0] != 0) & ~ecc_check[6]; // all errors in the sed_ded case will be recorded as DE
|
||||
|
||||
// Generate the mask for error correctiong
|
||||
for (genvar i=1; i<40; i++) begin
|
||||
assign error_mask[i-1] = (ecc_check[5:0] == i);
|
||||
end
|
||||
|
||||
// Generate the corrected data
|
||||
assign din_plus_parity[38:0] = {ecc_in[6], din[31:26], ecc_in[5], din[25:11], ecc_in[4], din[10:4], ecc_in[3], din[3:1], ecc_in[2], din[0], ecc_in[1:0]};
|
||||
|
||||
assign dout_plus_parity[38:0] = single_ecc_error ? (error_mask[38:0] ^ din_plus_parity[38:0]) : din_plus_parity[38:0];
|
||||
assign dout[31:0] = {dout_plus_parity[37:32], dout_plus_parity[30:16], dout_plus_parity[14:8], dout_plus_parity[6:4], dout_plus_parity[2]};
|
||||
assign ecc_out[6:0] = {(dout_plus_parity[38] ^ (ecc_check[6:0] == 7'b1000000)), dout_plus_parity[31], dout_plus_parity[15], dout_plus_parity[7], dout_plus_parity[3], dout_plus_parity[1:0]};
|
||||
|
||||
endmodule // rvecc_decode
|
||||
|
||||
module rvecc_encode_64 (
|
||||
input [63:0] din,
|
||||
output [6:0] ecc_out
|
||||
);
|
||||
assign ecc_out[0] = din[0]^din[1]^din[3]^din[4]^din[6]^din[8]^din[10]^din[11]^din[13]^din[15]^din[17]^din[19]^din[21]^din[23]^din[25]^din[26]^din[28]^din[30]^din[32]^din[34]^din[36]^din[38]^din[40]^din[42]^din[44]^din[46]^din[48]^din[50]^din[52]^din[54]^din[56]^din[57]^din[59]^din[61]^din[63];
|
||||
|
||||
assign ecc_out[1] = din[0]^din[2]^din[3]^din[5]^din[6]^din[9]^din[10]^din[12]^din[13]^din[16]^din[17]^din[20]^din[21]^din[24]^din[25]^din[27]^din[28]^din[31]^din[32]^din[35]^din[36]^din[39]^din[40]^din[43]^din[44]^din[47]^din[48]^din[51]^din[52]^din[55]^din[56]^din[58]^din[59]^din[62]^din[63];
|
||||
|
||||
assign ecc_out[2] = din[1]^din[2]^din[3]^din[7]^din[8]^din[9]^din[10]^din[14]^din[15]^din[16]^din[17]^din[22]^din[23]^din[24]^din[25]^din[29]^din[30]^din[31]^din[32]^din[37]^din[38]^din[39]^din[40]^din[45]^din[46]^din[47]^din[48]^din[53]^din[54]^din[55]^din[56]^din[60]^din[61]^din[62]^din[63];
|
||||
|
||||
assign ecc_out[3] = din[4]^din[5]^din[6]^din[7]^din[8]^din[9]^din[10]^din[18]^din[19]^din[20]^din[21]^din[22]^din[23]^din[24]^din[25]^din[33]^din[34]^din[35]^din[36]^din[37]^din[38]^din[39]^din[40]^din[49]^din[50]^din[51]^din[52]^din[53]^din[54]^din[55]^din[56];
|
||||
|
||||
assign ecc_out[4] = din[11]^din[12]^din[13]^din[14]^din[15]^din[16]^din[17]^din[18]^din[19]^din[20]^din[21]^din[22]^din[23]^din[24]^din[25]^din[41]^din[42]^din[43]^din[44]^din[45]^din[46]^din[47]^din[48]^din[49]^din[50]^din[51]^din[52]^din[53]^din[54]^din[55]^din[56];
|
||||
|
||||
assign ecc_out[5] = din[26]^din[27]^din[28]^din[29]^din[30]^din[31]^din[32]^din[33]^din[34]^din[35]^din[36]^din[37]^din[38]^din[39]^din[40]^din[41]^din[42]^din[43]^din[44]^din[45]^din[46]^din[47]^din[48]^din[49]^din[50]^din[51]^din[52]^din[53]^din[54]^din[55]^din[56];
|
||||
|
||||
assign ecc_out[6] = din[57]^din[58]^din[59]^din[60]^din[61]^din[62]^din[63];
|
||||
|
||||
endmodule // rvecc_encode_64
|
||||
|
||||
|
||||
module rvecc_decode_64 (
|
||||
input en,
|
||||
input [63:0] din,
|
||||
input [6:0] ecc_in,
|
||||
output ecc_error
|
||||
);
|
||||
|
||||
logic [6:0] ecc_check;
|
||||
|
||||
// Generate the ecc bits
|
||||
assign ecc_check[0] = ecc_in[0]^din[0]^din[1]^din[3]^din[4]^din[6]^din[8]^din[10]^din[11]^din[13]^din[15]^din[17]^din[19]^din[21]^din[23]^din[25]^din[26]^din[28]^din[30]^din[32]^din[34]^din[36]^din[38]^din[40]^din[42]^din[44]^din[46]^din[48]^din[50]^din[52]^din[54]^din[56]^din[57]^din[59]^din[61]^din[63];
|
||||
|
||||
assign ecc_check[1] = ecc_in[1]^din[0]^din[2]^din[3]^din[5]^din[6]^din[9]^din[10]^din[12]^din[13]^din[16]^din[17]^din[20]^din[21]^din[24]^din[25]^din[27]^din[28]^din[31]^din[32]^din[35]^din[36]^din[39]^din[40]^din[43]^din[44]^din[47]^din[48]^din[51]^din[52]^din[55]^din[56]^din[58]^din[59]^din[62]^din[63];
|
||||
|
||||
assign ecc_check[2] = ecc_in[2]^din[1]^din[2]^din[3]^din[7]^din[8]^din[9]^din[10]^din[14]^din[15]^din[16]^din[17]^din[22]^din[23]^din[24]^din[25]^din[29]^din[30]^din[31]^din[32]^din[37]^din[38]^din[39]^din[40]^din[45]^din[46]^din[47]^din[48]^din[53]^din[54]^din[55]^din[56]^din[60]^din[61]^din[62]^din[63];
|
||||
|
||||
assign ecc_check[3] = ecc_in[3]^din[4]^din[5]^din[6]^din[7]^din[8]^din[9]^din[10]^din[18]^din[19]^din[20]^din[21]^din[22]^din[23]^din[24]^din[25]^din[33]^din[34]^din[35]^din[36]^din[37]^din[38]^din[39]^din[40]^din[49]^din[50]^din[51]^din[52]^din[53]^din[54]^din[55]^din[56];
|
||||
|
||||
assign ecc_check[4] = ecc_in[4]^din[11]^din[12]^din[13]^din[14]^din[15]^din[16]^din[17]^din[18]^din[19]^din[20]^din[21]^din[22]^din[23]^din[24]^din[25]^din[41]^din[42]^din[43]^din[44]^din[45]^din[46]^din[47]^din[48]^din[49]^din[50]^din[51]^din[52]^din[53]^din[54]^din[55]^din[56];
|
||||
|
||||
assign ecc_check[5] = ecc_in[5]^din[26]^din[27]^din[28]^din[29]^din[30]^din[31]^din[32]^din[33]^din[34]^din[35]^din[36]^din[37]^din[38]^din[39]^din[40]^din[41]^din[42]^din[43]^din[44]^din[45]^din[46]^din[47]^din[48]^din[49]^din[50]^din[51]^din[52]^din[53]^din[54]^din[55]^din[56];
|
||||
|
||||
assign ecc_check[6] = ecc_in[6]^din[57]^din[58]^din[59]^din[60]^din[61]^din[62]^din[63];
|
||||
|
||||
assign ecc_error = en & (ecc_check[6:0] != 0); // all errors in the sed_ded case will be recorded as DE
|
||||
|
||||
endmodule // rvecc_decode_64
|
||||
|
||||
|
||||
module TEC_RV_ICG
|
||||
(
|
||||
input logic SE, EN, CK,
|
||||
output Q
|
||||
);
|
||||
|
||||
logic en_ff;
|
||||
logic enable;
|
||||
|
||||
assign enable = EN | SE;
|
||||
|
||||
`ifdef VERILATOR
|
||||
always @(negedge CK) begin
|
||||
en_ff <= enable;
|
||||
end
|
||||
`else
|
||||
always @(CK, enable) begin
|
||||
if(!CK)
|
||||
en_ff = enable;
|
||||
end
|
||||
`endif
|
||||
assign Q = CK & en_ff;
|
||||
|
||||
endmodule
|
||||
|
||||
module rvoclkhdr
|
||||
(
|
||||
input logic en,
|
||||
input logic clk,
|
||||
input logic scan_mode,
|
||||
output logic l1clk
|
||||
);
|
||||
|
||||
logic SE;
|
||||
assign SE = 0;
|
||||
|
||||
`ifdef RV_FPGA_OPTIMIZE
|
||||
assign l1clk = clk;
|
||||
`else
|
||||
TEC_RV_ICG clkhdr ( .*, .EN(en), .CK(clk), .Q(l1clk));
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2018 Western Digital Corporation or it's affiliates.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//------------------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright Western Digital, 2019
|
||||
// Owner : Alex Grobman
|
||||
// Description:
|
||||
// This module Synchronizes the signals between JTAG (TCK) and
|
||||
// processor (Core_clk)
|
||||
//
|
||||
//-------------------------------------------------------------------------------------
|
||||
|
||||
module dmi_jtag_to_core_sync (
|
||||
// JTAG signals
|
||||
input rd_en, // 1 bit Read Enable from JTAG
|
||||
input wr_en, // 1 bit Write enable from JTAG
|
||||
|
||||
// Processor Signals
|
||||
input rst_n, // Core reset
|
||||
input clk, // Core clock
|
||||
|
||||
output reg_en, // 1 bit Write interface bit to Processor
|
||||
output reg_wr_en // 1 bit Write enable to Processor
|
||||
);
|
||||
|
||||
wire c_rd_en;
|
||||
wire c_wr_en;
|
||||
reg [2:0] rden, wren;
|
||||
|
||||
|
||||
// Outputs
|
||||
assign reg_en = c_wr_en | c_rd_en;
|
||||
assign reg_wr_en = c_wr_en;
|
||||
|
||||
|
||||
// synchronizers
|
||||
always @ ( posedge clk or negedge rst_n) begin
|
||||
if(!rst_n) begin
|
||||
rden <= '0;
|
||||
wren <= '0;
|
||||
end
|
||||
else begin
|
||||
rden <= {rden[1:0], rd_en};
|
||||
wren <= {wren[1:0], wr_en};
|
||||
end
|
||||
end
|
||||
|
||||
assign c_rd_en = rden[1] & ~rden[2];
|
||||
assign c_wr_en = wren[1] & ~wren[2];
|
||||
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,90 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2018 Western Digital Corporation or it's affiliates.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//------------------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright Western Digital, 2018
|
||||
// Owner : Anusha Narayanamoorthy
|
||||
// Description:
|
||||
// Wrapper module for JTAG_TAP and DMI synchronizer
|
||||
//
|
||||
//-------------------------------------------------------------------------------------
|
||||
|
||||
module dmi_wrapper(
|
||||
|
||||
// JTAG signals
|
||||
input trst_n, // JTAG reset
|
||||
input tck, // JTAG clock
|
||||
input tms, // Test mode select
|
||||
input tdi, // Test Data Input
|
||||
output tdo, // Test Data Output
|
||||
output tdoEnable, // Test Data Output enable
|
||||
|
||||
// Processor Signals
|
||||
input core_rst_n, // Core reset
|
||||
input core_clk, // Core clock
|
||||
input [31:1] jtag_id, // JTAG ID
|
||||
input [31:0] rd_data, // 32 bit Read data from Processor
|
||||
output [31:0] reg_wr_data, // 32 bit Write data to Processor
|
||||
output [6:0] reg_wr_addr, // 7 bit reg address to Processor
|
||||
output reg_en, // 1 bit Read enable to Processor
|
||||
output reg_wr_en, // 1 bit Write enable to Processor
|
||||
output dmi_hard_reset
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//Wire Declaration
|
||||
wire rd_en;
|
||||
wire wr_en;
|
||||
wire dmireset;
|
||||
|
||||
|
||||
//jtag_tap instantiation
|
||||
rvjtag_tap i_jtag_tap(
|
||||
.trst(trst_n), // dedicated JTAG TRST (active low) pad signal or asynchronous active low power on reset
|
||||
.tck(tck), // dedicated JTAG TCK pad signal
|
||||
.tms(tms), // dedicated JTAG TMS pad signal
|
||||
.tdi(tdi), // dedicated JTAG TDI pad signal
|
||||
.tdo(tdo), // dedicated JTAG TDO pad signal
|
||||
.tdoEnable(tdoEnable), // enable for TDO pad
|
||||
.wr_data(reg_wr_data), // 32 bit Write data
|
||||
.wr_addr(reg_wr_addr), // 7 bit Write address
|
||||
.rd_en(rd_en), // 1 bit read enable
|
||||
.wr_en(wr_en), // 1 bit Write enable
|
||||
.rd_data(rd_data), // 32 bit Read data
|
||||
.rd_status(2'b0),
|
||||
.idle(3'h0), // no need to wait to sample data
|
||||
.dmi_stat(2'b0), // no need to wait or error possible
|
||||
.version(4'h1), // debug spec 0.13 compliant
|
||||
.jtag_id(jtag_id),
|
||||
.dmi_hard_reset(dmi_hard_reset),
|
||||
.dmi_reset(dmireset)
|
||||
);
|
||||
|
||||
|
||||
// dmi_jtag_to_core_sync instantiation
|
||||
dmi_jtag_to_core_sync i_dmi_jtag_to_core_sync(
|
||||
.wr_en(wr_en), // 1 bit Write enable
|
||||
.rd_en(rd_en), // 1 bit Read enable
|
||||
|
||||
.rst_n(core_rst_n),
|
||||
.clk(core_clk),
|
||||
.reg_en(reg_en), // 1 bit Write interface bit
|
||||
.reg_wr_en(reg_wr_en) // 1 bit Write enable
|
||||
);
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,14 @@
|
|||
module gated_latch
|
||||
(
|
||||
input logic SE, EN, CK,
|
||||
output Q
|
||||
);
|
||||
logic en_ff;
|
||||
logic enable;
|
||||
assign enable = EN | SE;
|
||||
always @(CK, enable) begin
|
||||
if(!CK)
|
||||
en_ff = enable;
|
||||
end
|
||||
assign Q = CK & en_ff;
|
||||
endmodule
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,479 @@
|
|||
//********************************************************************************
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 Western Digital Corporation or its affiliates.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//********************************************************************************
|
||||
|
||||
//********************************************************************************
|
||||
// Icache closely coupled memory --- ICCM
|
||||
//********************************************************************************
|
||||
|
||||
module ifu_iccm_mem
|
||||
//`include "parameter.sv"
|
||||
#(
|
||||
parameter ICCM_BITS,
|
||||
parameter ICCM_BANK_INDEX_LO,
|
||||
parameter ICCM_INDEX_BITS,
|
||||
parameter ICCM_BANK_HI,
|
||||
parameter ICCM_NUM_BANKS,
|
||||
// parameter ICCM_ENABLE= 'b1,
|
||||
parameter ICCM_BANK_BITS
|
||||
|
||||
)
|
||||
|
||||
(
|
||||
input logic clk, // Clock only while core active. Through one clock header. For flops with second clock header built in. Connected to ACTIVE_L2CLK.
|
||||
input logic active_clk, // Clock only while core active. Through two clock headers. For flops without second clock header built in.
|
||||
input logic rst_l, // reset, active low
|
||||
input logic clk_override, // Override non-functional clock gating
|
||||
|
||||
input logic iccm_wren, // ICCM write enable
|
||||
input logic iccm_rden, // ICCM read enable
|
||||
input logic [ICCM_BITS-1:1] iccm_rw_addr, // ICCM read/write address
|
||||
input logic iccm_buf_correct_ecc, // ICCM is doing a single bit error correct cycle
|
||||
input logic iccm_correction_state, // ICCM under a correction - This is needed to guard replacements when hit
|
||||
input logic [2:0] iccm_wr_size, // ICCM write size
|
||||
input logic [77:0] iccm_wr_data, // ICCM write data
|
||||
|
||||
input iccm_ext_in_pkt_t [ICCM_NUM_BANKS-1:0] iccm_ext_in_pkt, // External packet
|
||||
|
||||
|
||||
output logic [63:0] iccm_rd_data, // ICCM read data
|
||||
output logic [77:0] iccm_rd_data_ecc, // ICCM read ecc
|
||||
input logic scan_mode // Scan mode control
|
||||
|
||||
);
|
||||
|
||||
|
||||
logic [ICCM_NUM_BANKS-1:0] wren_bank;
|
||||
logic [ICCM_NUM_BANKS-1:0] rden_bank;
|
||||
logic [ICCM_NUM_BANKS-1:0] iccm_clken;
|
||||
logic [ICCM_NUM_BANKS-1:0] [ICCM_BITS-1:ICCM_BANK_INDEX_LO] addr_bank;
|
||||
|
||||
logic [ICCM_NUM_BANKS-1:0] [38:0] iccm_bank_dout, iccm_bank_dout_fn;
|
||||
logic [ICCM_NUM_BANKS-1:0] [38:0] iccm_bank_wr_data;
|
||||
logic [ICCM_BITS-1:1] addr_bank_inc;
|
||||
logic [ICCM_BANK_HI : 2] iccm_rd_addr_hi_q;
|
||||
logic [ICCM_BANK_HI : 1] iccm_rd_addr_lo_q;
|
||||
logic [63:0] iccm_rd_data_pre;
|
||||
logic [63:0] iccm_data;
|
||||
logic [1:0] addr_incr;
|
||||
logic [ICCM_NUM_BANKS-1:0] [38:0] iccm_bank_wr_data_vec;
|
||||
|
||||
// logic to handle hard persisten faults
|
||||
logic [1:0] [ICCM_BITS-1:2] redundant_address;
|
||||
logic [1:0] [38:0] redundant_data;
|
||||
logic [1:0] redundant_valid;
|
||||
logic [ICCM_NUM_BANKS-1:0] sel_red1, sel_red0, sel_red1_q, sel_red0_q;
|
||||
|
||||
|
||||
logic [38:0] redundant_data0_in, redundant_data1_in;
|
||||
logic redundant_lru, redundant_lru_in, redundant_lru_en;
|
||||
logic redundant_data0_en;
|
||||
logic redundant_data1_en;
|
||||
logic r0_addr_en, r1_addr_en;
|
||||
|
||||
// Testing persistent flip
|
||||
// logic [3:0] not_iccm_bank_dout;
|
||||
// logic [15:3] ecc_insert_flip_in, ecc_insert_flip;
|
||||
// logic flip_en, flip_match, flip_match_q;
|
||||
//
|
||||
// assign flip_in = (iccm_rw_addr[3:2] != 2'b00); // dont flip when bank0 - this is to make some progress in DMA streaming cases
|
||||
// assign flip_en = iccm_rden;
|
||||
//
|
||||
// rvdffs #(1) flipmatch (.*,
|
||||
// .clk(clk),
|
||||
// .din(flip_in),
|
||||
// .en(flip_en),
|
||||
// .dout(flip_match_q));
|
||||
//
|
||||
// end of testing flip
|
||||
|
||||
|
||||
assign addr_incr[1:0] = (iccm_wr_size[1:0] == 2'b11) ? 2'b10: 2'b01;
|
||||
assign addr_bank_inc[ICCM_BITS-1 : 1] = iccm_rw_addr[ICCM_BITS-1 : 1] + addr_incr[1:0];
|
||||
|
||||
for (genvar i=0; i<ICCM_NUM_BANKS/2; i++) begin: mem_bank_data
|
||||
assign iccm_bank_wr_data_vec[(2*i)] = iccm_wr_data[38:0];
|
||||
assign iccm_bank_wr_data_vec[(2*i)+1] = iccm_wr_data[77:39];
|
||||
end
|
||||
|
||||
for (genvar i=0; i<ICCM_NUM_BANKS; i++) begin: mem_bank
|
||||
assign wren_bank[i] = iccm_wren & ((iccm_rw_addr[ICCM_BANK_HI:2] == i) | (addr_bank_inc[ICCM_BANK_HI:2] == i));
|
||||
assign iccm_bank_wr_data[i] = iccm_bank_wr_data_vec[i];
|
||||
assign rden_bank[i] = iccm_rden & ( (iccm_rw_addr[ICCM_BANK_HI:2] == i) | (addr_bank_inc[ICCM_BANK_HI:2] == i));
|
||||
assign iccm_clken[i] = wren_bank[i] | rden_bank[i] | clk_override;
|
||||
assign addr_bank[i][ICCM_BITS-1 : ICCM_BANK_INDEX_LO] = wren_bank[i] ? iccm_rw_addr[ICCM_BITS-1 : ICCM_BANK_INDEX_LO] :
|
||||
((addr_bank_inc[ICCM_BANK_HI:2] == i) ?
|
||||
addr_bank_inc[ICCM_BITS-1 : ICCM_BANK_INDEX_LO] :
|
||||
iccm_rw_addr[ICCM_BITS-1 : ICCM_BANK_INDEX_LO]);
|
||||
`ifdef VERILATOR
|
||||
|
||||
el2_ram #(.depth(1<<ICCM_INDEX_BITS), .width(39)) iccm_bank (
|
||||
// Primary ports
|
||||
.ME(iccm_clken[i]),
|
||||
.CLK(clk),
|
||||
.WE(wren_bank[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(iccm_bank_wr_data[i][38:0]),
|
||||
.Q(iccm_bank_dout[i][38:0]),
|
||||
.ROP ( ),
|
||||
// These are used by SoC
|
||||
.TEST1(iccm_ext_in_pkt[i].TEST1),
|
||||
.RME(iccm_ext_in_pkt[i].RME),
|
||||
.RM(iccm_ext_in_pkt[i].RM),
|
||||
.LS(iccm_ext_in_pkt[i].LS),
|
||||
.DS(iccm_ext_in_pkt[i].DS),
|
||||
.SD(iccm_ext_in_pkt[i].SD) ,
|
||||
.TEST_RNM(iccm_ext_in_pkt[i].TEST_RNM),
|
||||
.BC1(iccm_ext_in_pkt[i].BC1),
|
||||
.BC2(iccm_ext_in_pkt[i].BC2)
|
||||
|
||||
);
|
||||
`else
|
||||
|
||||
if (ICCM_INDEX_BITS == 6 ) begin : iccm
|
||||
ram_64x39 iccm_bank (
|
||||
// Primary ports
|
||||
.CLK(clk),
|
||||
.ME(iccm_clken[i]),
|
||||
.WE(wren_bank[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(iccm_bank_wr_data[i][38:0]),
|
||||
.Q(iccm_bank_dout[i][38:0]),
|
||||
.ROP ( ),
|
||||
// These are used by SoC
|
||||
.TEST1(iccm_ext_in_pkt[i].TEST1),
|
||||
.RME(iccm_ext_in_pkt[i].RME),
|
||||
.RM(iccm_ext_in_pkt[i].RM),
|
||||
.LS(iccm_ext_in_pkt[i].LS),
|
||||
.DS(iccm_ext_in_pkt[i].DS),
|
||||
.SD(iccm_ext_in_pkt[i].SD) ,
|
||||
.TEST_RNM(iccm_ext_in_pkt[i].TEST_RNM),
|
||||
.BC1(iccm_ext_in_pkt[i].BC1),
|
||||
.BC2(iccm_ext_in_pkt[i].BC2)
|
||||
|
||||
);
|
||||
end // block: iccm
|
||||
|
||||
else if (ICCM_INDEX_BITS == 7 ) begin : iccm
|
||||
ram_128x39 iccm_bank (
|
||||
// Primary ports
|
||||
.CLK(clk),
|
||||
.ME(iccm_clken[i]),
|
||||
.WE(wren_bank[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(iccm_bank_wr_data[i][38:0]),
|
||||
.Q(iccm_bank_dout[i][38:0]),
|
||||
.ROP ( ),
|
||||
// These are used by SoC
|
||||
.TEST1(iccm_ext_in_pkt[i].TEST1),
|
||||
.RME(iccm_ext_in_pkt[i].RME),
|
||||
.RM(iccm_ext_in_pkt[i].RM),
|
||||
.LS(iccm_ext_in_pkt[i].LS),
|
||||
.DS(iccm_ext_in_pkt[i].DS),
|
||||
.SD(iccm_ext_in_pkt[i].SD) ,
|
||||
.TEST_RNM(iccm_ext_in_pkt[i].TEST_RNM),
|
||||
.BC1(iccm_ext_in_pkt[i].BC1),
|
||||
.BC2(iccm_ext_in_pkt[i].BC2)
|
||||
|
||||
);
|
||||
end // block: iccm
|
||||
|
||||
else if (ICCM_INDEX_BITS == 8 ) begin : iccm
|
||||
ram_256x39 iccm_bank (
|
||||
// Primary ports
|
||||
.CLK(clk),
|
||||
.ME(iccm_clken[i]),
|
||||
.WE(wren_bank[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(iccm_bank_wr_data[i][38:0]),
|
||||
.Q(iccm_bank_dout[i][38:0]),
|
||||
.ROP ( ),
|
||||
// These are used by SoC
|
||||
.TEST1(iccm_ext_in_pkt[i].TEST1),
|
||||
.RME(iccm_ext_in_pkt[i].RME),
|
||||
.RM(iccm_ext_in_pkt[i].RM),
|
||||
.LS(iccm_ext_in_pkt[i].LS),
|
||||
.DS(iccm_ext_in_pkt[i].DS),
|
||||
.SD(iccm_ext_in_pkt[i].SD) ,
|
||||
.TEST_RNM(iccm_ext_in_pkt[i].TEST_RNM),
|
||||
.BC1(iccm_ext_in_pkt[i].BC1),
|
||||
.BC2(iccm_ext_in_pkt[i].BC2)
|
||||
|
||||
);
|
||||
end // block: iccm
|
||||
else if (ICCM_INDEX_BITS == 9 ) begin : iccm
|
||||
ram_512x39 iccm_bank (
|
||||
// Primary ports
|
||||
.CLK(clk),
|
||||
.ME(iccm_clken[i]),
|
||||
.WE(wren_bank[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(iccm_bank_wr_data[i][38:0]),
|
||||
.Q(iccm_bank_dout[i][38:0]),
|
||||
.ROP ( ),
|
||||
// These are used by SoC
|
||||
.TEST1(iccm_ext_in_pkt[i].TEST1),
|
||||
.RME(iccm_ext_in_pkt[i].RME),
|
||||
.RM(iccm_ext_in_pkt[i].RM),
|
||||
.LS(iccm_ext_in_pkt[i].LS),
|
||||
.DS(iccm_ext_in_pkt[i].DS),
|
||||
.SD(iccm_ext_in_pkt[i].SD) ,
|
||||
.TEST_RNM(iccm_ext_in_pkt[i].TEST_RNM),
|
||||
.BC1(iccm_ext_in_pkt[i].BC1),
|
||||
.BC2(iccm_ext_in_pkt[i].BC2)
|
||||
|
||||
);
|
||||
end // block: iccm
|
||||
else if (ICCM_INDEX_BITS == 10 ) begin : iccm
|
||||
ram_1024x39 iccm_bank (
|
||||
// Primary ports
|
||||
.CLK(clk),
|
||||
.ME(iccm_clken[i]),
|
||||
.WE(wren_bank[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(iccm_bank_wr_data[i][38:0]),
|
||||
.Q(iccm_bank_dout[i][38:0]),
|
||||
.ROP ( ),
|
||||
// These are used by SoC
|
||||
.TEST1(iccm_ext_in_pkt[i].TEST1),
|
||||
.RME(iccm_ext_in_pkt[i].RME),
|
||||
.RM(iccm_ext_in_pkt[i].RM),
|
||||
.LS(iccm_ext_in_pkt[i].LS),
|
||||
.DS(iccm_ext_in_pkt[i].DS),
|
||||
.SD(iccm_ext_in_pkt[i].SD) ,
|
||||
.TEST_RNM(iccm_ext_in_pkt[i].TEST_RNM),
|
||||
.BC1(iccm_ext_in_pkt[i].BC1),
|
||||
.BC2(iccm_ext_in_pkt[i].BC2)
|
||||
|
||||
);
|
||||
end // block: iccm
|
||||
else if (ICCM_INDEX_BITS == 11 ) begin : iccm
|
||||
ram_2048x39 iccm_bank (
|
||||
// Primary ports
|
||||
.CLK(clk),
|
||||
.ME(iccm_clken[i]),
|
||||
.WE(wren_bank[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(iccm_bank_wr_data[i][38:0]),
|
||||
.Q(iccm_bank_dout[i][38:0]),
|
||||
.ROP ( ),
|
||||
// These are used by SoC
|
||||
.TEST1(iccm_ext_in_pkt[i].TEST1),
|
||||
.RME(iccm_ext_in_pkt[i].RME),
|
||||
.RM(iccm_ext_in_pkt[i].RM),
|
||||
.LS(iccm_ext_in_pkt[i].LS),
|
||||
.DS(iccm_ext_in_pkt[i].DS),
|
||||
.SD(iccm_ext_in_pkt[i].SD) ,
|
||||
.TEST_RNM(iccm_ext_in_pkt[i].TEST_RNM),
|
||||
.BC1(iccm_ext_in_pkt[i].BC1),
|
||||
.BC2(iccm_ext_in_pkt[i].BC2)
|
||||
|
||||
);
|
||||
end // block: iccm
|
||||
else if (ICCM_INDEX_BITS == 12 ) begin : iccm
|
||||
ram_4096x39 iccm_bank (
|
||||
// Primary ports
|
||||
.CLK(clk),
|
||||
.ME(iccm_clken[i]),
|
||||
.WE(wren_bank[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(iccm_bank_wr_data[i][38:0]),
|
||||
.Q(iccm_bank_dout[i][38:0]),
|
||||
.ROP ( ),
|
||||
// These are used by SoC
|
||||
.TEST1(iccm_ext_in_pkt[i].TEST1),
|
||||
.RME(iccm_ext_in_pkt[i].RME),
|
||||
.RM(iccm_ext_in_pkt[i].RM),
|
||||
.LS(iccm_ext_in_pkt[i].LS),
|
||||
.DS(iccm_ext_in_pkt[i].DS),
|
||||
.SD(iccm_ext_in_pkt[i].SD) ,
|
||||
.TEST_RNM(iccm_ext_in_pkt[i].TEST_RNM),
|
||||
.BC1(iccm_ext_in_pkt[i].BC1),
|
||||
.BC2(iccm_ext_in_pkt[i].BC2)
|
||||
|
||||
);
|
||||
end // block: iccm
|
||||
else if (ICCM_INDEX_BITS == 13 ) begin : iccm
|
||||
ram_8192x39 iccm_bank (
|
||||
// Primary ports
|
||||
.CLK(clk),
|
||||
.ME(iccm_clken[i]),
|
||||
.WE(wren_bank[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(iccm_bank_wr_data[i][38:0]),
|
||||
.Q(iccm_bank_dout[i][38:0]),
|
||||
.ROP ( ),
|
||||
// These are used by SoC
|
||||
.TEST1(iccm_ext_in_pkt[i].TEST1),
|
||||
.RME(iccm_ext_in_pkt[i].RME),
|
||||
.RM(iccm_ext_in_pkt[i].RM),
|
||||
.LS(iccm_ext_in_pkt[i].LS),
|
||||
.DS(iccm_ext_in_pkt[i].DS),
|
||||
.SD(iccm_ext_in_pkt[i].SD) ,
|
||||
.TEST_RNM(iccm_ext_in_pkt[i].TEST_RNM),
|
||||
.BC1(iccm_ext_in_pkt[i].BC1),
|
||||
.BC2(iccm_ext_in_pkt[i].BC2)
|
||||
|
||||
);
|
||||
end // block: iccm
|
||||
else if (ICCM_INDEX_BITS == 14 ) begin : iccm
|
||||
ram_16384x39 iccm_bank (
|
||||
// Primary ports
|
||||
.CLK(clk),
|
||||
.ME(iccm_clken[i]),
|
||||
.WE(wren_bank[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(iccm_bank_wr_data[i][38:0]),
|
||||
.Q(iccm_bank_dout[i][38:0]),
|
||||
.ROP ( ),
|
||||
// These are used by SoC
|
||||
.TEST1(iccm_ext_in_pkt[i].TEST1),
|
||||
.RME(iccm_ext_in_pkt[i].RME),
|
||||
.RM(iccm_ext_in_pkt[i].RM),
|
||||
.LS(iccm_ext_in_pkt[i].LS),
|
||||
.DS(iccm_ext_in_pkt[i].DS),
|
||||
.SD(iccm_ext_in_pkt[i].SD) ,
|
||||
.TEST_RNM(iccm_ext_in_pkt[i].TEST_RNM),
|
||||
.BC1(iccm_ext_in_pkt[i].BC1),
|
||||
.BC2(iccm_ext_in_pkt[i].BC2)
|
||||
|
||||
);
|
||||
end // block: iccm
|
||||
else begin : iccm
|
||||
ram_32768x39 iccm_bank (
|
||||
// Primary ports
|
||||
.CLK(clk),
|
||||
.ME(iccm_clken[i]),
|
||||
.WE(wren_bank[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(iccm_bank_wr_data[i][38:0]),
|
||||
.Q(iccm_bank_dout[i][38:0]),
|
||||
.ROP ( ),
|
||||
// These are used by SoC
|
||||
.TEST1(iccm_ext_in_pkt[i].TEST1),
|
||||
.RME(iccm_ext_in_pkt[i].RME),
|
||||
.RM(iccm_ext_in_pkt[i].RM),
|
||||
.LS(iccm_ext_in_pkt[i].LS),
|
||||
.DS(iccm_ext_in_pkt[i].DS),
|
||||
.SD(iccm_ext_in_pkt[i].SD) ,
|
||||
.TEST_RNM(iccm_ext_in_pkt[i].TEST_RNM),
|
||||
.BC1(iccm_ext_in_pkt[i].BC1),
|
||||
.BC2(iccm_ext_in_pkt[i].BC2)
|
||||
|
||||
);
|
||||
end // block: iccm
|
||||
`endif
|
||||
|
||||
// match the redundant rows
|
||||
assign sel_red1[i] = (redundant_valid[1] & (((iccm_rw_addr[ICCM_BITS-1:2] == redundant_address[1][ICCM_BITS-1:2]) & (iccm_rw_addr[3:2] == i)) |
|
||||
((addr_bank_inc[ICCM_BITS-1:2]== redundant_address[1][ICCM_BITS-1:2]) & (addr_bank_inc[3:2] == i))));
|
||||
|
||||
assign sel_red0[i] = (redundant_valid[0] & (((iccm_rw_addr[ICCM_BITS-1:2] == redundant_address[0][ICCM_BITS-1:2]) & (iccm_rw_addr[3:2] == i)) |
|
||||
((addr_bank_inc[ICCM_BITS-1:2]== redundant_address[0][ICCM_BITS-1:2]) & (addr_bank_inc[3:2] == i))));
|
||||
|
||||
rvdff #(1) selred0 (.*,
|
||||
.clk(active_clk),
|
||||
.din(sel_red0[i]),
|
||||
.dout(sel_red0_q[i]));
|
||||
|
||||
rvdff #(1) selred1 (.*,
|
||||
.clk(active_clk),
|
||||
.din(sel_red1[i]),
|
||||
.dout(sel_red1_q[i]));
|
||||
|
||||
|
||||
// muxing out the memory data with the redundant data if the address matches
|
||||
assign iccm_bank_dout_fn[i][38:0] = ({39{sel_red1_q[i]}} & redundant_data[1][38:0]) |
|
||||
({39{sel_red0_q[i]}} & redundant_data[0][38:0]) |
|
||||
({39{~sel_red0_q[i] & ~sel_red1_q[i]}} & iccm_bank_dout[i][38:0]);
|
||||
|
||||
end : mem_bank
|
||||
// This section does the redundancy for tolerating single bit errors
|
||||
// 2x 39 bit data values with address[hi:2] and a valid bit is needed to CAM and sub out the reads/writes to the particular locations
|
||||
// Also a LRU flop is kept to decide which of the redundant element to replace.
|
||||
assign r0_addr_en = ~redundant_lru & iccm_buf_correct_ecc;
|
||||
assign r1_addr_en = redundant_lru & iccm_buf_correct_ecc;
|
||||
assign redundant_lru_en = iccm_buf_correct_ecc | (((|sel_red0[ICCM_NUM_BANKS-1:0]) | (|sel_red1[ICCM_NUM_BANKS-1:0])) & iccm_rden & iccm_correction_state);
|
||||
assign redundant_lru_in = iccm_buf_correct_ecc ? ~redundant_lru : (|sel_red0[ICCM_NUM_BANKS-1:0]) ? 1'b1 : 1'b0;
|
||||
|
||||
rvdffs #() red_lru (.*, // LRU flop for the redundant replacements
|
||||
.clk(active_clk),
|
||||
.en(redundant_lru_en),
|
||||
.din(redundant_lru_in),
|
||||
.dout(redundant_lru));
|
||||
|
||||
rvdffs #(ICCM_BITS-2) r0_address (.*, // Redundant Row 0 address
|
||||
.clk(active_clk),
|
||||
.en(r0_addr_en),
|
||||
.din(iccm_rw_addr[ICCM_BITS-1:2]),
|
||||
.dout(redundant_address[0][ICCM_BITS-1:2]));
|
||||
|
||||
rvdffs #(ICCM_BITS-2) r1_address (.*, // Redundant Row 0 address
|
||||
.clk(active_clk),
|
||||
.en(r1_addr_en),
|
||||
.din(iccm_rw_addr[ICCM_BITS-1:2]),
|
||||
.dout(redundant_address[1][ICCM_BITS-1:2]));
|
||||
|
||||
rvdffs #(1) r0_valid (.*,
|
||||
.clk(active_clk), // Redundant Row 0 Valid
|
||||
.en(r0_addr_en),
|
||||
.din(1'b1),
|
||||
.dout(redundant_valid[0]));
|
||||
|
||||
rvdffs #(1) r1_valid (.*, // Redundant Row 1 Valid
|
||||
.clk(active_clk),
|
||||
.en(r1_addr_en),
|
||||
.din(1'b1),
|
||||
.dout(redundant_valid[1]));
|
||||
|
||||
|
||||
|
||||
// We will have to update the Redundant copies in addition to the memory on subsequent writes to this memory location.
|
||||
// The data gets updated on : 1) correction cycle, 2) Future writes - this could be W writes from DMA ( match up till addr[2]) or DW writes ( match till address[3])
|
||||
// The data to pick also depends on the current address[2], size and the addr[2] stored in the address field of the redundant flop. Correction cycle is always W write and the data is splat on both legs, so choosing lower Word
|
||||
|
||||
assign redundant_data0_en = ((iccm_rw_addr[ICCM_BITS-1:3] == redundant_address[0][ICCM_BITS-1:3]) & ((iccm_rw_addr[2] == redundant_address[0][2]) | (iccm_wr_size[1:0] == 2'b11)) & redundant_valid[0] & iccm_wren) |
|
||||
(~redundant_lru & iccm_buf_correct_ecc);
|
||||
|
||||
assign redundant_data0_in[38:0] = (((iccm_rw_addr[2] == redundant_address[0][2]) & iccm_rw_addr[2]) | (redundant_address[0][2] & (iccm_wr_size[1:0] == 2'b11))) ? iccm_wr_data[77:39] : iccm_wr_data[38:0];
|
||||
|
||||
rvdffs #(39) r0_data (.*, // Redundant Row 1 data
|
||||
.clk(active_clk),
|
||||
.en(redundant_data0_en),
|
||||
.din(redundant_data0_in[38:0]),
|
||||
.dout(redundant_data[0][38:0]));
|
||||
|
||||
assign redundant_data1_en = ((iccm_rw_addr[ICCM_BITS-1:3] == redundant_address[1][ICCM_BITS-1:3]) & ((iccm_rw_addr[2] == redundant_address[1][2]) | (iccm_wr_size[1:0] == 2'b11)) & redundant_valid[1] & iccm_wren) |
|
||||
(redundant_lru & iccm_buf_correct_ecc);
|
||||
|
||||
assign redundant_data1_in[38:0] = (((iccm_rw_addr[2] == redundant_address[1][2]) & iccm_rw_addr[2]) | (redundant_address[1][2] & (iccm_wr_size[1:0] == 2'b11))) ? iccm_wr_data[77:39] : iccm_wr_data[38:0];
|
||||
|
||||
rvdffs #(39) r1_data (.*, // Redundant Row 1 data
|
||||
.clk(active_clk),
|
||||
.en(redundant_data1_en),
|
||||
.din(redundant_data1_in[38:0]),
|
||||
.dout(redundant_data[1][38:0]));
|
||||
|
||||
|
||||
rvdffs #(ICCM_BANK_HI) rd_addr_lo_ff (.*, .clk(active_clk), .din(iccm_rw_addr [ICCM_BANK_HI:1]), .dout(iccm_rd_addr_lo_q[ICCM_BANK_HI:1]), .en(1'b1)); // bit 0 of address is always 0
|
||||
rvdffs #(ICCM_BANK_BITS) rd_addr_hi_ff (.*, .clk(active_clk), .din(addr_bank_inc[ICCM_BANK_HI:2]), .dout(iccm_rd_addr_hi_q[ICCM_BANK_HI:2]), .en(1'b1));
|
||||
|
||||
assign iccm_rd_data_pre[63:0] = {iccm_bank_dout_fn[iccm_rd_addr_hi_q][31:0], iccm_bank_dout_fn[iccm_rd_addr_lo_q[ICCM_BANK_HI:2]][31:0]};
|
||||
assign iccm_data[63:0] = 64'({16'b0, (iccm_rd_data_pre[63:0] >> (16*iccm_rd_addr_lo_q[1]))});
|
||||
assign iccm_rd_data[63:0] = {iccm_data[63:0]};
|
||||
assign iccm_rd_data_ecc[77:0] = {iccm_bank_dout_fn[iccm_rd_addr_hi_q][38:0], iccm_bank_dout_fn[iccm_rd_addr_lo_q[ICCM_BANK_HI:2]][38:0]};
|
||||
|
||||
endmodule // ifu_iccm_mem
|
|
@ -0,0 +1,302 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 Western Digital Corporation or its affiliates.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//********************************************************************************
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Owner:
|
||||
// Function: DCCM for LSU pipe
|
||||
// Comments: Single ported memory
|
||||
//
|
||||
//
|
||||
// DC1 -> DC2 -> DC3 -> DC4 (Commit)
|
||||
//
|
||||
// //********************************************************************************
|
||||
|
||||
|
||||
|
||||
`define LOCAL_DCCM_RAM_TEST_PORTS .TEST1(dccm_ext_in_pkt[i].TEST1), \
|
||||
.RME(dccm_ext_in_pkt[i].RME), \
|
||||
.RM(dccm_ext_in_pkt[i].RM), \
|
||||
.LS(dccm_ext_in_pkt[i].LS), \
|
||||
.DS(dccm_ext_in_pkt[i].DS), \
|
||||
.SD(dccm_ext_in_pkt[i].SD), \
|
||||
.TEST_RNM(dccm_ext_in_pkt[i].TEST_RNM), \
|
||||
.BC1(dccm_ext_in_pkt[i].BC1), \
|
||||
.BC2(dccm_ext_in_pkt[i].BC2), \
|
||||
|
||||
|
||||
|
||||
module lsu_dccm_mem
|
||||
//`include "parameter.sv"
|
||||
#(
|
||||
|
||||
parameter DCCM_BYTE_WIDTH,
|
||||
parameter DCCM_BITS,
|
||||
parameter DCCM_NUM_BANKS,
|
||||
parameter DCCM_ENABLE= 'b1,
|
||||
parameter DCCM_BANK_BITS,
|
||||
parameter DCCM_SIZE,
|
||||
parameter DCCM_FDATA_WIDTH,
|
||||
parameter DCCM_WIDTH_BITS
|
||||
)
|
||||
(
|
||||
input logic clk, // Clock only while core active. Through one clock header. For flops with second clock header built in. Connected to ACTIVE_L2CLK.
|
||||
input logic active_clk, // Clock only while core active. Through two clock headers. For flops without second clock header built in.
|
||||
input logic rst_l, // reset, active low
|
||||
input logic clk_override, // Override non-functional clock gating
|
||||
|
||||
input logic dccm_wren, // write enable
|
||||
input logic dccm_rden, // read enable
|
||||
input logic [DCCM_BITS-1:0] dccm_wr_addr_lo, // write address
|
||||
input logic [DCCM_BITS-1:0] dccm_wr_addr_hi, // write address
|
||||
input logic [DCCM_BITS-1:0] dccm_rd_addr_lo, // read address
|
||||
input logic [DCCM_BITS-1:0] dccm_rd_addr_hi, // read address for the upper bank in case of a misaligned access
|
||||
input logic [DCCM_FDATA_WIDTH-1:0] dccm_wr_data_lo, // write data
|
||||
input logic [DCCM_FDATA_WIDTH-1:0] dccm_wr_data_hi, // write data
|
||||
input dccm_ext_in_pkt_t [DCCM_NUM_BANKS-1:0] dccm_ext_in_pkt, // the dccm packet from the soc
|
||||
|
||||
output logic [DCCM_FDATA_WIDTH-1:0] dccm_rd_data_lo, // read data from the lo bank
|
||||
output logic [DCCM_FDATA_WIDTH-1:0] dccm_rd_data_hi, // read data from the hi bank
|
||||
|
||||
input logic scan_mode
|
||||
);
|
||||
|
||||
|
||||
//localparam DCCM_WIDTH_BITS = $clog2(DCCM_BYTE_WIDTH);
|
||||
localparam DCCM_INDEX_BITS = (DCCM_BITS - DCCM_BANK_BITS - DCCM_WIDTH_BITS);
|
||||
localparam DCCM_INDEX_DEPTH = ((DCCM_SIZE)*1024)/((DCCM_BYTE_WIDTH)*(DCCM_NUM_BANKS)); // Depth of memory bank
|
||||
|
||||
logic [DCCM_NUM_BANKS-1:0] wren_bank;
|
||||
logic [DCCM_NUM_BANKS-1:0] rden_bank;
|
||||
logic [DCCM_NUM_BANKS-1:0] [DCCM_BITS-1:(DCCM_BANK_BITS+2)] addr_bank;
|
||||
logic [DCCM_BITS-1:(DCCM_BANK_BITS+DCCM_WIDTH_BITS)] rd_addr_even, rd_addr_odd;
|
||||
logic rd_unaligned, wr_unaligned;
|
||||
logic [DCCM_NUM_BANKS-1:0] [DCCM_FDATA_WIDTH-1:0] dccm_bank_dout;
|
||||
logic [DCCM_FDATA_WIDTH-1:0] wrdata;
|
||||
|
||||
logic [DCCM_NUM_BANKS-1:0][DCCM_FDATA_WIDTH-1:0] wr_data_bank;
|
||||
|
||||
logic [(DCCM_WIDTH_BITS+DCCM_BANK_BITS-1):DCCM_WIDTH_BITS] dccm_rd_addr_lo_q;
|
||||
logic [(DCCM_WIDTH_BITS+DCCM_BANK_BITS-1):DCCM_WIDTH_BITS] dccm_rd_addr_hi_q;
|
||||
|
||||
logic [DCCM_NUM_BANKS-1:0] dccm_clken;
|
||||
|
||||
assign rd_unaligned = (dccm_rd_addr_lo[DCCM_WIDTH_BITS+:DCCM_BANK_BITS] != dccm_rd_addr_hi[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]);
|
||||
assign wr_unaligned = (dccm_wr_addr_lo[DCCM_WIDTH_BITS+:DCCM_BANK_BITS] != dccm_wr_addr_hi[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]);
|
||||
|
||||
// Align the read data
|
||||
assign dccm_rd_data_lo[DCCM_FDATA_WIDTH-1:0] = dccm_bank_dout[dccm_rd_addr_lo_q[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]][DCCM_FDATA_WIDTH-1:0];
|
||||
assign dccm_rd_data_hi[DCCM_FDATA_WIDTH-1:0] = dccm_bank_dout[dccm_rd_addr_hi_q[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]][DCCM_FDATA_WIDTH-1:0];
|
||||
|
||||
|
||||
// 8 Banks, 16KB each (2048 x 72)
|
||||
for (genvar i=0; i<DCCM_NUM_BANKS; i++) begin: mem_bank
|
||||
assign wren_bank[i] = dccm_wren & ((dccm_wr_addr_hi[2+:DCCM_BANK_BITS] == i) | (dccm_wr_addr_lo[2+:DCCM_BANK_BITS] == i));
|
||||
assign rden_bank[i] = dccm_rden & ((dccm_rd_addr_hi[2+:DCCM_BANK_BITS] == i) | (dccm_rd_addr_lo[2+:DCCM_BANK_BITS] == i));
|
||||
assign addr_bank[i][(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] = wren_bank[i] ? (((dccm_wr_addr_hi[2+:DCCM_BANK_BITS] == i) & wr_unaligned) ?
|
||||
dccm_wr_addr_hi[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] :
|
||||
dccm_wr_addr_lo[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS]) :
|
||||
(((dccm_rd_addr_hi[2+:DCCM_BANK_BITS] == i) & rd_unaligned) ?
|
||||
dccm_rd_addr_hi[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS] :
|
||||
dccm_rd_addr_lo[(DCCM_BANK_BITS+DCCM_WIDTH_BITS)+:DCCM_INDEX_BITS]);
|
||||
|
||||
assign wr_data_bank[i] = ((dccm_wr_addr_hi[2+:DCCM_BANK_BITS] == i) & wr_unaligned) ? dccm_wr_data_hi[DCCM_FDATA_WIDTH-1:0] : dccm_wr_data_lo[DCCM_FDATA_WIDTH-1:0];
|
||||
|
||||
// clock gating section
|
||||
assign dccm_clken[i] = (wren_bank[i] | rden_bank[i] | clk_override) ;
|
||||
// end clock gating section
|
||||
|
||||
`ifdef VERILATOR
|
||||
|
||||
el2_ram #(DCCM_INDEX_DEPTH,39) ram (
|
||||
// Primary ports
|
||||
.ME(dccm_clken[i]),
|
||||
.CLK(clk),
|
||||
.WE(wren_bank[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(wr_data_bank[i][DCCM_FDATA_WIDTH-1:0]),
|
||||
.Q(dccm_bank_dout[i][DCCM_FDATA_WIDTH-1:0]),
|
||||
.ROP ( ),
|
||||
// These are used by SoC
|
||||
`LOCAL_DCCM_RAM_TEST_PORTS
|
||||
.*
|
||||
);
|
||||
`else
|
||||
|
||||
if (DCCM_INDEX_DEPTH == 32768) begin : dccm
|
||||
ram_32768x39 dccm_bank (
|
||||
// Primary ports
|
||||
.ME(dccm_clken[i]),
|
||||
.CLK(clk),
|
||||
.WE(wren_bank[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(wr_data_bank[i][DCCM_FDATA_WIDTH-1:0]),
|
||||
.Q(dccm_bank_dout[i][DCCM_FDATA_WIDTH-1:0]),
|
||||
.ROP ( ),
|
||||
// These are used by SoC
|
||||
`LOCAL_DCCM_RAM_TEST_PORTS
|
||||
.*
|
||||
);
|
||||
end
|
||||
else if (DCCM_INDEX_DEPTH == 16384) begin : dccm
|
||||
ram_16384x39 dccm_bank (
|
||||
// Primary ports
|
||||
.ME(dccm_clken[i]),
|
||||
.CLK(clk),
|
||||
.WE(wren_bank[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(wr_data_bank[i][DCCM_FDATA_WIDTH-1:0]),
|
||||
.Q(dccm_bank_dout[i][DCCM_FDATA_WIDTH-1:0]),
|
||||
.ROP ( ),
|
||||
// These are used by SoC
|
||||
`LOCAL_DCCM_RAM_TEST_PORTS
|
||||
.*
|
||||
);
|
||||
end
|
||||
else if (DCCM_INDEX_DEPTH == 8192) begin : dccm
|
||||
ram_8192x39 dccm_bank (
|
||||
// Primary ports
|
||||
.ME(dccm_clken[i]),
|
||||
.CLK(clk),
|
||||
.WE(wren_bank[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(wr_data_bank[i][DCCM_FDATA_WIDTH-1:0]),
|
||||
.Q(dccm_bank_dout[i][DCCM_FDATA_WIDTH-1:0]),
|
||||
.ROP ( ),
|
||||
// These are used by SoC
|
||||
`LOCAL_DCCM_RAM_TEST_PORTS
|
||||
.*
|
||||
);
|
||||
end
|
||||
else if (DCCM_INDEX_DEPTH == 4096) begin : dccm
|
||||
ram_4096x39 dccm_bank (
|
||||
// Primary ports
|
||||
.ME(dccm_clken[i]),
|
||||
.CLK(clk),
|
||||
.WE(wren_bank[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(wr_data_bank[i][DCCM_FDATA_WIDTH-1:0]),
|
||||
.Q(dccm_bank_dout[i][DCCM_FDATA_WIDTH-1:0]),
|
||||
.ROP ( ),
|
||||
// These are used by SoC
|
||||
`LOCAL_DCCM_RAM_TEST_PORTS
|
||||
.*
|
||||
);
|
||||
end
|
||||
else if (DCCM_INDEX_DEPTH == 3072) begin : dccm
|
||||
ram_3072x39 dccm_bank (
|
||||
// Primary ports
|
||||
.ME(dccm_clken[i]),
|
||||
.CLK(clk),
|
||||
.WE(wren_bank[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(wr_data_bank[i][DCCM_FDATA_WIDTH-1:0]),
|
||||
.Q(dccm_bank_dout[i][DCCM_FDATA_WIDTH-1:0]),
|
||||
.ROP ( ),
|
||||
// These are used by SoC
|
||||
`LOCAL_DCCM_RAM_TEST_PORTS
|
||||
.*
|
||||
);
|
||||
end
|
||||
else if (DCCM_INDEX_DEPTH == 2048) begin : dccm
|
||||
ram_2048x39 dccm_bank (
|
||||
// Primary ports
|
||||
.ME(dccm_clken[i]),
|
||||
.CLK(clk),
|
||||
.WE(wren_bank[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(wr_data_bank[i][DCCM_FDATA_WIDTH-1:0]),
|
||||
.Q(dccm_bank_dout[i][DCCM_FDATA_WIDTH-1:0]),
|
||||
.ROP ( ),
|
||||
// These are used by SoC
|
||||
`LOCAL_DCCM_RAM_TEST_PORTS
|
||||
.*
|
||||
);
|
||||
end
|
||||
else if (DCCM_INDEX_DEPTH == 1024) begin : dccm
|
||||
ram_1024x39 dccm_bank (
|
||||
// Primary ports
|
||||
.ME(dccm_clken[i]),
|
||||
.CLK(clk),
|
||||
.WE(wren_bank[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(wr_data_bank[i][DCCM_FDATA_WIDTH-1:0]),
|
||||
.Q(dccm_bank_dout[i][DCCM_FDATA_WIDTH-1:0]),
|
||||
.ROP ( ),
|
||||
// These are used by SoC
|
||||
`LOCAL_DCCM_RAM_TEST_PORTS
|
||||
.*
|
||||
);
|
||||
end
|
||||
else if (DCCM_INDEX_DEPTH == 512) begin : dccm
|
||||
ram_512x39 dccm_bank (
|
||||
// Primary ports
|
||||
.ME(dccm_clken[i]),
|
||||
.CLK(clk),
|
||||
.WE(wren_bank[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(wr_data_bank[i][DCCM_FDATA_WIDTH-1:0]),
|
||||
.Q(dccm_bank_dout[i][DCCM_FDATA_WIDTH-1:0]),
|
||||
.ROP ( ),
|
||||
// These are used by SoC
|
||||
`LOCAL_DCCM_RAM_TEST_PORTS
|
||||
.*
|
||||
);
|
||||
end
|
||||
else if (DCCM_INDEX_DEPTH == 256) begin : dccm
|
||||
ram_256x39 dccm_bank (
|
||||
// Primary ports
|
||||
.ME(dccm_clken[i]),
|
||||
.CLK(clk),
|
||||
.WE(wren_bank[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(wr_data_bank[i][DCCM_FDATA_WIDTH-1:0]),
|
||||
.Q(dccm_bank_dout[i][DCCM_FDATA_WIDTH-1:0]),
|
||||
.ROP ( ),
|
||||
// These are used by SoC
|
||||
`LOCAL_DCCM_RAM_TEST_PORTS
|
||||
.*
|
||||
);
|
||||
end
|
||||
else if (DCCM_INDEX_DEPTH == 128) begin : dccm
|
||||
ram_128x39 dccm_bank (
|
||||
// Primary ports
|
||||
.ME(dccm_clken[i]),
|
||||
.CLK(clk),
|
||||
.WE(wren_bank[i]),
|
||||
.ADR(addr_bank[i]),
|
||||
.D(wr_data_bank[i][DCCM_FDATA_WIDTH-1:0]),
|
||||
.Q(dccm_bank_dout[i][DCCM_FDATA_WIDTH-1:0]),
|
||||
.ROP ( ),
|
||||
// These are used by SoC
|
||||
`LOCAL_DCCM_RAM_TEST_PORTS
|
||||
.*
|
||||
);
|
||||
end
|
||||
`endif
|
||||
|
||||
end : mem_bank
|
||||
|
||||
// Flops
|
||||
rvdff #(DCCM_BANK_BITS) rd_addr_lo_ff (.*, .din(dccm_rd_addr_lo[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]), .dout(dccm_rd_addr_lo_q[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]), .clk(active_clk));
|
||||
rvdff #(DCCM_BANK_BITS) rd_addr_hi_ff (.*, .din(dccm_rd_addr_hi[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]), .dout(dccm_rd_addr_hi_q[DCCM_WIDTH_BITS+:DCCM_BANK_BITS]), .clk(active_clk));
|
||||
|
||||
`undef LOCAL_DCCM_RAM_TEST_PORTS
|
||||
|
||||
endmodule // lsu_dccm_mem
|
||||
|
||||
|
|
@ -0,0 +1,549 @@
|
|||
//********************************************************************************
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 Western Digital Corporation or its affiliates.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//********************************************************************************
|
||||
|
||||
typedef struct packed {
|
||||
logic TEST1;
|
||||
logic RME;
|
||||
logic [3:0] RM;
|
||||
|
||||
logic LS;
|
||||
logic DS;
|
||||
logic SD;
|
||||
logic TEST_RNM;
|
||||
logic BC1;
|
||||
logic BC2;
|
||||
} iccm_ext_in_pkt_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic TEST1;
|
||||
logic RME;
|
||||
logic [3:0] RM;
|
||||
logic LS;
|
||||
logic DS;
|
||||
logic SD;
|
||||
logic TEST_RNM;
|
||||
logic BC1;
|
||||
logic BC2;
|
||||
} dccm_ext_in_pkt_t;
|
||||
|
||||
|
||||
typedef struct packed {
|
||||
logic TEST1;
|
||||
logic RME;
|
||||
logic [3:0] RM;
|
||||
logic LS;
|
||||
logic DS;
|
||||
logic SD;
|
||||
logic TEST_RNM;
|
||||
logic BC1;
|
||||
logic BC2;
|
||||
} ic_data_ext_in_pkt_t;
|
||||
|
||||
|
||||
typedef struct packed {
|
||||
logic TEST1;
|
||||
logic RME;
|
||||
logic [3:0] RM;
|
||||
logic LS;
|
||||
logic DS;
|
||||
logic SD;
|
||||
logic TEST_RNM;
|
||||
logic BC1;
|
||||
logic BC2;
|
||||
} ic_tag_ext_in_pkt_t;
|
||||
module mem#(
|
||||
parameter ICACHE_BEAT_BITS,
|
||||
parameter ICCM_BITS,
|
||||
parameter ICACHE_NUM_WAYS,
|
||||
parameter DCCM_BYTE_WIDTH,
|
||||
parameter ICCM_BANK_INDEX_LO,
|
||||
parameter ICACHE_BANK_BITS,
|
||||
parameter DCCM_BITS,
|
||||
parameter ICACHE_BEAT_ADDR_HI,
|
||||
parameter ICCM_INDEX_BITS,
|
||||
parameter ICCM_BANK_HI,
|
||||
parameter ICACHE_BANKS_WAY,
|
||||
parameter ICACHE_INDEX_HI,
|
||||
parameter DCCM_NUM_BANKS,
|
||||
parameter ICACHE_BANK_HI,
|
||||
parameter ICACHE_BANK_LO,
|
||||
parameter DCCM_ENABLE= 'b1,
|
||||
parameter ICACHE_TAG_LO,
|
||||
parameter ICACHE_DATA_INDEX_LO,
|
||||
parameter ICCM_NUM_BANKS,
|
||||
parameter ICACHE_ECC,
|
||||
parameter ICACHE_ENABLE= 'b1,
|
||||
parameter DCCM_BANK_BITS,
|
||||
parameter ICCM_ENABLE= 'b1,
|
||||
parameter ICCM_BANK_BITS,
|
||||
parameter ICACHE_TAG_DEPTH,
|
||||
parameter ICACHE_WAYPACK,
|
||||
parameter DCCM_SIZE,
|
||||
parameter DCCM_FDATA_WIDTH,
|
||||
parameter ICACHE_TAG_INDEX_LO,
|
||||
parameter ICACHE_DATA_DEPTH,
|
||||
parameter DCCM_WIDTH_BITS,
|
||||
parameter ICACHE_NUM_BYPASS,
|
||||
parameter ICACHE_TAG_NUM_BYPASS,
|
||||
parameter ICACHE_TAG_NUM_BYPASS_WIDTH,
|
||||
parameter ICACHE_TAG_BYPASS_ENABLE,
|
||||
parameter ICACHE_NUM_BYPASS_WIDTH,
|
||||
parameter ICACHE_BYPASS_ENABLE,
|
||||
parameter ICACHE_LN_SZ
|
||||
)
|
||||
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst_l,
|
||||
input logic dccm_clk_override,
|
||||
input logic icm_clk_override,
|
||||
input logic dec_tlu_core_ecc_disable,
|
||||
|
||||
//DCCM ports
|
||||
input logic dccm_wren,
|
||||
input logic dccm_rden,
|
||||
input logic [DCCM_BITS-1:0] dccm_wr_addr_lo,
|
||||
input logic [DCCM_BITS-1:0] dccm_wr_addr_hi,
|
||||
input logic [DCCM_BITS-1:0] dccm_rd_addr_lo,
|
||||
input logic [DCCM_BITS-1:0] dccm_rd_addr_hi,
|
||||
input logic [DCCM_FDATA_WIDTH-1:0] dccm_wr_data_lo,
|
||||
input logic [DCCM_FDATA_WIDTH-1:0] dccm_wr_data_hi,
|
||||
|
||||
|
||||
output logic [DCCM_FDATA_WIDTH-1:0] dccm_rd_data_lo,
|
||||
output logic [DCCM_FDATA_WIDTH-1:0] dccm_rd_data_hi,
|
||||
|
||||
//`ifdef DCCM_ENABLE
|
||||
//input dccm_ext_in_pkt_t [DCCM_NUM_BANKS-1:0] dccm_ext_in_pkt,
|
||||
input logic dccm_ext_in_pkt_TEST1_0,
|
||||
input logic dccm_ext_in_pkt_RME_0,
|
||||
input logic [3:0] dccm_ext_in_pkt_RM_0,
|
||||
input logic dccm_ext_in_pkt_LS_0,
|
||||
input logic dccm_ext_in_pkt_DS_0,
|
||||
input logic dccm_ext_in_pkt_SD_0,
|
||||
input logic dccm_ext_in_pkt_TEST_RNM_0,
|
||||
input logic dccm_ext_in_pkt_BC1_0,
|
||||
input logic dccm_ext_in_pkt_BC2_0,
|
||||
|
||||
input logic dccm_ext_in_pkt_TEST1_1,
|
||||
input logic dccm_ext_in_pkt_RME_1,
|
||||
input logic [3:0] dccm_ext_in_pkt_RM_1,
|
||||
input logic dccm_ext_in_pkt_LS_1,
|
||||
input logic dccm_ext_in_pkt_DS_1,
|
||||
input logic dccm_ext_in_pkt_SD_1,
|
||||
input logic dccm_ext_in_pkt_TEST_RNM_1,
|
||||
input logic dccm_ext_in_pkt_BC1_1,
|
||||
input logic dccm_ext_in_pkt_BC2_1,
|
||||
|
||||
input logic dccm_ext_in_pkt_TEST1_2,
|
||||
input logic dccm_ext_in_pkt_RME_2,
|
||||
input logic [3:0] dccm_ext_in_pkt_RM_2,
|
||||
input logic dccm_ext_in_pkt_LS_2,
|
||||
input logic dccm_ext_in_pkt_DS_2,
|
||||
input logic dccm_ext_in_pkt_SD_2,
|
||||
input logic dccm_ext_in_pkt_TEST_RNM_2,
|
||||
input logic dccm_ext_in_pkt_BC1_2,
|
||||
input logic dccm_ext_in_pkt_BC2_2,
|
||||
|
||||
input logic dccm_ext_in_pkt_TEST1_3,
|
||||
input logic dccm_ext_in_pkt_RME_3,
|
||||
input logic [3:0] dccm_ext_in_pkt_RM_3,
|
||||
input logic dccm_ext_in_pkt_LS_3,
|
||||
input logic dccm_ext_in_pkt_DS_3,
|
||||
input logic dccm_ext_in_pkt_SD_3,
|
||||
input logic dccm_ext_in_pkt_TEST_RNM_3,
|
||||
input logic dccm_ext_in_pkt_BC1_3,
|
||||
input logic dccm_ext_in_pkt_BC2_3,
|
||||
|
||||
//`endif
|
||||
|
||||
//ICCM ports
|
||||
input logic iccm_ext_in_pkt_TEST1_0,
|
||||
input logic iccm_ext_in_pkt_RME_0,
|
||||
input logic [3:0] iccm_ext_in_pkt_RM_0,
|
||||
input logic iccm_ext_in_pkt_LS_0,
|
||||
input logic iccm_ext_in_pkt_DS_0,
|
||||
input logic iccm_ext_in_pkt_SD_0,
|
||||
input logic iccm_ext_in_pkt_TEST_RNM_0,
|
||||
input logic iccm_ext_in_pkt_BC1_0,
|
||||
input logic iccm_ext_in_pkt_BC2_0,
|
||||
|
||||
input logic iccm_ext_in_pkt_TEST1_1,
|
||||
input logic iccm_ext_in_pkt_RME_1,
|
||||
input logic [3:0] iccm_ext_in_pkt_RM_1,
|
||||
input logic iccm_ext_in_pkt_LS_1,
|
||||
input logic iccm_ext_in_pkt_DS_1,
|
||||
input logic iccm_ext_in_pkt_SD_1,
|
||||
input logic iccm_ext_in_pkt_TEST_RNM_1,
|
||||
input logic iccm_ext_in_pkt_BC1_1,
|
||||
input logic iccm_ext_in_pkt_BC2_1,
|
||||
|
||||
input logic iccm_ext_in_pkt_TEST1_2,
|
||||
input logic iccm_ext_in_pkt_RME_2,
|
||||
input logic [3:0] iccm_ext_in_pkt_RM_2,
|
||||
input logic iccm_ext_in_pkt_LS_2,
|
||||
input logic iccm_ext_in_pkt_DS_2,
|
||||
input logic iccm_ext_in_pkt_SD_2,
|
||||
input logic iccm_ext_in_pkt_TEST_RNM_2,
|
||||
input logic iccm_ext_in_pkt_BC1_2,
|
||||
input logic iccm_ext_in_pkt_BC2_2,
|
||||
|
||||
input logic iccm_ext_in_pkt_TEST1_3,
|
||||
input logic iccm_ext_in_pkt_RME_3,
|
||||
input logic [3:0] iccm_ext_in_pkt_RM_3,
|
||||
input logic iccm_ext_in_pkt_LS_3,
|
||||
input logic iccm_ext_in_pkt_DS_3,
|
||||
input logic iccm_ext_in_pkt_SD_3,
|
||||
input logic iccm_ext_in_pkt_TEST_RNM_3,
|
||||
input logic iccm_ext_in_pkt_BC1_3,
|
||||
input logic iccm_ext_in_pkt_BC2_3,
|
||||
|
||||
input logic [ICCM_BITS-1:1] iccm_rw_addr,
|
||||
input logic iccm_buf_correct_ecc, // ICCM is doing a single bit error correct cycle
|
||||
input logic iccm_correction_state, // ICCM is doing a single bit error correct cycle
|
||||
input logic iccm_wren,
|
||||
input logic iccm_rden,
|
||||
input logic [2:0] iccm_wr_size,
|
||||
input logic [77:0] iccm_wr_data,
|
||||
|
||||
output logic [63:0] iccm_rd_data,
|
||||
output logic [77:0] iccm_rd_data_ecc,
|
||||
|
||||
// Icache and Itag Ports
|
||||
|
||||
input logic [31:1] ic_rw_addr,
|
||||
input logic [ICACHE_NUM_WAYS-1:0] ic_tag_valid,
|
||||
input logic [ICACHE_NUM_WAYS-1:0] ic_wr_en,
|
||||
input logic ic_rd_en,
|
||||
input logic [63:0] ic_premux_data, // Premux data to be muxed with each way of the Icache.
|
||||
input logic ic_sel_premux_data, // Premux data sel
|
||||
// input ic_data_ext_in_pkt_t [ICACHE_NUM_WAYS-1:0][ICACHE_BANKS_WAY-1:0] ic_data_ext_in_pkt,
|
||||
input logic ic_tag_ext_in_pkt_TEST1_0,
|
||||
input logic ic_tag_ext_in_pkt_RME_0,
|
||||
input logic [3:0] ic_tag_ext_in_pkt_RM_0,
|
||||
input logic ic_tag_ext_in_pkt_LS_0,
|
||||
input logic ic_tag_ext_in_pkt_DS_0,
|
||||
input logic ic_tag_ext_in_pkt_SD_0,
|
||||
input logic ic_tag_ext_in_pkt_TEST_RNM_0,
|
||||
input logic ic_tag_ext_in_pkt_BC1_0,
|
||||
input logic ic_tag_ext_in_pkt_BC2_0,
|
||||
|
||||
input logic ic_tag_ext_in_pkt_TEST1_1,
|
||||
input logic ic_tag_ext_in_pkt_RME_1,
|
||||
input logic [3:0] ic_tag_ext_in_pkt_RM_1,
|
||||
input logic ic_tag_ext_in_pkt_LS_1,
|
||||
input logic ic_tag_ext_in_pkt_DS_1,
|
||||
input logic ic_tag_ext_in_pkt_SD_1,
|
||||
input logic ic_tag_ext_in_pkt_TEST_RNM_1,
|
||||
input logic ic_tag_ext_in_pkt_BC1_1,
|
||||
input logic ic_tag_ext_in_pkt_BC2_1,
|
||||
|
||||
input logic ic_data_ext_in_pkt_0_TEST1_0,
|
||||
input logic ic_data_ext_in_pkt_0_RME_0,
|
||||
input logic [3:0] ic_data_ext_in_pkt_0_RM_0,
|
||||
input logic ic_data_ext_in_pkt_0_LS_0,
|
||||
input logic ic_data_ext_in_pkt_0_DS_0,
|
||||
input logic ic_data_ext_in_pkt_0_SD_0,
|
||||
input logic ic_data_ext_in_pkt_0_TEST_RNM_0,
|
||||
input logic ic_data_ext_in_pkt_0_BC1_0,
|
||||
input logic ic_data_ext_in_pkt_0_BC2_0,
|
||||
|
||||
input logic ic_data_ext_in_pkt_0_TEST1_1,
|
||||
input logic ic_data_ext_in_pkt_0_RME_1,
|
||||
input logic [3:0] ic_data_ext_in_pkt_0_RM_1,
|
||||
input logic ic_data_ext_in_pkt_0_LS_1,
|
||||
input logic ic_data_ext_in_pkt_0_DS_1,
|
||||
input logic ic_data_ext_in_pkt_0_SD_1,
|
||||
input logic ic_data_ext_in_pkt_0_TEST_RNM_1,
|
||||
input logic ic_data_ext_in_pkt_0_BC1_1,
|
||||
input logic ic_data_ext_in_pkt_0_BC2_1,
|
||||
|
||||
input logic ic_data_ext_in_pkt_1_TEST1_0,
|
||||
input logic ic_data_ext_in_pkt_1_RME_0,
|
||||
input logic [3:0] ic_data_ext_in_pkt_1_RM_0,
|
||||
input logic ic_data_ext_in_pkt_1_LS_0,
|
||||
input logic ic_data_ext_in_pkt_1_DS_0,
|
||||
input logic ic_data_ext_in_pkt_1_SD_0,
|
||||
input logic ic_data_ext_in_pkt_1_TEST_RNM_0,
|
||||
input logic ic_data_ext_in_pkt_1_BC1_0,
|
||||
input logic ic_data_ext_in_pkt_1_BC2_0,
|
||||
|
||||
input logic ic_data_ext_in_pkt_1_TEST1_1,
|
||||
input logic ic_data_ext_in_pkt_1_RME_1,
|
||||
input logic [3:0] ic_data_ext_in_pkt_1_RM_1,
|
||||
input logic ic_data_ext_in_pkt_1_LS_1,
|
||||
input logic ic_data_ext_in_pkt_1_DS_1,
|
||||
input logic ic_data_ext_in_pkt_1_SD_1,
|
||||
input logic ic_data_ext_in_pkt_1_TEST_RNM_1,
|
||||
input logic ic_data_ext_in_pkt_1_BC1_1,
|
||||
input logic ic_data_ext_in_pkt_1_BC2_1,
|
||||
|
||||
// input logic [ICACHE_BANKS_WAY-1:0][70:0] ic_wr_data, // Data to fill to the Icache. With ECC
|
||||
input logic [70:0] ic_wr_data_0, // Data to fill to the Icache. With ECC
|
||||
input logic [70:0] ic_wr_data_1, // Data to fill to the Icache. With ECC
|
||||
input logic [70:0] ic_debug_wr_data, // Debug wr cache.
|
||||
output logic [70:0] ic_debug_rd_data , // Data read from Icache. 2x64bits + parity bits. F2 stage. With ECC
|
||||
input logic [ICACHE_INDEX_HI:3] ic_debug_addr, // Read/Write addresss to the Icache.
|
||||
input logic ic_debug_rd_en, // Icache debug rd
|
||||
input logic ic_debug_wr_en, // Icache debug wr
|
||||
input logic ic_debug_tag_array, // Debug tag array
|
||||
input logic [ICACHE_NUM_WAYS-1:0] ic_debug_way, // Debug way. Rd or Wr.
|
||||
|
||||
output logic [63:0] ic_rd_data , // Data read from Icache. 2x64bits + parity bits. F2 stage. With ECC
|
||||
output logic [25:0] ic_tag_debug_rd_data,// Debug icache tag.
|
||||
|
||||
|
||||
output logic [ICACHE_BANKS_WAY-1:0] ic_eccerr, // ecc error per bank
|
||||
output logic [ICACHE_BANKS_WAY-1:0] ic_parerr, // parity error per bank
|
||||
output logic [ICACHE_NUM_WAYS-1:0] ic_rd_hit,
|
||||
output logic ic_tag_perr, // Icache Tag parity error
|
||||
|
||||
|
||||
input logic scan_mode
|
||||
|
||||
);
|
||||
|
||||
iccm_ext_in_pkt_t [ICCM_NUM_BANKS-1:0] iccm_ext_in_pkt;
|
||||
dccm_ext_in_pkt_t [DCCM_NUM_BANKS-1:0] dccm_ext_in_pkt;
|
||||
ic_data_ext_in_pkt_t [ICACHE_NUM_WAYS-1:0][ICACHE_BANKS_WAY-1:0] ic_data_ext_in_pkt;
|
||||
ic_tag_ext_in_pkt_t [ICACHE_NUM_WAYS-1:0] ic_tag_ext_in_pkt;
|
||||
|
||||
|
||||
assign dccm_ext_in_pkt[0].TEST1 = dccm_ext_in_pkt_TEST1_0;
|
||||
assign dccm_ext_in_pkt[0].RME = dccm_ext_in_pkt_RME_0;
|
||||
assign dccm_ext_in_pkt[0].RM = dccm_ext_in_pkt_RM_0[3:0];
|
||||
assign dccm_ext_in_pkt[0].LS = dccm_ext_in_pkt_LS_0;
|
||||
assign dccm_ext_in_pkt[0].DS = dccm_ext_in_pkt_DS_0;
|
||||
assign dccm_ext_in_pkt[0].SD = dccm_ext_in_pkt_SD_0;
|
||||
assign dccm_ext_in_pkt[0].TEST_RNM = dccm_ext_in_pkt_TEST_RNM_0;
|
||||
assign dccm_ext_in_pkt[0].BC1 = dccm_ext_in_pkt_BC1_0;
|
||||
assign dccm_ext_in_pkt[0].BC2 = dccm_ext_in_pkt_BC2_0;
|
||||
|
||||
assign dccm_ext_in_pkt[1].TEST1 = dccm_ext_in_pkt_TEST1_1;
|
||||
assign dccm_ext_in_pkt[1].RME = dccm_ext_in_pkt_RME_1;
|
||||
assign dccm_ext_in_pkt[1].RM = dccm_ext_in_pkt_RM_1[3:0];
|
||||
assign dccm_ext_in_pkt[1].LS = dccm_ext_in_pkt_LS_1;
|
||||
assign dccm_ext_in_pkt[1].DS = dccm_ext_in_pkt_DS_1;
|
||||
assign dccm_ext_in_pkt[1].SD = dccm_ext_in_pkt_SD_1;
|
||||
assign dccm_ext_in_pkt[1].TEST_RNM = dccm_ext_in_pkt_TEST_RNM_1;
|
||||
assign dccm_ext_in_pkt[1].BC1 = dccm_ext_in_pkt_BC1_1;
|
||||
assign dccm_ext_in_pkt[1].BC2 = dccm_ext_in_pkt_BC2_1;
|
||||
|
||||
|
||||
assign dccm_ext_in_pkt[2].TEST1 = dccm_ext_in_pkt_TEST1_2;
|
||||
assign dccm_ext_in_pkt[2].RME = dccm_ext_in_pkt_RME_2;
|
||||
assign dccm_ext_in_pkt[2].RM = dccm_ext_in_pkt_RM_2[3:0];
|
||||
assign dccm_ext_in_pkt[2].LS = dccm_ext_in_pkt_LS_2;
|
||||
assign dccm_ext_in_pkt[2].DS = dccm_ext_in_pkt_DS_2;
|
||||
assign dccm_ext_in_pkt[2].SD = dccm_ext_in_pkt_SD_2;
|
||||
assign dccm_ext_in_pkt[2].TEST_RNM = dccm_ext_in_pkt_TEST_RNM_2;
|
||||
assign dccm_ext_in_pkt[2].BC1 = dccm_ext_in_pkt_BC1_2;
|
||||
assign dccm_ext_in_pkt[2].BC2 = dccm_ext_in_pkt_BC2_2;
|
||||
|
||||
assign dccm_ext_in_pkt[3].TEST1 = dccm_ext_in_pkt_TEST1_3;
|
||||
assign dccm_ext_in_pkt[3].RME = dccm_ext_in_pkt_RME_3;
|
||||
assign dccm_ext_in_pkt[3].RM = dccm_ext_in_pkt_RM_3[3:0];
|
||||
assign dccm_ext_in_pkt[3].LS = dccm_ext_in_pkt_LS_3;
|
||||
assign dccm_ext_in_pkt[3].DS = dccm_ext_in_pkt_DS_3;
|
||||
assign dccm_ext_in_pkt[3].SD = dccm_ext_in_pkt_SD_3;
|
||||
assign dccm_ext_in_pkt[3].TEST_RNM = dccm_ext_in_pkt_TEST_RNM_3;
|
||||
assign dccm_ext_in_pkt[3].BC1 = dccm_ext_in_pkt_BC1_3;
|
||||
assign dccm_ext_in_pkt[3].BC2 = dccm_ext_in_pkt_BC2_3;
|
||||
|
||||
assign iccm_ext_in_pkt[0].TEST1 = iccm_ext_in_pkt_TEST1_0;
|
||||
assign iccm_ext_in_pkt[0].RME = iccm_ext_in_pkt_RME_0;
|
||||
assign iccm_ext_in_pkt[0].RM = iccm_ext_in_pkt_RM_0[3:0];
|
||||
assign iccm_ext_in_pkt[0].LS = iccm_ext_in_pkt_LS_0;
|
||||
assign iccm_ext_in_pkt[0].DS = iccm_ext_in_pkt_DS_0;
|
||||
assign iccm_ext_in_pkt[0].SD = iccm_ext_in_pkt_SD_0;
|
||||
assign iccm_ext_in_pkt[0].TEST_RNM = iccm_ext_in_pkt_TEST_RNM_0;
|
||||
assign iccm_ext_in_pkt[0].BC1 = iccm_ext_in_pkt_BC1_0;
|
||||
assign iccm_ext_in_pkt[0].BC2 = iccm_ext_in_pkt_BC2_0;
|
||||
|
||||
assign iccm_ext_in_pkt[1].TEST1 = iccm_ext_in_pkt_TEST1_1;
|
||||
assign iccm_ext_in_pkt[1].RME = iccm_ext_in_pkt_RME_1;
|
||||
assign iccm_ext_in_pkt[1].RM = iccm_ext_in_pkt_RM_1[3:0];
|
||||
assign iccm_ext_in_pkt[1].LS = iccm_ext_in_pkt_LS_1;
|
||||
assign iccm_ext_in_pkt[1].DS = iccm_ext_in_pkt_DS_1;
|
||||
assign iccm_ext_in_pkt[1].SD = iccm_ext_in_pkt_SD_1;
|
||||
assign iccm_ext_in_pkt[1].TEST_RNM = iccm_ext_in_pkt_TEST_RNM_1;
|
||||
assign iccm_ext_in_pkt[1].BC1 = iccm_ext_in_pkt_BC1_1;
|
||||
assign iccm_ext_in_pkt[1].BC2 = iccm_ext_in_pkt_BC2_1;
|
||||
|
||||
|
||||
assign iccm_ext_in_pkt[2].TEST1 = iccm_ext_in_pkt_TEST1_2;
|
||||
assign iccm_ext_in_pkt[2].RME = iccm_ext_in_pkt_RME_2;
|
||||
assign iccm_ext_in_pkt[2].RM = iccm_ext_in_pkt_RM_2[3:0];
|
||||
assign iccm_ext_in_pkt[2].LS = iccm_ext_in_pkt_LS_2;
|
||||
assign iccm_ext_in_pkt[2].DS = iccm_ext_in_pkt_DS_2;
|
||||
assign iccm_ext_in_pkt[2].SD = iccm_ext_in_pkt_SD_2;
|
||||
assign iccm_ext_in_pkt[2].TEST_RNM = iccm_ext_in_pkt_TEST_RNM_2;
|
||||
assign iccm_ext_in_pkt[2].BC1 = iccm_ext_in_pkt_BC1_2;
|
||||
assign iccm_ext_in_pkt[2].BC2 = iccm_ext_in_pkt_BC2_2;
|
||||
|
||||
assign iccm_ext_in_pkt[3].TEST1 = iccm_ext_in_pkt_TEST1_3;
|
||||
assign iccm_ext_in_pkt[3].RME = iccm_ext_in_pkt_RME_3;
|
||||
assign iccm_ext_in_pkt[3].RM = iccm_ext_in_pkt_RM_3[3:0];
|
||||
assign iccm_ext_in_pkt[3].LS = iccm_ext_in_pkt_LS_3;
|
||||
assign iccm_ext_in_pkt[3].DS = iccm_ext_in_pkt_DS_3;
|
||||
assign iccm_ext_in_pkt[3].SD = iccm_ext_in_pkt_SD_3;
|
||||
assign iccm_ext_in_pkt[3].TEST_RNM = iccm_ext_in_pkt_TEST_RNM_3;
|
||||
assign iccm_ext_in_pkt[3].BC1 = iccm_ext_in_pkt_BC1_3;
|
||||
assign iccm_ext_in_pkt[3].BC2 = iccm_ext_in_pkt_BC2_3;
|
||||
|
||||
|
||||
assign ic_tag_ext_in_pkt[0].TEST1 = ic_tag_ext_in_pkt_TEST1_0;
|
||||
assign ic_tag_ext_in_pkt[0].RME = ic_tag_ext_in_pkt_RME_0;
|
||||
assign ic_tag_ext_in_pkt[0].RM = ic_tag_ext_in_pkt_RM_0[3:0];
|
||||
assign ic_tag_ext_in_pkt[0].LS = ic_tag_ext_in_pkt_LS_0;
|
||||
assign ic_tag_ext_in_pkt[0].DS = ic_tag_ext_in_pkt_DS_0;
|
||||
assign ic_tag_ext_in_pkt[0].SD = ic_tag_ext_in_pkt_SD_0;
|
||||
assign ic_tag_ext_in_pkt[0].TEST_RNM = ic_tag_ext_in_pkt_TEST_RNM_0;
|
||||
assign ic_tag_ext_in_pkt[0].BC1 = ic_tag_ext_in_pkt_BC1_0;
|
||||
assign ic_tag_ext_in_pkt[0].BC2 = ic_tag_ext_in_pkt_BC2_0;
|
||||
|
||||
assign ic_tag_ext_in_pkt[1].TEST1 = ic_tag_ext_in_pkt_TEST1_1;
|
||||
assign ic_tag_ext_in_pkt[1].RME = ic_tag_ext_in_pkt_RME_1;
|
||||
assign ic_tag_ext_in_pkt[1].RM = ic_tag_ext_in_pkt_RM_1[3:0];
|
||||
assign ic_tag_ext_in_pkt[1].LS = ic_tag_ext_in_pkt_LS_1;
|
||||
assign ic_tag_ext_in_pkt[1].DS = ic_tag_ext_in_pkt_DS_1;
|
||||
assign ic_tag_ext_in_pkt[1].SD = ic_tag_ext_in_pkt_SD_1;
|
||||
assign ic_tag_ext_in_pkt[1].TEST_RNM = ic_tag_ext_in_pkt_TEST_RNM_1;
|
||||
assign ic_tag_ext_in_pkt[1].BC1 = ic_tag_ext_in_pkt_BC1_1;
|
||||
assign ic_tag_ext_in_pkt[1].BC2 = ic_tag_ext_in_pkt_BC2_1;
|
||||
|
||||
// PKT connection
|
||||
assign ic_data_ext_in_pkt[0][0].TEST1 = ic_data_ext_in_pkt_0_TEST1_0;
|
||||
assign ic_data_ext_in_pkt[0][0].RME = ic_data_ext_in_pkt_0_RME_0;
|
||||
assign ic_data_ext_in_pkt[0][0].RM = ic_data_ext_in_pkt_0_RM_0[3:0];
|
||||
assign ic_data_ext_in_pkt[0][0].LS = ic_data_ext_in_pkt_0_LS_0;
|
||||
assign ic_data_ext_in_pkt[0][0].DS = ic_data_ext_in_pkt_0_DS_0;
|
||||
assign ic_data_ext_in_pkt[0][0].SD = ic_data_ext_in_pkt_0_SD_0;
|
||||
assign ic_data_ext_in_pkt[0][0].TEST_RNM = ic_data_ext_in_pkt_0_TEST_RNM_0;
|
||||
assign ic_data_ext_in_pkt[0][0].BC1 = ic_data_ext_in_pkt_0_BC1_0;
|
||||
assign ic_data_ext_in_pkt[0][0].BC2 = ic_data_ext_in_pkt_0_BC2_0;
|
||||
|
||||
assign ic_data_ext_in_pkt[0][1].TEST1 = ic_data_ext_in_pkt_1_TEST1_1;
|
||||
assign ic_data_ext_in_pkt[0][1].RME = ic_data_ext_in_pkt_1_RME_1;
|
||||
assign ic_data_ext_in_pkt[0][1].RM = ic_data_ext_in_pkt_1_RM_1[3:0];
|
||||
assign ic_data_ext_in_pkt[0][1].LS = ic_data_ext_in_pkt_1_LS_1;
|
||||
assign ic_data_ext_in_pkt[0][1].DS = ic_data_ext_in_pkt_1_DS_1;
|
||||
assign ic_data_ext_in_pkt[0][1].SD = ic_data_ext_in_pkt_1_SD_1;
|
||||
assign ic_data_ext_in_pkt[0][1].TEST_RNM = ic_data_ext_in_pkt_1_TEST_RNM_1;
|
||||
assign ic_data_ext_in_pkt[0][1].BC1 = ic_data_ext_in_pkt_1_BC1_1;
|
||||
assign ic_data_ext_in_pkt[0][1].BC2 = ic_data_ext_in_pkt_1_BC2_1;
|
||||
|
||||
assign ic_data_ext_in_pkt[1][0].TEST1 = ic_data_ext_in_pkt_1_TEST1_0;
|
||||
assign ic_data_ext_in_pkt[1][0].RME = ic_data_ext_in_pkt_1_RME_0;
|
||||
assign ic_data_ext_in_pkt[1][0].RM = ic_data_ext_in_pkt_1_RM_0[3:0];
|
||||
assign ic_data_ext_in_pkt[1][0].LS = ic_data_ext_in_pkt_1_LS_0;
|
||||
assign ic_data_ext_in_pkt[1][0].DS = ic_data_ext_in_pkt_1_DS_0;
|
||||
assign ic_data_ext_in_pkt[1][0].SD = ic_data_ext_in_pkt_1_SD_0;
|
||||
assign ic_data_ext_in_pkt[1][0].TEST_RNM = ic_data_ext_in_pkt_1_TEST_RNM_0;
|
||||
assign ic_data_ext_in_pkt[1][0].BC1 = ic_data_ext_in_pkt_1_BC1_0;
|
||||
assign ic_data_ext_in_pkt[1][0].BC2 = ic_data_ext_in_pkt_1_BC2_0;
|
||||
|
||||
assign ic_data_ext_in_pkt[1][1].TEST1 = ic_data_ext_in_pkt_1_TEST1_1;
|
||||
assign ic_data_ext_in_pkt[1][1].RME = ic_data_ext_in_pkt_1_RME_1;
|
||||
assign ic_data_ext_in_pkt[1][1].RM = ic_data_ext_in_pkt_1_RM_1[3:0];
|
||||
assign ic_data_ext_in_pkt[1][1].LS = ic_data_ext_in_pkt_1_LS_1;
|
||||
assign ic_data_ext_in_pkt[1][1].DS = ic_data_ext_in_pkt_1_DS_1;
|
||||
assign ic_data_ext_in_pkt[1][1].SD = ic_data_ext_in_pkt_1_SD_1;
|
||||
assign ic_data_ext_in_pkt[1][1].TEST_RNM = ic_data_ext_in_pkt_1_TEST_RNM_1;
|
||||
assign ic_data_ext_in_pkt[1][1].BC1 = ic_data_ext_in_pkt_1_BC1_1;
|
||||
assign ic_data_ext_in_pkt[1][1].BC2 = ic_data_ext_in_pkt_1_BC2_1;
|
||||
|
||||
wire active_clk;
|
||||
|
||||
rvoclkhdr active_cg ( .en(1'b1), .l1clk(active_clk), .* );
|
||||
|
||||
// DCCM Instantiation
|
||||
if (DCCM_ENABLE == 1) begin: Gen_dccm_enable
|
||||
lsu_dccm_mem #(
|
||||
.DCCM_BYTE_WIDTH(DCCM_BYTE_WIDTH),
|
||||
.DCCM_BITS(DCCM_BITS),
|
||||
.DCCM_NUM_BANKS(DCCM_NUM_BANKS),
|
||||
.DCCM_BANK_BITS(DCCM_BANK_BITS),
|
||||
.DCCM_SIZE(DCCM_SIZE),
|
||||
.DCCM_FDATA_WIDTH(DCCM_FDATA_WIDTH),
|
||||
.DCCM_WIDTH_BITS(DCCM_WIDTH_BITS)) dccm (
|
||||
.clk_override(dccm_clk_override),
|
||||
.*
|
||||
);
|
||||
end else begin: Gen_dccm_disable
|
||||
assign dccm_rd_data_lo = '0;
|
||||
assign dccm_rd_data_hi = '0;
|
||||
end
|
||||
|
||||
if ( ICACHE_ENABLE ) begin: icache
|
||||
ifu_ic_mem #(
|
||||
.ICACHE_BEAT_BITS(ICACHE_BEAT_BITS),
|
||||
.ICACHE_NUM_WAYS(ICACHE_NUM_WAYS),
|
||||
.ICACHE_BANK_BITS(ICACHE_BANK_BITS),
|
||||
.ICACHE_BEAT_ADDR_HI(ICACHE_BEAT_ADDR_HI),
|
||||
.ICACHE_BANKS_WAY(ICACHE_BANKS_WAY),
|
||||
.ICACHE_INDEX_HI(ICACHE_INDEX_HI),
|
||||
.ICACHE_BANK_HI(ICACHE_BANK_HI),
|
||||
.ICACHE_BANK_LO(ICACHE_BANK_LO),
|
||||
.ICACHE_TAG_LO(ICACHE_TAG_LO),
|
||||
.ICACHE_DATA_INDEX_LO(ICACHE_DATA_INDEX_LO),
|
||||
.ICACHE_ECC(ICACHE_ECC),
|
||||
.ICACHE_TAG_DEPTH(ICACHE_TAG_DEPTH),
|
||||
.ICACHE_WAYPACK(ICACHE_WAYPACK),
|
||||
.ICACHE_TAG_INDEX_LO(ICACHE_TAG_INDEX_LO),
|
||||
.ICACHE_DATA_DEPTH(ICACHE_DATA_DEPTH),
|
||||
.ICACHE_TAG_NUM_BYPASS(ICACHE_TAG_NUM_BYPASS),
|
||||
.ICACHE_TAG_NUM_BYPASS_WIDTH(ICACHE_TAG_NUM_BYPASS_WIDTH),
|
||||
.ICACHE_TAG_BYPASS_ENABLE(ICACHE_TAG_BYPASS_ENABLE),
|
||||
.ICACHE_NUM_BYPASS_WIDTH(ICACHE_NUM_BYPASS_WIDTH),
|
||||
.ICACHE_BYPASS_ENABLE(ICACHE_BYPASS_ENABLE),
|
||||
.ICACHE_NUM_BYPASS(ICACHE_NUM_BYPASS),
|
||||
.ICACHE_LN_SZ(ICACHE_LN_SZ)) icm (
|
||||
.clk_override(icm_clk_override),
|
||||
.*
|
||||
);
|
||||
end
|
||||
else begin
|
||||
assign ic_rd_hit[ICACHE_NUM_WAYS-1:0] = '0;
|
||||
assign ic_tag_perr = '0 ;
|
||||
assign ic_rd_data = '0 ;
|
||||
assign ic_tag_debug_rd_data = '0 ;
|
||||
end // else: !if( ICACHE_ENABLE )
|
||||
|
||||
|
||||
|
||||
if (ICCM_ENABLE) begin : iccm
|
||||
ifu_iccm_mem #(
|
||||
.ICCM_BITS(ICCM_BITS),
|
||||
.ICCM_BANK_INDEX_LO(ICCM_BANK_INDEX_LO),
|
||||
.ICCM_INDEX_BITS(ICCM_INDEX_BITS),
|
||||
.ICCM_BANK_HI(ICCM_BANK_HI),
|
||||
.ICCM_NUM_BANKS(ICCM_NUM_BANKS),
|
||||
.ICCM_BANK_BITS(ICCM_BANK_BITS)) iccm (.*,
|
||||
.clk_override(icm_clk_override),
|
||||
.iccm_rw_addr(iccm_rw_addr[ICCM_BITS-1:1]),
|
||||
.iccm_rd_data(iccm_rd_data[63:0])
|
||||
);
|
||||
end
|
||||
else begin
|
||||
assign iccm_rd_data = '0 ;
|
||||
assign iccm_rd_data_ecc = '0 ;
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,243 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2020 Western Digital Corporation or it's affiliates.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
`define EL2_LOCAL_RAM_TEST_IO \
|
||||
input logic WE, \
|
||||
input logic ME, \
|
||||
input logic CLK, \
|
||||
input logic TEST1, \
|
||||
input logic RME, \
|
||||
input logic [3:0] RM, \
|
||||
input logic LS, \
|
||||
input logic DS, \
|
||||
input logic SD, \
|
||||
input logic TEST_RNM, \
|
||||
input logic BC1, \
|
||||
input logic BC2, \
|
||||
output logic ROP
|
||||
|
||||
`define EL2_RAM(depth, width) \
|
||||
module ram_``depth``x``width( \
|
||||
input logic [$clog2(depth)-1:0] ADR, \
|
||||
input logic [(width-1):0] D, \
|
||||
output logic [(width-1):0] Q, \
|
||||
`EL2_LOCAL_RAM_TEST_IO \
|
||||
); \
|
||||
reg [(width-1):0] ram_core [(depth-1):0]; \
|
||||
`ifdef GTLSIM \
|
||||
integer i; \
|
||||
initial begin \
|
||||
for (i=0; i<depth; i=i+1) \
|
||||
ram_core[i] = '0; \
|
||||
end \
|
||||
`endif \
|
||||
always @(posedge CLK) begin \
|
||||
`ifdef GTLSIM \
|
||||
if (ME && WE) ram_core[ADR] <= D; \
|
||||
`else \
|
||||
if (ME && WE) begin ram_core[ADR] <= D; Q <= 'x; end \
|
||||
`endif \
|
||||
if (ME && ~WE) Q <= ram_core[ADR]; \
|
||||
end \
|
||||
assign ROP = ME; \
|
||||
\
|
||||
endmodule
|
||||
|
||||
`define EL2_RAM_BE(depth, width) \
|
||||
module ram_be_``depth``x``width( \
|
||||
input logic [$clog2(depth)-1:0] ADR, \
|
||||
input logic [(width-1):0] D, WEM, \
|
||||
output logic [(width-1):0] Q, \
|
||||
`EL2_LOCAL_RAM_TEST_IO \
|
||||
); \
|
||||
reg [(width-1):0] ram_core [(depth-1):0]; \
|
||||
`ifdef GTLSIM \
|
||||
integer i; \
|
||||
initial begin \
|
||||
for (i=0; i<depth; i=i+1) \
|
||||
ram_core[i] = '0; \
|
||||
end \
|
||||
`endif \
|
||||
always @(posedge CLK) begin \
|
||||
`ifdef GTLSIM \
|
||||
if (ME && WE) ram_core[ADR] <= D & WEM | ~WEM & ram_core[ADR]; \
|
||||
`else \
|
||||
if (ME && WE) begin ram_core[ADR] <= D & WEM | ~WEM & ram_core[ADR]; Q <= 'x; end \
|
||||
`endif \
|
||||
if (ME && ~WE) Q <= ram_core[ADR]; \
|
||||
end \
|
||||
assign ROP = ME; \
|
||||
\
|
||||
endmodule
|
||||
|
||||
// parameterizable RAM for verilator sims
|
||||
module el2_ram #(depth=4096, width=39) (
|
||||
input logic [$clog2(depth)-1:0] ADR,
|
||||
input logic [(width-1):0] D,
|
||||
output logic [(width-1):0] Q,
|
||||
`EL2_LOCAL_RAM_TEST_IO
|
||||
);
|
||||
reg [(width-1):0] ram_core [(depth-1):0];
|
||||
|
||||
always @(posedge CLK) begin
|
||||
`ifdef GTLSIM
|
||||
if (ME && WE) ram_core[ADR] <= D;
|
||||
`else
|
||||
if (ME && WE) begin ram_core[ADR] <= D; Q <= 'x; end
|
||||
`endif
|
||||
if (ME && ~WE) Q <= ram_core[ADR];
|
||||
end
|
||||
endmodule
|
||||
|
||||
//=========================================================================================================================
|
||||
//=================================== START OF CCM =======================================================================
|
||||
//============= Possible sram sizes for a 39 bit wide memory ( 4 bytes + 7 bits ECC ) =====================================
|
||||
//-------------------------------------------------------------------------------------------------------------------------
|
||||
`EL2_RAM(32768, 39)
|
||||
`EL2_RAM(16384, 39)
|
||||
`EL2_RAM(8192, 39)
|
||||
`EL2_RAM(4096, 39)
|
||||
`EL2_RAM(3072, 39)
|
||||
`EL2_RAM(2048, 39)
|
||||
`EL2_RAM(1536, 39) // need this for the 48KB DCCM option)
|
||||
`EL2_RAM(1024, 39)
|
||||
`EL2_RAM(768, 39)
|
||||
`EL2_RAM(512, 39)
|
||||
`EL2_RAM(256, 39)
|
||||
`EL2_RAM(128, 39)
|
||||
`EL2_RAM(1024, 20)
|
||||
`EL2_RAM(512, 20)
|
||||
`EL2_RAM(256, 20)
|
||||
`EL2_RAM(128, 20)
|
||||
`EL2_RAM(64, 20)
|
||||
`EL2_RAM(4096, 34)
|
||||
`EL2_RAM(2048, 34)
|
||||
`EL2_RAM(1024, 34)
|
||||
`EL2_RAM(512, 34)
|
||||
`EL2_RAM(256, 34)
|
||||
`EL2_RAM(128, 34)
|
||||
`EL2_RAM(64, 34)
|
||||
`EL2_RAM(8192, 68)
|
||||
`EL2_RAM(4096, 68)
|
||||
`EL2_RAM(2048, 68)
|
||||
`EL2_RAM(1024, 68)
|
||||
`EL2_RAM(512, 68)
|
||||
`EL2_RAM(256, 68)
|
||||
`EL2_RAM(128, 68)
|
||||
`EL2_RAM(64, 68)
|
||||
`EL2_RAM(8192, 71)
|
||||
`EL2_RAM(4096, 71)
|
||||
`EL2_RAM(2048, 71)
|
||||
`EL2_RAM(1024, 71)
|
||||
`EL2_RAM(512, 71)
|
||||
`EL2_RAM(256, 71)
|
||||
`EL2_RAM(128, 71)
|
||||
`EL2_RAM(64, 71)
|
||||
`EL2_RAM(4096, 42)
|
||||
`EL2_RAM(2048, 42)
|
||||
`EL2_RAM(1024, 42)
|
||||
`EL2_RAM(512, 42)
|
||||
`EL2_RAM(256, 42)
|
||||
`EL2_RAM(128, 42)
|
||||
`EL2_RAM(64, 42)
|
||||
`EL2_RAM(4096, 22)
|
||||
`EL2_RAM(2048, 22)
|
||||
`EL2_RAM(1024, 22)
|
||||
`EL2_RAM(512, 22)
|
||||
`EL2_RAM(256, 22)
|
||||
`EL2_RAM(128, 22)
|
||||
`EL2_RAM(64, 22)
|
||||
`EL2_RAM(1024, 26)
|
||||
`EL2_RAM(4096, 26)
|
||||
`EL2_RAM(2048, 26)
|
||||
`EL2_RAM(512, 26)
|
||||
`EL2_RAM(256, 26)
|
||||
`EL2_RAM(128, 26)
|
||||
`EL2_RAM(64, 26)
|
||||
`EL2_RAM(32, 26)
|
||||
`EL2_RAM(32, 22)
|
||||
`EL2_RAM_BE(8192, 142)
|
||||
`EL2_RAM_BE(4096, 142)
|
||||
`EL2_RAM_BE(2048, 142)
|
||||
`EL2_RAM_BE(1024, 142)
|
||||
`EL2_RAM_BE(512, 142)
|
||||
`EL2_RAM_BE(256, 142)
|
||||
`EL2_RAM_BE(128, 142)
|
||||
`EL2_RAM_BE(64, 142)
|
||||
`EL2_RAM_BE(8192, 284)
|
||||
`EL2_RAM_BE(4096, 284)
|
||||
`EL2_RAM_BE(2048, 284)
|
||||
`EL2_RAM_BE(1024, 284)
|
||||
`EL2_RAM_BE(512, 284)
|
||||
`EL2_RAM_BE(256, 284)
|
||||
`EL2_RAM_BE(128, 284)
|
||||
`EL2_RAM_BE(64, 284)
|
||||
`EL2_RAM_BE(8192, 136)
|
||||
`EL2_RAM_BE(4096, 136)
|
||||
`EL2_RAM_BE(2048, 136)
|
||||
`EL2_RAM_BE(1024, 136)
|
||||
`EL2_RAM_BE(512, 136)
|
||||
`EL2_RAM_BE(256, 136)
|
||||
`EL2_RAM_BE(128, 136)
|
||||
`EL2_RAM_BE(64, 136)
|
||||
`EL2_RAM_BE(8192, 272)
|
||||
`EL2_RAM_BE(4096, 272)
|
||||
`EL2_RAM_BE(2048, 272)
|
||||
`EL2_RAM_BE(1024, 272)
|
||||
`EL2_RAM_BE(512, 272)
|
||||
`EL2_RAM_BE(256, 272)
|
||||
`EL2_RAM_BE(128, 272)
|
||||
`EL2_RAM_BE(64, 272)
|
||||
`EL2_RAM_BE(4096, 52)
|
||||
`EL2_RAM_BE(2048, 52)
|
||||
`EL2_RAM_BE(1024, 52)
|
||||
`EL2_RAM_BE(512, 52)
|
||||
`EL2_RAM_BE(256, 52)
|
||||
`EL2_RAM_BE(128, 52)
|
||||
`EL2_RAM_BE(64, 52)
|
||||
`EL2_RAM_BE(32, 52)
|
||||
`EL2_RAM_BE(4096, 104)
|
||||
`EL2_RAM_BE(2048, 104)
|
||||
`EL2_RAM_BE(1024, 104)
|
||||
`EL2_RAM_BE(512, 104)
|
||||
`EL2_RAM_BE(256, 104)
|
||||
`EL2_RAM_BE(128, 104)
|
||||
`EL2_RAM_BE(64, 104)
|
||||
`EL2_RAM_BE(32, 104)
|
||||
`EL2_RAM_BE(4096, 44)
|
||||
`EL2_RAM_BE(2048, 44)
|
||||
`EL2_RAM_BE(1024, 44)
|
||||
`EL2_RAM_BE(512, 44)
|
||||
`EL2_RAM_BE(256, 44)
|
||||
`EL2_RAM_BE(128, 44)
|
||||
`EL2_RAM_BE(64, 44)
|
||||
`EL2_RAM_BE(32, 44)
|
||||
`EL2_RAM_BE(4096, 88)
|
||||
`EL2_RAM_BE(2048, 88)
|
||||
`EL2_RAM_BE(1024, 88)
|
||||
`EL2_RAM_BE(512, 88)
|
||||
`EL2_RAM_BE(256, 88)
|
||||
`EL2_RAM_BE(128, 88)
|
||||
`EL2_RAM_BE(64, 88)
|
||||
`EL2_RAM_BE(32, 88)
|
||||
`EL2_RAM(64, 39)
|
||||
|
||||
|
||||
`undef EL2_RAM
|
||||
`undef EL2_RAM_BE
|
||||
`undef EL2_LOCAL_RAM_TEST_IO
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
#(parameter AWIDTH = 7,
|
||||
TAG = 1'h1,
|
||||
BHT_ADDR_HI = 4'h9,
|
||||
BHT_ADDR_LO = 2'h2,
|
||||
BHT_ARRAY_DEPTH = 11'h100,
|
||||
BHT_GHR_HASH_1 = 1'h0,
|
||||
BHT_GHR_SIZE = 4'h8,
|
||||
BHT_SIZE = 12'h200,
|
||||
BTB_ADDR_HI = 5'h09,
|
||||
BTB_ADDR_LO = 2'h2,
|
||||
BTB_ARRAY_DEPTH = 9'h100,
|
||||
BTB_BTAG_FOLD = 1'h0,
|
||||
BTB_BTAG_SIZE = 4'h5,
|
||||
BTB_FOLD2_INDEX_HASH = 1'h0,
|
||||
BTB_INDEX1_HI = 5'h09,
|
||||
BTB_INDEX1_LO = 5'h02,
|
||||
BTB_INDEX2_HI = 5'h11,
|
||||
BTB_INDEX2_LO = 5'h0A,
|
||||
BTB_INDEX3_HI = 5'h19,
|
||||
BTB_INDEX3_LO = 5'h12,
|
||||
BTB_SIZE = 10'h200,
|
||||
BUILD_AHB_LITE = 1'h0,
|
||||
BUILD_AXI4 = 1'h1,
|
||||
BUILD_AXI_NATIVE = 1'h1,
|
||||
BUS_PRTY_DEFAULT = 2'h3,
|
||||
DATA_ACCESS_ADDR0 = 32'h00000000,
|
||||
DATA_ACCESS_ADDR1 = 32'h00000000,
|
||||
DATA_ACCESS_ADDR2 = 32'h00000000,
|
||||
DATA_ACCESS_ADDR3 = 32'h00000000,
|
||||
DATA_ACCESS_ADDR4 = 32'h00000000,
|
||||
DATA_ACCESS_ADDR5 = 32'h00000000,
|
||||
DATA_ACCESS_ADDR6 = 32'h00000000,
|
||||
DATA_ACCESS_ADDR7 = 32'h00000000,
|
||||
DATA_ACCESS_ENABLE0 = 1'h0,
|
||||
DATA_ACCESS_ENABLE1 = 1'h0,
|
||||
DATA_ACCESS_ENABLE2 = 1'h0,
|
||||
DATA_ACCESS_ENABLE3 = 1'h0,
|
||||
DATA_ACCESS_ENABLE4 = 1'h0,
|
||||
DATA_ACCESS_ENABLE5 = 1'h0,
|
||||
DATA_ACCESS_ENABLE6 = 1'h0,
|
||||
DATA_ACCESS_ENABLE7 = 1'h0,
|
||||
DATA_ACCESS_MASK0 = 32'h0FFFFFFF,
|
||||
DATA_ACCESS_MASK1 = 32'h0FFFFFFF,
|
||||
DATA_ACCESS_MASK2 = 32'h0FFFFFFF,
|
||||
DATA_ACCESS_MASK3 = 32'h0FFFFFFF,
|
||||
DATA_ACCESS_MASK4 = 32'h0FFFFFFF,
|
||||
DATA_ACCESS_MASK5 = 32'h0FFFFFFF,
|
||||
DATA_ACCESS_MASK6 = 32'h0FFFFFFF,
|
||||
DATA_ACCESS_MASK7 = 32'h0FFFFFFF,
|
||||
DCCM_BANK_BITS = 3'h2,
|
||||
DCCM_BITS = 5'h10,
|
||||
DCCM_BYTE_WIDTH = 3'h4,
|
||||
DCCM_DATA_WIDTH = 6'h20,
|
||||
DCCM_ECC_WIDTH = 3'h7,
|
||||
DCCM_ENABLE = 1'h1,
|
||||
DCCM_FDATA_WIDTH = 6'h27,
|
||||
//DCCM_INDEX_BITS = 4'hC,
|
||||
DCCM_NUM_BANKS = 5'h04,
|
||||
DCCM_REGION = 4'hF,
|
||||
DCCM_SADR = 32'hF0040000,
|
||||
DCCM_SIZE = 10'h040,
|
||||
//DCCM_WIDTH_BITS = 2'h2,
|
||||
DMA_BUF_DEPTH = 3'h5,
|
||||
DMA_BUS_ID = 1'h1,
|
||||
DMA_BUS_PRTY = 2'h2,
|
||||
DMA_BUS_TAG = 4'h1,
|
||||
FAST_INTERRUPT_REDIRECT = 1'h1,
|
||||
ICACHE_2BANKS = 1'h1,
|
||||
ICACHE_BANK_BITS = 3'h1,
|
||||
ICACHE_BANK_HI = 3'h3,
|
||||
ICACHE_BANK_LO = 2'h3,
|
||||
ICACHE_BANK_WIDTH = 4'h8,
|
||||
ICACHE_BANKS_WAY = 3'h2,
|
||||
ICACHE_BEAT_ADDR_HI = 4'h5,
|
||||
ICACHE_BEAT_BITS = 4'h3,
|
||||
ICACHE_DATA_DEPTH = 14'h0200,
|
||||
ICACHE_DATA_INDEX_LO = 3'h4,
|
||||
ICACHE_DATA_WIDTH = 7'h40,
|
||||
ICACHE_ECC = 1'h1,
|
||||
ICACHE_ENABLE = 1'h1,
|
||||
ICACHE_FDATA_WIDTH = 7'h47,
|
||||
ICACHE_INDEX_HI = 5'h0C,
|
||||
ICACHE_LN_SZ = 7'h40,
|
||||
ICACHE_NUM_BEATS = 4'h8,
|
||||
ICACHE_NUM_WAYS = 3'h2,
|
||||
ICACHE_ONLY = 1'h0,
|
||||
ICACHE_SCND_LAST = 4'h6,
|
||||
ICACHE_SIZE = 9'h010,
|
||||
ICACHE_STATUS_BITS = 3'h1,
|
||||
ICACHE_TAG_DEPTH = 13'h0080,
|
||||
ICACHE_TAG_INDEX_LO = 3'h6,
|
||||
ICACHE_TAG_LO = 5'h0D,
|
||||
ICACHE_WAYPACK = 1'h0,
|
||||
ICCM_BANK_BITS = 3'h2,
|
||||
ICCM_BANK_HI = 5'h03,
|
||||
ICCM_BANK_INDEX_LO = 5'h04,
|
||||
ICCM_BITS = 5'h10,
|
||||
ICCM_ENABLE = 1'h1,
|
||||
ICCM_ICACHE = 1'h1,
|
||||
ICCM_INDEX_BITS = 4'hC,
|
||||
ICCM_NUM_BANKS = 5'h04,
|
||||
ICCM_ONLY = 1'h0,
|
||||
ICCM_REGION = 4'hE,
|
||||
ICCM_SADR = 32'hEE000000,
|
||||
ICCM_SIZE = 10'h040,
|
||||
IFU_BUS_ID = 1'h1,
|
||||
IFU_BUS_PRTY = 2'h2,
|
||||
IFU_BUS_TAG = 4'h3,
|
||||
INST_ACCESS_ADDR0 = 32'h00000000,
|
||||
INST_ACCESS_ADDR1 = 32'h00000000,
|
||||
INST_ACCESS_ADDR2 = 32'h00000000,
|
||||
INST_ACCESS_ADDR3 = 32'h00000000,
|
||||
INST_ACCESS_ADDR4 = 32'h00000000,
|
||||
INST_ACCESS_ADDR5 = 32'h00000000,
|
||||
INST_ACCESS_ADDR6 = 32'h00000000,
|
||||
INST_ACCESS_ADDR7 = 32'h00000000,
|
||||
INST_ACCESS_ENABLE0 = 1'h0,
|
||||
INST_ACCESS_ENABLE1 = 1'h0,
|
||||
INST_ACCESS_ENABLE2 = 1'h0,
|
||||
INST_ACCESS_ENABLE3 = 1'h0,
|
||||
INST_ACCESS_ENABLE4 = 1'h0,
|
||||
INST_ACCESS_ENABLE5 = 1'h0,
|
||||
INST_ACCESS_ENABLE6 = 1'h0,
|
||||
INST_ACCESS_ENABLE7 = 1'h0,
|
||||
INST_ACCESS_MASK0 = 32'h0FFFFFFF,
|
||||
INST_ACCESS_MASK1 = 32'h0FFFFFFF,
|
||||
INST_ACCESS_MASK2 = 32'h0FFFFFFF,
|
||||
INST_ACCESS_MASK3 = 32'h0FFFFFFF,
|
||||
INST_ACCESS_MASK4 = 32'h0FFFFFFF,
|
||||
INST_ACCESS_MASK5 = 32'h0FFFFFFF,
|
||||
INST_ACCESS_MASK6 = 32'h0FFFFFFF,
|
||||
INST_ACCESS_MASK7 = 32'h0FFFFFFF,
|
||||
LOAD_TO_USE_PLUS1 = 1'h0,
|
||||
LSU2DMA = 1'h0,
|
||||
LSU_BUS_ID = 1'h1,
|
||||
LSU_BUS_PRTY = 2'h2,
|
||||
LSU_BUS_TAG = 4'h3,
|
||||
LSU_NUM_NBLOAD = 5'h04,
|
||||
LSU_NUM_NBLOAD_WIDTH = 3'h2,
|
||||
LSU_SB_BITS = 5'h10,
|
||||
LSU_STBUF_DEPTH = 4'h4,
|
||||
NO_ICCM_NO_ICACHE = 1'h0,
|
||||
PIC_2CYCLE = 1'h0,
|
||||
PIC_BASE_ADDR = 32'hF00C0000,
|
||||
PIC_BITS = 5'h0F,
|
||||
PIC_INT_WORDS = 4'h1,
|
||||
PIC_REGION = 4'hF,
|
||||
PIC_SIZE = 9'h020,
|
||||
PIC_TOTAL_INT = 8'h1F,
|
||||
PIC_TOTAL_INT_PLUS1 = 9'h020,
|
||||
RET_STACK_SIZE = 4'h8,
|
||||
SB_BUS_ID = 1'h1,
|
||||
SB_BUS_PRTY = 2'h2,
|
||||
SB_BUS_TAG = 4'h1,
|
||||
TIMER_LEGAL_EN = 1'h1,
|
||||
RV_FPGA_OPTIMIZE = 5'h01,
|
||||
DIV_NEW = 5'h01,
|
||||
DIV_BIT = 7'h04,
|
||||
BTB_ENABLE = 5'h01,
|
||||
BTB_TOFFSET_SIZE = 9'h00C,
|
||||
BTB_FULLYA = 5'h00,
|
||||
BITMANIP_ZBA = 5'h00 ,
|
||||
BITMANIP_ZBB = 5'h01 ,
|
||||
BITMANIP_ZBC = 5'h00 ,
|
||||
BITMANIP_ZBE = 5'h00 ,
|
||||
BITMANIP_ZBF = 5'h00 ,
|
||||
BITMANIP_ZBP = 5'h00 ,
|
||||
BITMANIP_ZBR = 5'h00 ,
|
||||
BITMANIP_ZBS = 5'h01 ,
|
||||
ICACHE_BYPASS_ENABLE = 5'h01,
|
||||
ICACHE_NUM_BYPASS = 8'h02,
|
||||
ICACHE_NUM_BYPASS_WIDTH = 8'h02,
|
||||
ICACHE_TAG_BYPASS_ENABLE = 5'h01,
|
||||
ICACHE_TAG_NUM_BYPASS = 8'h02,
|
||||
ICACHE_TAG_NUM_BYPASS_WIDTH = 8'h02
|
||||
|
||||
|
||||
)
|
|
@ -0,0 +1,223 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright 2019 Western Digital Corporation or it's affiliates.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License
|
||||
|
||||
module rvjtag_tap #(
|
||||
parameter AWIDTH = 7
|
||||
)
|
||||
(
|
||||
input trst,
|
||||
input tck,
|
||||
input tms,
|
||||
input tdi,
|
||||
output reg tdo,
|
||||
output tdoEnable,
|
||||
|
||||
output [31:0] wr_data,
|
||||
output [AWIDTH-1:0] wr_addr,
|
||||
output wr_en,
|
||||
output rd_en,
|
||||
|
||||
input [31:0] rd_data,
|
||||
input [1:0] rd_status,
|
||||
|
||||
output reg dmi_reset,
|
||||
output reg dmi_hard_reset,
|
||||
|
||||
input [2:0] idle,
|
||||
input [1:0] dmi_stat,
|
||||
/*
|
||||
-- revisionCode : 4'h0;
|
||||
-- manufacturersIdCode : 11'h45;
|
||||
-- deviceIdCode : 16'h0001;
|
||||
-- order MSB .. LSB -> [4 bit version or revision] [16 bit part number] [11 bit manufacturer id] [value of 1'b1 in LSB]
|
||||
*/
|
||||
input [31:1] jtag_id,
|
||||
input [3:0] version
|
||||
);
|
||||
|
||||
localparam USER_DR_LENGTH = AWIDTH + 34;
|
||||
|
||||
|
||||
reg [USER_DR_LENGTH-1:0] sr, nsr, dr;
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// Tap controller
|
||||
///////////////////////////////////////////////////////
|
||||
logic[3:0] state, nstate;
|
||||
logic [4:0] ir;
|
||||
wire jtag_reset;
|
||||
wire shift_dr;
|
||||
wire pause_dr;
|
||||
wire update_dr;
|
||||
wire capture_dr;
|
||||
wire shift_ir;
|
||||
wire pause_ir ;
|
||||
wire update_ir ;
|
||||
wire capture_ir;
|
||||
wire[1:0] dr_en;
|
||||
wire devid_sel;
|
||||
wire [5:0] abits;
|
||||
|
||||
assign abits = AWIDTH[5:0];
|
||||
|
||||
|
||||
localparam TEST_LOGIC_RESET_STATE = 0;
|
||||
localparam RUN_TEST_IDLE_STATE = 1;
|
||||
localparam SELECT_DR_SCAN_STATE = 2;
|
||||
localparam CAPTURE_DR_STATE = 3;
|
||||
localparam SHIFT_DR_STATE = 4;
|
||||
localparam EXIT1_DR_STATE = 5;
|
||||
localparam PAUSE_DR_STATE = 6;
|
||||
localparam EXIT2_DR_STATE = 7;
|
||||
localparam UPDATE_DR_STATE = 8;
|
||||
localparam SELECT_IR_SCAN_STATE = 9;
|
||||
localparam CAPTURE_IR_STATE = 10;
|
||||
localparam SHIFT_IR_STATE = 11;
|
||||
localparam EXIT1_IR_STATE = 12;
|
||||
localparam PAUSE_IR_STATE = 13;
|
||||
localparam EXIT2_IR_STATE = 14;
|
||||
localparam UPDATE_IR_STATE = 15;
|
||||
|
||||
always_comb begin
|
||||
nstate = state;
|
||||
case(state)
|
||||
TEST_LOGIC_RESET_STATE: nstate = tms ? TEST_LOGIC_RESET_STATE : RUN_TEST_IDLE_STATE;
|
||||
RUN_TEST_IDLE_STATE: nstate = tms ? SELECT_DR_SCAN_STATE : RUN_TEST_IDLE_STATE;
|
||||
SELECT_DR_SCAN_STATE: nstate = tms ? SELECT_IR_SCAN_STATE : CAPTURE_DR_STATE;
|
||||
CAPTURE_DR_STATE: nstate = tms ? EXIT1_DR_STATE : SHIFT_DR_STATE;
|
||||
SHIFT_DR_STATE: nstate = tms ? EXIT1_DR_STATE : SHIFT_DR_STATE;
|
||||
EXIT1_DR_STATE: nstate = tms ? UPDATE_DR_STATE : PAUSE_DR_STATE;
|
||||
PAUSE_DR_STATE: nstate = tms ? EXIT2_DR_STATE : PAUSE_DR_STATE;
|
||||
EXIT2_DR_STATE: nstate = tms ? UPDATE_DR_STATE : SHIFT_DR_STATE;
|
||||
UPDATE_DR_STATE: nstate = tms ? SELECT_DR_SCAN_STATE : RUN_TEST_IDLE_STATE;
|
||||
SELECT_IR_SCAN_STATE: nstate = tms ? TEST_LOGIC_RESET_STATE : CAPTURE_IR_STATE;
|
||||
CAPTURE_IR_STATE: nstate = tms ? EXIT1_IR_STATE : SHIFT_IR_STATE;
|
||||
SHIFT_IR_STATE: nstate = tms ? EXIT1_IR_STATE : SHIFT_IR_STATE;
|
||||
EXIT1_IR_STATE: nstate = tms ? UPDATE_IR_STATE : PAUSE_IR_STATE;
|
||||
PAUSE_IR_STATE: nstate = tms ? EXIT2_IR_STATE : PAUSE_IR_STATE;
|
||||
EXIT2_IR_STATE: nstate = tms ? UPDATE_IR_STATE : SHIFT_IR_STATE;
|
||||
UPDATE_IR_STATE: nstate = tms ? SELECT_DR_SCAN_STATE : RUN_TEST_IDLE_STATE;
|
||||
default: nstate = TEST_LOGIC_RESET_STATE;
|
||||
endcase
|
||||
end
|
||||
|
||||
always @ (posedge tck or negedge trst) begin
|
||||
if(!trst) state <= TEST_LOGIC_RESET_STATE;
|
||||
else state <= nstate;
|
||||
end
|
||||
|
||||
assign jtag_reset = state == TEST_LOGIC_RESET_STATE;
|
||||
assign shift_dr = state == SHIFT_DR_STATE;
|
||||
assign pause_dr = state == PAUSE_DR_STATE;
|
||||
assign update_dr = state == UPDATE_DR_STATE;
|
||||
assign capture_dr = state == CAPTURE_DR_STATE;
|
||||
assign shift_ir = state == SHIFT_IR_STATE;
|
||||
assign pause_ir = state == PAUSE_IR_STATE;
|
||||
assign update_ir = state == UPDATE_IR_STATE;
|
||||
assign capture_ir = state == CAPTURE_IR_STATE;
|
||||
|
||||
assign tdoEnable = shift_dr | shift_ir;
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// IR register
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
always @ (negedge tck or negedge trst) begin
|
||||
if (!trst) ir <= 5'b1;
|
||||
else begin
|
||||
if (jtag_reset) ir <= 5'b1;
|
||||
else if (update_ir) ir <= (sr[4:0] == '0) ? 5'h1f :sr[4:0];
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
assign devid_sel = ir == 5'b00001;
|
||||
assign dr_en[0] = ir == 5'b10000;
|
||||
assign dr_en[1] = ir == 5'b10001;
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// Shift register
|
||||
///////////////////////////////////////////////////////
|
||||
always @ (posedge tck or negedge trst) begin
|
||||
if(!trst)begin
|
||||
sr <= '0;
|
||||
end
|
||||
else begin
|
||||
sr <= nsr;
|
||||
end
|
||||
end
|
||||
|
||||
// SR next value
|
||||
always_comb begin
|
||||
nsr = sr;
|
||||
case(1)
|
||||
shift_dr: begin
|
||||
case(1)
|
||||
dr_en[1]: nsr = {tdi, sr[USER_DR_LENGTH-1:1]};
|
||||
|
||||
dr_en[0],
|
||||
devid_sel: nsr = {{USER_DR_LENGTH-32{1'b0}},tdi, sr[31:1]};
|
||||
default: nsr = {{USER_DR_LENGTH-1{1'b0}},tdi}; // bypass
|
||||
endcase
|
||||
end
|
||||
capture_dr: begin
|
||||
case(1)
|
||||
dr_en[0]: nsr = {{USER_DR_LENGTH-15{1'b0}}, idle, dmi_stat, abits, version};
|
||||
dr_en[1]: nsr = {{AWIDTH{1'b0}}, rd_data, rd_status};
|
||||
devid_sel: nsr = {{USER_DR_LENGTH-32{1'b0}}, jtag_id, 1'b1};
|
||||
endcase
|
||||
end
|
||||
shift_ir: nsr = {{USER_DR_LENGTH-5{1'b0}},tdi, sr[4:1]};
|
||||
capture_ir: nsr = {{USER_DR_LENGTH-1{1'b0}},1'b1};
|
||||
endcase
|
||||
end
|
||||
|
||||
// TDO retiming
|
||||
always @ (negedge tck ) tdo <= sr[0];
|
||||
|
||||
// DMI CS register
|
||||
always @ (posedge tck or negedge trst) begin
|
||||
if(!trst) begin
|
||||
dmi_hard_reset <= 1'b0;
|
||||
dmi_reset <= 1'b0;
|
||||
end
|
||||
else if (update_dr & dr_en[0]) begin
|
||||
dmi_hard_reset <= sr[17];
|
||||
dmi_reset <= sr[16];
|
||||
end
|
||||
else begin
|
||||
dmi_hard_reset <= 1'b0;
|
||||
dmi_reset <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
// DR register
|
||||
always @ (posedge tck or negedge trst) begin
|
||||
if(!trst)
|
||||
dr <= '0;
|
||||
else begin
|
||||
if (update_dr & dr_en[1])
|
||||
dr <= sr;
|
||||
else
|
||||
dr <= {dr[USER_DR_LENGTH-1:2],2'b0};
|
||||
end
|
||||
end
|
||||
|
||||
assign {wr_addr, wr_data, wr_en, rd_en} = dr;
|
||||
|
||||
|
||||
|
||||
|
||||
endmodule
|
Loading…
Reference in New Issue