Add demo for veilator and fpga.

This commit is contained in:
colin 2022-03-10 03:56:21 +00:00
parent 2bc0985afd
commit 896011449d
35 changed files with 96803 additions and 0 deletions

22
.gitignore vendored Normal file
View File

@ -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/

77
demo/Makefile Normal file
View File

@ -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

29
demo/Readmd.md Normal file
View File

@ -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`

3
demo/gdbinit Normal file
View File

@ -0,0 +1,3 @@
# set debug remote 1
target remote :3333
set remotetimeout 2000

BIN
demo/jtag.bin Executable file

Binary file not shown.

28
demo/program.hex Executable file
View File

@ -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

34
demo/swerv.cfg Normal file
View File

@ -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

65
demo/test_soc_sim.cpp Normal file
View File

@ -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);
}

2267
soc/JSON.pm Normal file

File diff suppressed because it is too large Load Diff

0
soc/Makefile Normal file
View File

110
soc/ahb_sif.sv Normal file
View File

@ -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

196
soc/axi_lsu_dma_bridge.sv Normal file
View File

@ -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

395
soc/dasm.svi Normal file
View File

@ -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

437
soc/dpi/common/tcp_server.c Normal file
View File

@ -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;
}

View File

@ -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_

154
soc/dpi/jtagdpi/jtagdpi.c Normal file
View File

@ -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;
}

56
soc/dpi/jtagdpi/jtagdpi.h Normal file
View File

@ -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_

View File

@ -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

84981
soc/quasar_wrapper.sv Normal file

File diff suppressed because it is too large Load Diff

9
soc/soc_sim.mk Normal file
View File

@ -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

416
soc/soc_sim.sv Normal file
View File

@ -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

16
soc/soc_top.mk Normal file
View File

@ -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

843
soc/soc_top.sv Normal file
View File

@ -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

2057
soc/swerv.config Executable file

File diff suppressed because it is too large Load Diff

799
soc/vsrc/beh_lib.sv Normal file
View File

@ -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

View File

@ -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

90
soc/vsrc/dmi_wrapper.sv Normal file
View File

@ -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

14
soc/vsrc/gated_latch.sv Normal file
View File

@ -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

1551
soc/vsrc/ifu_ic_mem.sv Normal file

File diff suppressed because it is too large Load Diff

479
soc/vsrc/ifu_iccm_mem.sv Normal file
View File

@ -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

302
soc/vsrc/lsu_dccm_mem.sv Normal file
View File

@ -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

549
soc/vsrc/mem.sv Normal file
View File

@ -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

243
soc/vsrc/mem_lib.sv Normal file
View File

@ -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

178
soc/vsrc/parameter.sv Normal file
View File

@ -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
)

223
soc/vsrc/rvjtag_tap.sv Normal file
View File

@ -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