Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • soclabs/expansion_subsystem_tech
1 result
Select Git revision
Show changes
Commits on Source (3)
......@@ -6,6 +6,8 @@ logical/SMC
logical/nic400_expansion_subsystem
logical/shared
simulate
verif/cocotb/sim_build
verif/cocotb/__pycache__
verif/cocotb/*.vstf
......
......@@ -15,14 +15,34 @@ You will need the following IP from Arm, all available through Arm Academic Acce
- NIC400
You will also need installed
- Socrates
- Socrates (with NIC400 IP and license)
- CocoTB
- A simulator (e.g. QuestaSim, VCS, xelium)
For FPGA development you will need a Vivado installation
## Usage
## Setup
1. Setup make config
You will first need to add the path to the DMA-350 and BP301 (SIE300) logical directories. Edit the make.cfg file at the top level of this repository to point to the logical directories of each IP
2. Build configured IP
If this is a fresh version of the repository, you can run:
```make first_time_setup```
This will generate the RTL for the DMA-350 and BP301, it will also create a socrates project for the generation of the NIC400 RTL. You may see a lot of warnings during the building of the NIC400, these are expected. Once run you can check the logical/ directory of the local repository which should contain - DMA350, SMC, and nic400_expansion_subsystem
If you have already run ```make first_time_setup``` or ```make make_project``` you can run:
```make build_ip```
which will build all of the necessary IP.
3. Setup environment variables
You can run ```source set_exp_env.sh``` which will setup the relevant environment variables
## Simulation
Currently cocoTB is the only supported method of simulation, although a verilog testbench is under developement.
To run the current cocoTB verification go to verif/cocotb and run ```make```
This will run the default tests for the expansion subsystem. You can edit the expansion_subsystem_tests.py file to include further tests
## Accelerator integration
The subsystem has an expansion region where you can integrate your accelerator. This includes a full AXI slave port with 128-bit data width, an APB port for register interfacing with your accelerator, as well as clock and power control (Q and P-channel).
......
$(SOCLABS_EXP_SUBSYSTEM_TECH_DIR)/logical/expansion_region/verilog/expansion_region.v
$(SOCLABS_EXP_SUBSYSTEM_TECH_DIR)/logical/SRAM/verilog/SRAM_wrapper.v
$(SOCLABS_EXP_SUBSYSTEM_TECH_DIR)/logical/SRAM/verilog/SRAM.v
$(SOCLABS_EXP_SUBSYSTEM_TECH_DIR)/logical/top_expansion_subsystem/verilog/expansion_subsystem_wrapper.v
-F $(SOCLABS_EXP_SUBSYSTEM_TECH_DIR)/logical/dma350/logical/ada_top_sldma350/verilog/ada_top_sldma350.vc
-F $(SOCLABS_EXP_SUBSYSTEM_TECH_DIR)/logical/nic400_expansion_subsystem/logical/nic400_expansion_subsystem/nic400/verilog/nic400_expansion_subsystem.vc
-F $(SOCLABS_EXP_SUBSYSTEM_TECH_DIR)/logical/SMC/logical/sie300_axi5_sram_ctrl_expansion_subsystem/verilog/sie300_axi5_sram_ctrl_expansion_subsystem.vc
\ No newline at end of file
#-----------------------------------------------------------------------------
#-------------------------------------------------------------------------------------
# Expansion subsystem Simulation Makefile
# A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
#
......@@ -7,4 +7,153 @@
# David Mapstone (d.a.mapstone@soton.ac.uk)
# Daniel Newbrook (d.newbrook@soton.ac.uk)
# Copyright (C) 2021-4, SoC Labs (www.soclabs.org)
#-----------------------------------------------------------------------------
#-------------------------------------------------------------------------------------
# MTI options
MTI_VC_OPTIONS = +acc
MTI_VC_OPTIONS += -suppress 2892
MTI_VC_OPTIONS += -f $(TBENCH_VC) $(ADP_OPTIONS)
MTI_RUN_OPTIONS = -voptargs=+acc
# VCS options
VCS_OPTIONS = +vcs+lic+wait +v2k -sverilog -override_timescale=1ns/1ps +lint=all,noTMR,noVCDE -debug
VCS_SIM_OPTION = +vcs+lic+wait +vcs+flush+log -assert nopostproc
VCS_VC_OPTIONS = -f $(TBENCH_VC) $(ADP_OPTIONS)
# XM verilog options
XMSIM_OPTIONS = -unbuffered -64bit -status -LICQUEUE -f xmsim.args -cdslib cds.lib -hdlvar hdl.var -NBASYNC
XM_VC_OPTIONS = -f $(TBENCH_VC) $(ADP_OPTIONS)
# ------- Cocotb Variables -----------
# Convert Simulator Name for Cocotb
COCOTB_SIMULATOR ?= questa
ifeq ($(SIMULATOR),mti)
COCOTB_SIMULATOR := questa
else ifeq ($(SIMULATOR),xm)
COCOTB_SIMULATOR := xcelium
else ifeq ($(SIMULATOR),vcs)
COCOTB_SIMULATOR := vcs
endif
# Cocotb GUI Variable
GUI ?= 0
# Cocotb Test Location
COCOTB_TEST_DIR := $(SOCLABS_EXP_SUBSYSTEM_TECH_DIR)/verif/cocotb
# Cocotb Scratch Directory
COCOTB_DIR := $(EXP_SIM_TOP_DIR)/cocotb
COCOTB_SCRATCH_DIR := $(COCOTB_DIR)/scratch
# Filelist for Cocotb
MAKEFILE_FILELIST := $(COCOTB_DIR)/makefile.flist
# Create a List of PHONY Targets
.PHONY: compile_$(SIMULATOR) run_$(SIMULATOR) sim_$(SIMULATOR)
# ------- Simulator redirect -----------
compile: compile_$(SIMULATOR)
run: run_$(SIMULATOR)
sim: sim_$(SIMULATOR)
# Preload IMEM in Simulation
compile_mti: EXPANSION_SUBSYSTEM_DEFINES += IMEM_0_RAM_PRELOAD
compile_vcs: EXPANSION_SUBSYSTEM_DEFINES += IMEM_0_RAM_PRELOAD
compile_xm: EXPANSION_SUBSYSTEM_DEFINES += IMEM_0_RAM_PRELOAD
make_workspace:
@if [ ! -d $(EXP_SIM_DIR) ] ; then \
mkdir -p $(EXP_SIM_DIR); \
fi
@if [ ! -d $(EXP_SIM_DIR)/logs ] ; then \
mkdir -p $(EXP_SIM_DIR)/logs; \
fi
# ------- VCS -----------
# Compile RTL
compile_vcs : gen_defs
cd $(EXP_SIM_DIR); vcs $(VCS_OPTIONS) -f tbench.vc $(DEFINES_VC) | tee compile_vcs.log
# Run simulation in batch mode
run_vcs : code compile_vcs
@echo quit > $(EXP_SIM_DIR)/quit.do
cd $(EXP_SIM_DIR); ./simv $(VCS_SIM_OPTION) -define ADP_FILE=adp.cmd < quit.do | tee logs/run_$(TESTNAME).log ;
# Run simulation in interactive mode
sim_vcs : code compile_vcs
cd $(EXP_SIM_DIR); ./simv -gui +vcs+lic+wait +vcs+flush+log &
# ------- XM -----------
# Compile RTL
compile_xm : bootrom gen_defs
@echo ADP_FILE
@echo $(ADP_OPTIONS)
cd $(EXP_SIM_DIR); xmprep +overwrite $(XM_VC_OPTIONS) $(DEFINES_VC) +debug -timescale 1ns/1ps -top $(TB_TOP) | tee compile_xm.log
cd $(EXP_SIM_DIR); xmvlog -work worklib -f xmvlog_ver.args | tee -a compile_xm.log
cd $(EXP_SIM_DIR); xmelab -mess -f xmelab.args -access +r | tee -a compile_xm.log
# Note : If coverage is required, you can add -coverage all to xmelab
# Run simulation in batch mode
run_xm : code compile_xm
@echo run > $(EXP_SIM_DIR)/run.tcl.tmp
@echo exit >> $(EXP_SIM_DIR)/run.tcl.tmp
@mv $(EXP_SIM_DIR)/run.tcl.tmp $(EXP_SIM_DIR)/run.tcl
cd $(EXP_SIM_DIR); xmsim $(XMSIM_OPTIONS) -input run.tcl | tee logs/run_$(TESTNAME).log ;
# Run simulation in interactive mode
sim_xm : code compile_xm
cd $(EXP_SIM_DIR); xmsim -gui $(XMSIM_OPTIONS)
# ------- MTI -----------
# Compile RTL
compile_mti : lib_mti
cd $(EXP_SIM_DIR); vlog -incr -lint +v2k -f $(TBENCH_VC) $(ADP_OPTIONS) $(DEFINES_VC) | tee compile_mti.log
# Run simulation in batch mode
run_mti : compile_mti
@echo "run -all" > $(EXP_SIM_DIR)/run.tcl.tmp
@echo "quit -f" >> $(EXP_SIM_DIR)/run.tcl.tmp
@mv $(EXP_SIM_DIR)/run.tcl.tmp $(EXP_SIM_DIR)/run.tcl
cd $(EXP_SIM_DIR); vsim $(MTI_RUN_OPTIONS) -c $(TB_TOP) -do run.tcl | tee $(EXP_SIM_DIR)/logs/run_$(TESTNAME).log ;
run_mti_to:
timeout 2s $(MAKE) run_mti >> /dev/null 2>&1
run_mti_wrap:
$(MAKE) run_mti_to
# Run simulation in interactive mode
sim_mti : compile_mti
cd $(EXP_SIM_DIR); vsim $(MTI_RUN_OPTIONS) -gui $(TB_TOP) &
# Create work directory
lib_mti :
@if [ -d $(EXP_SIM_DIR)/work ] ; then \
true ; \
else \
vlib $(EXP_SIM_DIR)/work; \
fi
run_cocotb: DEFINES_VC += COCOTB_SIM
run_cocotb:
@mkdir -p $(EXP_SIM_DIR)
@cd $(EXP_SIM_DIR); $(MAKE) -C $(SOCLABS_EXP_SUBSYSTEM_TECH_DIR)/verif/cocotb clean SIM_BUILD=$(COCOTB_SCRATCH_DIR)
@cd $(EXP_SIM_DIR); $(MAKE) -C $(SOCLABS_EXP_SUBSYSTEM_TECH_DIR)/verif/cocotb sim MODULE=$(MODULE) SIM=$(COCOTB_SIMULATOR) TESTCASE=$(TESTNAME) GUI=$(GUI) SIM_BUILD=$(COCOTB_SCRATCH_DIR)
sim_cocotb: GUI=1
sim_cocotb: run_cocotb
......@@ -71,7 +71,7 @@ module expansion_subsystem_wrapper(
input wire AXI_EXP_SS_rready,
// AXI System output port
output wire [1:0] AXI_SYS_awid,
output wire [2:0] AXI_SYS_awid,
output wire [31:0] AXI_SYS_awaddr,
output wire [7:0] AXI_SYS_awlen,
output wire [2:0] AXI_SYS_awsize,
......@@ -86,11 +86,11 @@ module expansion_subsystem_wrapper(
output wire AXI_SYS_wlast,
output wire AXI_SYS_wvalid,
input wire AXI_SYS_wready,
input wire [1:0] AXI_SYS_bid,
input wire [2:0] AXI_SYS_bid,
input wire [1:0] AXI_SYS_bresp,
input wire AXI_SYS_bvalid,
output wire AXI_SYS_bready,
output wire [1:0] AXI_SYS_arid,
output wire [2:0] AXI_SYS_arid,
output wire [31:0] AXI_SYS_araddr,
output wire [7:0] AXI_SYS_arlen,
output wire [2:0] AXI_SYS_arsize,
......@@ -100,7 +100,7 @@ module expansion_subsystem_wrapper(
output wire [2:0] AXI_SYS_arprot,
output wire AXI_SYS_arvalid,
input wire AXI_SYS_arready,
input wire [1:0] AXI_SYS_rid,
input wire [2:0] AXI_SYS_rid,
input wire [63:0] AXI_SYS_rdata,
input wire [1:0] AXI_SYS_rresp,
input wire AXI_SYS_rlast,
......
......@@ -12,6 +12,42 @@
include ./flows/makefile.simulate
include ./make.cfg
#-------------------------------------
# - Commonly Overloaded Variables
#-------------------------------------
# Name of test directory - Default Test is Hello World
TESTNAME ?= hello
# Simulator type (mti/vcs/xm)
SIMULATOR = mti
# Is an accelerator subsystem present in the design?
ACCELERATOR ?= yes
# Is this for a backend ASIC flow?
ASIC ?= no
#-------------------------------------
# - Directory Setups
#-------------------------------------
# Directory of Testcodes
TESTCODES_DIR := $(SOCLABS_EXP_SUBSYSTEM_TECH_DIR)/testcodes
# Project System Directory
FPGA_IMP_DIR := $(SOCLABS_EXP_SUBSYSTEM_TECH_DIR)/imp/fpga
# Directory to put simulation files
EXP_SIM_TOP_DIR := $(SOCLABS_EXP_SUBSYSTEM_TECH_DIR)/simulate/sim
EXP_SIM_DIR := $(EXP_SIM_TOP_DIR)/$(TESTNAME)
DESIGN_VC ?= $(SOCLABS_EXP_SUBSYSTEM_TECH_DIR)/flist/expansion_subsystem.vc
TBENCH_VC ?= $(SOCLABS_EXP_SUBSYSTEM_TECH_DIR)/verif/testbench/logical/expansion_subsystem_tb.vc
TB_TOP ?= expansion_subsystem_tb
build_dma350:
@$(DMA350_IP_LOGICAL_DIR)/generate --config ./socrates/DMA350/config/cfg_dma_axi.yaml --output ./logical/dma350/
build_sie300_sram_ctrl:
......
......@@ -29,13 +29,14 @@ from cocotb.clock import Clock
from cocotb.triggers import RisingEdge, Timer, ClockCycles
from cocotb.regression import TestFactory
from cocotbext.axi import AxiBus, AxiMaster, AxiBurstType, AxiSlave
from cocotbext.axi import AxiBus, AxiMaster, AxiRam, AxiBurstType, AxiSlave
SRAM_0_BASE_ADDR = 0x60000000
SRAM_1_BASE_ADDR = 0x60040000
SRAM_0_BASE_ADDR_HI = 0x68000000
SRAM_1_BASE_ADDR_HI = 0x68040000
EXT_SRAM_BASE_ADDR = 0x00000000
class TB:
def __init__(self,dut):
......@@ -47,17 +48,24 @@ class TB:
cocotb.start_soon(Clock(dut.sys_clk, 1.25, units="ns").start())
cocotb.start_soon(Clock(dut.exp_clk, 1, units="ns").start())
self.axi_master = AxiMaster(AxiBus.from_prefix(dut,"AXI_EXP_SS"), dut.sys_clk, dut.resetn, reset_active_level=False)
self.axi_slave = AxiSlave(AxiBus.from_prefix(dut,"AXI_SYS"), dut.sys_clk, dut.expresetn, reset_active_level=False)
self.axi_ram= AxiRam(AxiBus.from_prefix(dut,"AXI_SYS"), dut.sys_clk, dut.expresetn, reset_active_level=False, size=2**32)
self.axi_ram.write_if.log.setLevel(logging.DEBUG)
self.axi_ram.read_if.log.setLevel(logging.DEBUG)
def set_idle_generator(self, generator=None):
if generator:
self.axi_master.write_if.aw_channel.set_pause_generator(generator())
self.axi_master.write_if.w_channel.set_pause_generator(generator())
self.axi_master.read_if.ar_channel.set_pause_generator(generator())
self.axi_ram.write_if.b_channel.set_pause_generator(generator())
self.axi_ram.read_if.r_channel.set_pause_generator(generator())
def set_backpressure_generator(self, generator=None):
if generator:
self.axi_master.write_if.b_channel.set_pause_generator(generator())
self.axi_master.read_if.r_channel.set_pause_generator(generator())
self.axi_ram.write_if.aw_channel.set_pause_generator(generator())
self.axi_ram.write_if.w_channel.set_pause_generator(generator())
self.axi_ram.read_if.ar_channel.set_pause_generator(generator())
async def cycle_reset(self):
self.dut.resetn.setimmediatevalue(1)
......@@ -111,6 +119,27 @@ async def init_sram_random(dut, tb, base_addr):
await RisingEdge(dut.sys_clk)
async def init_ext_sram_random(dut, tb, base_addr):
data = random.bytes(2048)
tb.axi_ram.write(base_addr, data)
tb.axi_ram.write(base_addr+2048, data)
tb.axi_ram.write(base_addr+4096, data)
tb.axi_ram.write(base_addr+6144, data)
tb.axi_ram.write(base_addr+8192, data)
tb.axi_ram.write(base_addr+10240, data)
tb.axi_ram.write(base_addr+12288, data)
tb.axi_ram.write(base_addr+14336, data)
await RisingEdge(dut.sys_clk)
async def init_sram_incr(dut, tb, base_addr):
data = bytearray(range(256))
for i in range(64):
await tb.axi_master.write(base_addr+i*256, data)
await RisingEdge(dut.sys_clk)
async def SRAM_test_write(dut, tb, base_addr, byte_lanes, size):
for length in list(range(1, byte_lanes*2))+[8192]:
for offset in list(range(byte_lanes))+list(range(8192-byte_lanes, 8192)):
......@@ -284,3 +313,71 @@ async def DMA350_basic_transfer(dut, idle_inserter=None, backpressure_inserter=N
bandwidth = 128*transactions/(tend-tstart)
tb.log.info("Bandwidth of DMA transfer = " + str(bandwidth) + " Gbps")
@cocotb.test()
async def DMA350_to_external_SRAM(dut, idle_inserter=None, backpressure_inserter=None, size=None):
transactions = 0x1FF
tb = TB(dut)
await tb.cycle_reset()
await RisingEdge(dut.sys_clk)
await RisingEdge(dut.sys_clk)
await init_sram_random(dut, tb, SRAM_0_BASE_ADDR)
await dma350.AdaSetSourceAddress(dut, tb, 0, SRAM_0_BASE_ADDR)
await dma350.AdaSetDestAddress(dut, tb, 0, EXT_SRAM_BASE_ADDR)
await dma350.AdaSetTranSize(dut, tb, 0, transactions, transactions)
await dma350.AdaSetChControl(dut, tb, 0, dma350_regtype.TRANSIZE_type.bits128, 15, dma350_regtype.XYTYPE_type.cont, dma350_regtype.XYTYPE_type.dis, 0, 0, 0, 0, 0, 0, 0, 0)
await dma350.AdaSetIntrEn(dut, tb, 0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0)
await dma350.AdaSetChDESTRANSCFG(dut, tb, 0, 0x4, 0x4, 0x0, 0x1, 0x0, 0xF)
await dma350.AdaSetChSRCTRANSCFG(dut, tb, 0, 0x4, 0x4, 0x0, 0x1, 0x0, 0xF)
await dma350.AdaSetChXADDRINC(dut, tb, 0, 0x1, 0x1)
await dma350.AdaGetIntrEn(dut, tb, 0)
tstart=cocotb.utils.get_sim_time('ns')
await dma350.AdaEnable(dut, tb, 0)
tb.log.info("DMA Transfer started")
ch_enabled = 1
while ch_enabled == 1:
ch_enabled = dut.u_DMA350.ch_enabled.value
await ClockCycles(dut.sys_clk, 1)
tb.log.info("DMA Transfer finished")
tend = cocotb.utils.get_sim_time('ns')
ch_stat = await dma350.AdaGetStatus(dut, tb, 0)
n_cycles = (tend-tstart)/(transactions)
tb.log.info("Tstart: " + str(tstart) + " Tend: " + str(tend))
tb.log.info("Average no of clocks per transaction = " + str(n_cycles))
bandwidth = 128*transactions/(tend-tstart)
tb.log.info("Bandwidth of DMA transfer = " + str(bandwidth) + " Gbps")
@cocotb.test()
async def DMA350_from_external_SRAM(dut, idle_inserter=None, backpressure_inserter=None, size=None):
transactions = 0x1FF
tb = TB(dut)
await tb.cycle_reset()
await RisingEdge(dut.sys_clk)
await RisingEdge(dut.sys_clk)
await init_ext_sram_random(dut, tb, EXT_SRAM_BASE_ADDR)
await dma350.AdaSetSourceAddress(dut, tb, 0, EXT_SRAM_BASE_ADDR)
await dma350.AdaSetDestAddress(dut, tb, 0, SRAM_0_BASE_ADDR)
await dma350.AdaSetTranSize(dut, tb, 0, transactions, transactions)
await dma350.AdaSetChControl(dut, tb, 0, dma350_regtype.TRANSIZE_type.bits128, 15, dma350_regtype.XYTYPE_type.cont, dma350_regtype.XYTYPE_type.dis, 0, 0, 0, 0, 0, 0, 0, 0)
await dma350.AdaSetIntrEn(dut, tb, 0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0)
await dma350.AdaSetChDESTRANSCFG(dut, tb, 0, 0x4, 0x4, 0x0, 0x1, 0x0, 0xF)
await dma350.AdaSetChSRCTRANSCFG(dut, tb, 0, 0x4, 0x4, 0x0, 0x1, 0x0, 0xF)
await dma350.AdaSetChXADDRINC(dut, tb, 0, 0x1, 0x1)
await dma350.AdaGetIntrEn(dut, tb, 0)
tstart=cocotb.utils.get_sim_time('ns')
await dma350.AdaEnable(dut, tb, 0)
tb.log.info("DMA Transfer started")
ch_enabled = 1
while ch_enabled == 1:
ch_enabled = dut.u_DMA350.ch_enabled.value
await ClockCycles(dut.sys_clk, 1)
tb.log.info("DMA Transfer finished")
tend = cocotb.utils.get_sim_time('ns')
ch_stat = await dma350.AdaGetStatus(dut, tb, 0)
n_cycles = (tend-tstart)/(transactions)
tb.log.info("Tstart: " + str(tstart) + " Tend: " + str(tend))
tb.log.info("Average no of clocks per transaction = " + str(n_cycles))
bandwidth = 128*transactions/(tend-tstart)
tb.log.info("Bandwidth of DMA transfer = " + str(bandwidth) + " Gbps")
module clk_ctrl (
input wire SYSCLK,
input wire NRST,
input wire EXPCLK,
input wire EXP_NRST,
output wire CSYSREQ_CD_sys,
input wire CSYSACK_CD_sys,
input wire CACTIVE_CD_sys,
output wire CSYSREQ_CD_exp,
input wire CSYSACK_CD_exp,
input wire CACTIVE_CD_exp
);
parameter IDLE=2'b00, REQ=2'b01, ACK=2'b10, ACT=2'b11;
reg [1:0] state_sys;
reg [1:0] state_sys_next;
reg [1:0] state_exp;
reg [1:0] state_exp_next;
reg CSYSREQ_CD_sys_reg;
reg SYS_ACT;
reg CSYSREQ_CD_exp_reg;
reg EXP_ACT;
always @(posedge SYSCLK or negedge NRST) begin
if (!NRST) begin
state_sys <= IDLE;
CSYSREQ_CD_sys_reg <= 0;
SYS_ACT<=0;
end
else
state_sys <= state_sys_next;
end
always @(*) begin
state_sys_next = state_sys;
case(state_sys)
IDLE : begin
if(!SYS_ACT)
state_sys_next = REQ;
end
REQ: begin
CSYSREQ_CD_sys_reg = 1;
state_sys_next = ACK;
end
ACK: begin
if(CSYSACK_CD_sys) begin
$display("CLK CTRL: System clock enable acknowledged");
state_sys_next = ACT;
end
end
ACT: begin
if(CACTIVE_CD_sys) begin
$display("CLK CTRL: System clock active");
SYS_ACT = 1;
state_sys_next = IDLE;
end
end
endcase
end
assign CSYSREQ_CD_sys = CSYSREQ_CD_sys_reg;
always @(posedge EXPCLK or negedge EXP_NRST) begin
if (!EXP_NRST) begin
state_exp <= IDLE;
CSYSREQ_CD_exp_reg <= 0;
EXP_ACT<=0;
end
else
state_exp <= state_exp_next;
end
always @(*) begin
state_exp_next = state_exp;
case(state_exp)
IDLE : begin
if(!EXP_ACT)
state_exp_next = REQ;
end
REQ: begin
CSYSREQ_CD_exp_reg = 1;
state_exp_next = ACK;
end
ACK: begin
if(CSYSACK_CD_exp) begin
$display("CLK CTRL: Expansion clock enable acknowledged");
state_exp_next = ACT;
end
end
ACT: begin
if(CACTIVE_CD_exp) begin
$display("CLK CTRL: Expansion clock active");
SYS_ACT = 1;
state_exp_next = IDLE;
end
end
endcase
end
assign CSYSREQ_CD_exp = CSYSREQ_CD_exp_reg;
endmodule
\ No newline at end of file
//-----------------------------------------------------------------------------
// Expansion subsystem clock and power on generator adapted from Arm CMSDK Simple clock and power on reset generator
// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
//
// Contributors
//
// David Flynn (d.w.flynn@soton.ac.uk)
//
// Copyright � 2021-3, SoC Labs (www.soclabs.org)
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// The confidential and proprietary information contained in this file may
// only be used by a person authorised under and to the extent permitted
// by a subsisting licensing agreement from Arm Limited or its affiliates.
//
// (C) COPYRIGHT 2010-2013 Arm Limited or its affiliates.
// ALL RIGHTS RESERVED
//
// This entire notice must be reproduced on all copies of this file
// and copies of this file may only be made by a person if such person is
// permitted to do so under the terms of a subsisting license agreement
// from Arm Limited or its affiliates.
//
// SVN Information
//
// Checked In : $Date: 2017-10-10 15:55:38 +0100 (Tue, 10 Oct 2017) $
//
// Revision : $Revision: 371321 $
//
// Release Information : Cortex-M System Design Kit-r1p1-00rel0
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Abstract : Simple clock and power on reset generator
//-----------------------------------------------------------------------------
`timescale 1ns/1ps
module clkreset(
output wire SYSCLK,
output wire EXPCLK,
output wire NRST,
output wire EXP_NRST
);
reg clock_q;
reg clock_q_exp;
reg [7:0] shifter;
reg [15:0] exp_shifter;
initial
begin
clock_q <= 1'b0;
clock_q_exp <= 1'b1;
shifter <= 8'h00;
exp_shifter <= 16'h0000;
#10 clock_q <= 1'b1;
#10 clock_q_exp <= 1'b1;
end
always @(clock_q) begin
#1 clock_q <= !clock_q; // 2ns period, 500 MHz
end
assign SYSCLK = clock_q;
always @(clock_q_exp) begin
#0.5 clock_q_exp <= !clock_q_exp; // 1ns period, 1000 MHz
end
assign EXPCLK = clock_q_exp;
always @(posedge clock_q)
if (! (&shifter)) // until full...
shifter <= {shifter[6:0], 1'b1}; // shift left, fill with 1's
assign NRST = shifter[7];
always @(posedge clock_q_exp)
if (! (&exp_shifter)) // until full...
exp_shifter <= {exp_shifter[14:0], 1'b1}; // shift left, fill with 1's
assign EXP_NRST = exp_shifter[15];
endmodule
`timescale 1ns/1ps
module expansion_subsystem_tb;
// Clock and Reset Signals
wire SYSCLK;
wire EXPCLK;
wire NRST;
wire EXP_NRST;
// Clock Control Signals
wire CSYSREQ_CD_sys;
wire CSYSACK_CD_sys;
wire CACTIVE_CD_sys;
wire CSYSREQ_CD_exp;
wire CSYSACK_CD_exp;
wire CACTIVE_CD_exp;
reg [31:0] timer;
initial begin
#500 timer <= 32'd0;
end
clkreset u_clkreset(
.SYSCLK(SYSCLK),
.EXPCLK(EXPCLK),
.NRST(NRST),
.EXP_NRST(EXP_NRST)
);
clk_ctrl u_clk_ctrl(
.SYSCLK(SYSCLK),
.NRST(NRST),
.EXPCLK(EXPCLK),
.EXP_NRST(EXP_NRST),
.CSYSREQ_CD_sys(CSYSREQ_CD_sys),
.CSYSACK_CD_sys(CSYSACK_CD_sys),
.CACTIVE_CD_sys(CACTIVE_CD_sys),
.CSYSREQ_CD_exp(CSYSREQ_CD_exp),
.CSYSACK_CD_exp(CSYSACK_CD_exp),
.CACTIVE_CD_exp(CACTIVE_CD_exp)
);
// AXI EXP SS
wire AXI_EXP_SS_awid;
wire [31:0] AXI_EXP_SS_awaddr;
wire [7:0] AXI_EXP_SS_awlen;
wire [2:0] AXI_EXP_SS_awsize;
wire [1:0] AXI_EXP_SS_awburst;
wire AXI_EXP_SS_awlock;
wire [3:0] AXI_EXP_SS_awcache;
wire [2:0] AXI_EXP_SS_awprot;
wire AXI_EXP_SS_awvalid;
wire AXI_EXP_SS_awready;
wire [63:0] AXI_EXP_SS_wdata;
wire [7:0] AXI_EXP_SS_wstrb;
wire AXI_EXP_SS_wlast;
wire AXI_EXP_SS_wvalid;
wire AXI_EXP_SS_wready;
wire AXI_EXP_SS_bid;
wire [1:0] AXI_EXP_SS_bresp;
wire AXI_EXP_SS_bvalid;
wire AXI_EXP_SS_bready;
wire AXI_EXP_SS_arid;
wire [31:0] AXI_EXP_SS_araddr;
wire [7:0] AXI_EXP_SS_arlen;
wire [2:0] AXI_EXP_SS_arsize;
wire [1:0] AXI_EXP_SS_arburst;
wire AXI_EXP_SS_arlock;
wire [3:0] AXI_EXP_SS_arcache;
wire [2:0] AXI_EXP_SS_arprot;
wire AXI_EXP_SS_arvalid;
wire AXI_EXP_SS_arready;
wire AXI_EXP_SS_rid;
wire [63:0] AXI_EXP_SS_rdata;
wire [1:0] AXI_EXP_SS_rresp;
wire AXI_EXP_SS_rlast;
wire AXI_EXP_SS_rvalid;
wire AXI_EXP_SS_rready;
// AXI System output port
wire [1:0] AXI_SYS_awid;
wire [31:0] AXI_SYS_awaddr;
wire [7:0] AXI_SYS_awlen;
wire [2:0] AXI_SYS_awsize;
wire [1:0] AXI_SYS_awburst;
wire AXI_SYS_awlock;
wire [3:0] AXI_SYS_awcache;
wire [2:0] AXI_SYS_awprot;
wire AXI_SYS_awvalid;
wire AXI_SYS_awready;
wire [63:0] AXI_SYS_wdata;
wire [7:0] AXI_SYS_wstrb;
wire AXI_SYS_wlast;
wire AXI_SYS_wvalid;
wire AXI_SYS_wready;
wire [1:0] AXI_SYS_bid;
wire [1:0] AXI_SYS_bresp;
wire AXI_SYS_bvalid;
wire AXI_SYS_bready;
wire [1:0] AXI_SYS_arid;
wire [31:0] AXI_SYS_araddr;
wire [7:0] AXI_SYS_arlen;
wire [2:0] AXI_SYS_arsize;
wire [1:0] AXI_SYS_arburst;
wire AXI_SYS_arlock;
wire [3:0] AXI_SYS_arcache;
wire [2:0] AXI_SYS_arprot;
wire AXI_SYS_arvalid;
wire AXI_SYS_arready;
wire [1:0] AXI_SYS_rid;
wire [63:0] AXI_SYS_rdata;
wire [1:0] AXI_SYS_rresp;
wire AXI_SYS_rlast;
wire AXI_SYS_rvalid;
wire AXI_SYS_rready;
expansion_subsystem_wrapper u_expansion_subsystem_wrapper(
.sys_clk(SYSCLK),
.resetn(NRST),
.exp_clk(EXPCLK),
.exp_clken(1'b1),
.expresetn(EXP_NRST),
.CSYSREQ_CD_sys(CSYSREQ_CD_sys),
.CSYSACK_CD_sys(CSYSACK_CD_sys),
.CACTIVE_CD_sys(CACTIVE_CD_sys),
.CSYSREQ_CD_exp(CSYSREQ_CD_exp),
.CSYSACK_CD_exp(CSYSACK_CD_exp),
.CACTIVE_CD_exp(CACTIVE_CD_exp),
.AXI_EXP_SS_awid(AXI_EXP_SS_awid),
.AXI_EXP_SS_awaddr(AXI_EXP_SS_awaddr),
.AXI_EXP_SS_awlen(AXI_EXP_SS_awlen),
.AXI_EXP_SS_awsize(AXI_EXP_SS_awsize),
.AXI_EXP_SS_awburst(AXI_EXP_SS_awburst),
.AXI_EXP_SS_awlock(AXI_EXP_SS_awlock),
.AXI_EXP_SS_awcache(AXI_EXP_SS_awcache),
.AXI_EXP_SS_awprot(AXI_EXP_SS_awprot),
.AXI_EXP_SS_awvalid(AXI_EXP_SS_awvalid),
.AXI_EXP_SS_awready(AXI_EXP_SS_awready),
.AXI_EXP_SS_wdata(AXI_EXP_SS_wdata),
.AXI_EXP_SS_wstrb(AXI_EXP_SS_wstrb),
.AXI_EXP_SS_wlast(AXI_EXP_SS_wlast),
.AXI_EXP_SS_wvalid(AXI_EXP_SS_wvalid),
.AXI_EXP_SS_wready(AXI_EXP_SS_wready),
.AXI_EXP_SS_bid(AXI_EXP_SS_bid),
.AXI_EXP_SS_bresp(AXI_EXP_SS_bresp),
.AXI_EXP_SS_bvalid(AXI_EXP_SS_bvalid),
.AXI_EXP_SS_bready(AXI_EXP_SS_bready),
.AXI_EXP_SS_arid(AXI_EXP_SS_arid),
.AXI_EXP_SS_araddr(AXI_EXP_SS_araddr),
.AXI_EXP_SS_arlen(AXI_EXP_SS_arlen),
.AXI_EXP_SS_arsize(AXI_EXP_SS_arsize),
.AXI_EXP_SS_arburst(AXI_EXP_SS_arburst),
.AXI_EXP_SS_arlock(AXI_EXP_SS_arlock),
.AXI_EXP_SS_arcache(AXI_EXP_SS_arcache),
.AXI_EXP_SS_arprot(AXI_EXP_SS_arprot),
.AXI_EXP_SS_arvalid(AXI_EXP_SS_arvalid),
.AXI_EXP_SS_arready(AXI_EXP_SS_arready),
.AXI_EXP_SS_rid(AXI_EXP_SS_rid),
.AXI_EXP_SS_rdata(AXI_EXP_SS_rdata),
.AXI_EXP_SS_rresp(AXI_EXP_SS_rresp),
.AXI_EXP_SS_rlast(AXI_EXP_SS_rlast),
.AXI_EXP_SS_rvalid(AXI_EXP_SS_rvalid),
.AXI_EXP_SS_rready(AXI_EXP_SS_rready),
.AXI_SYS_awid(AXI_SYS_awid),
.AXI_SYS_awaddr(AXI_SYS_awaddr),
.AXI_SYS_awlen(AXI_SYS_awlen),
.AXI_SYS_awsize(AXI_SYS_awsize),
.AXI_SYS_awburst(AXI_SYS_awburst),
.AXI_SYS_awlock(AXI_SYS_awlock),
.AXI_SYS_awcache(AXI_SYS_awcache),
.AXI_SYS_awprot(AXI_SYS_awprot),
.AXI_SYS_awvalid(AXI_SYS_awvalid),
.AXI_SYS_awready(AXI_SYS_awready),
.AXI_SYS_wdata(AXI_SYS_wdata),
.AXI_SYS_wstrb(AXI_SYS_wstrb),
.AXI_SYS_wlast(AXI_SYS_wlast),
.AXI_SYS_wvalid(AXI_SYS_wvalid),
.AXI_SYS_wready(AXI_SYS_wready),
.AXI_SYS_bid(AXI_SYS_bid),
.AXI_SYS_bresp(AXI_SYS_bresp),
.AXI_SYS_bvalid(AXI_SYS_bvalid),
.AXI_SYS_bready(AXI_SYS_bready),
.AXI_SYS_arid(AXI_SYS_arid),
.AXI_SYS_araddr(AXI_SYS_araddr),
.AXI_SYS_arlen(AXI_SYS_arlen),
.AXI_SYS_arsize(AXI_SYS_arsize),
.AXI_SYS_arburst(AXI_SYS_arburst),
.AXI_SYS_arlock(AXI_SYS_arlock),
.AXI_SYS_arcache(AXI_SYS_arcache),
.AXI_SYS_arprot(AXI_SYS_arprot),
.AXI_SYS_arvalid(AXI_SYS_arvalid),
.AXI_SYS_arready(AXI_SYS_arready),
.AXI_SYS_rid(AXI_SYS_rid),
.AXI_SYS_rdata(AXI_SYS_rdata),
.AXI_SYS_rresp(AXI_SYS_rresp),
.AXI_SYS_rlast(AXI_SYS_rlast),
.AXI_SYS_rvalid(AXI_SYS_rvalid),
.AXI_SYS_rready(AXI_SYS_rready),
.irq_dma_channel(),
.irq_dma_comb_nonsec()
);
trickbox u_trickbox(
.SYSCLK(SYSCLK),
.NRST(NRST),
.AXI_EXP_SS_awid(AXI_EXP_SS_awid),
.AXI_EXP_SS_awaddr(AXI_EXP_SS_awaddr),
.AXI_EXP_SS_awlen(AXI_EXP_SS_awlen),
.AXI_EXP_SS_awsize(AXI_EXP_SS_awsize),
.AXI_EXP_SS_awburst(AXI_EXP_SS_awburst),
.AXI_EXP_SS_awlock(AXI_EXP_SS_awlock),
.AXI_EXP_SS_awcache(AXI_EXP_SS_awcache),
.AXI_EXP_SS_awprot(AXI_EXP_SS_awprot),
.AXI_EXP_SS_awvalid(AXI_EXP_SS_awvalid),
.AXI_EXP_SS_awready(AXI_EXP_SS_awready),
.AXI_EXP_SS_wdata(AXI_EXP_SS_wdata),
.AXI_EXP_SS_wstrb(AXI_EXP_SS_wstrb),
.AXI_EXP_SS_wlast(AXI_EXP_SS_wlast),
.AXI_EXP_SS_wvalid(AXI_EXP_SS_wvalid),
.AXI_EXP_SS_wready(AXI_EXP_SS_wready),
.AXI_EXP_SS_bid(AXI_EXP_SS_bid),
.AXI_EXP_SS_bresp(AXI_EXP_SS_bresp),
.AXI_EXP_SS_bvalid(AXI_EXP_SS_bvalid),
.AXI_EXP_SS_bready(AXI_EXP_SS_bready),
.AXI_EXP_SS_arid(AXI_EXP_SS_arid),
.AXI_EXP_SS_araddr(AXI_EXP_SS_araddr),
.AXI_EXP_SS_arlen(AXI_EXP_SS_arlen),
.AXI_EXP_SS_arsize(AXI_EXP_SS_arsize),
.AXI_EXP_SS_arburst(AXI_EXP_SS_arburst),
.AXI_EXP_SS_arlock(AXI_EXP_SS_arlock),
.AXI_EXP_SS_arcache(AXI_EXP_SS_arcache),
.AXI_EXP_SS_arprot(AXI_EXP_SS_arprot),
.AXI_EXP_SS_arvalid(AXI_EXP_SS_arvalid),
.AXI_EXP_SS_arready(AXI_EXP_SS_arready),
.AXI_EXP_SS_rid(AXI_EXP_SS_rid),
.AXI_EXP_SS_rdata(AXI_EXP_SS_rdata),
.AXI_EXP_SS_rresp(AXI_EXP_SS_rresp),
.AXI_EXP_SS_rlast(AXI_EXP_SS_rlast),
.AXI_EXP_SS_rvalid(AXI_EXP_SS_rvalid),
.AXI_EXP_SS_rready(AXI_EXP_SS_rready)
);
endmodule
\ No newline at end of file
$(SOCLABS_EXP_SUBSYSTEM_TECH_DIR)/verif/testbench/logical/expansion_subsystem_tb.v
$(SOCLABS_EXP_SUBSYSTEM_TECH_DIR)/verif/testbench/logical/clk_reset.v
$(SOCLABS_EXP_SUBSYSTEM_TECH_DIR)/verif/testbench/logical/clk_ctrl.v
-F $(SOCLABS_EXP_SUBSYSTEM_TECH_DIR)/flist/expansion_subsystem.vc
module trickbox(
input wire SYSCLK,
input wire NRST,
// AXI Trickbox output port
output wire AXI_EXP_SS_awid,
output wire [31:0] AXI_EXP_SS_awaddr,
output wire [7:0] AXI_EXP_SS_awlen,
output wire [2:0] AXI_EXP_SS_awsize,
output wire [1:0] AXI_EXP_SS_awburst,
output wire AXI_EXP_SS_awlock,
output wire [3:0] AXI_EXP_SS_awcache,
output wire [2:0] AXI_EXP_SS_awprot,
output wire AXI_EXP_SS_awvalid,
input wire AXI_EXP_SS_awready,
output wire [63:0] AXI_EXP_SS_wdata,
output wire [7:0] AXI_EXP_SS_wstrb,
output wire AXI_EXP_SS_wlast,
output wire AXI_EXP_SS_wvalid,
input wire AXI_EXP_SS_wready,
input wire AXI_EXP_SS_bid,
input wire [1:0] AXI_EXP_SS_bresp,
input wire AXI_EXP_SS_bvalid,
output wire AXI_EXP_SS_bready,
output wire AXI_EXP_SS_arid,
output wire [31:0] AXI_EXP_SS_araddr,
output wire [7:0] AXI_EXP_SS_arlen,
output wire [2:0] AXI_EXP_SS_arsize,
output wire [1:0] AXI_EXP_SS_arburst,
output wire AXI_EXP_SS_arlock,
output wire [3:0] AXI_EXP_SS_arcache,
output wire [2:0] AXI_EXP_SS_arprot,
output wire AXI_EXP_SS_arvalid,
input wire AXI_EXP_SS_arready,
input wire AXI_EXP_SS_rid,
input wire [63:0] AXI_EXP_SS_rdata,
input wire [1:0] AXI_EXP_SS_rresp,
input wire AXI_EXP_SS_rlast,
input wire AXI_EXP_SS_rvalid,
output wire AXI_EXP_SS_rready
);
endmodule
\ No newline at end of file