Commit 6172b444 by sakundu

Added SKY130HD FakeStack enablement and the testcases

Signed-off-by: sakundu <sakundu@ucsd.edu>
parent 204e29eb
......@@ -6,4 +6,4 @@ As the ASAP7 enablement does not have memory generators, we use the FakeRAM2.0 m
With this combined enablement, testcases with SRAMs can be synthesized, placed and routed using both proprietary (commercial) tools such as Cadence Genus/Innovus, and open-source tools such as OpenROAD.
The [*./lef*](./lef) directory contains the technology, standard cell and macro lef files, the [*./lib*](./lib/) directory contains the standard cell and macro liberty files and the [*./qrc*](./qrc/) directory contains the qrc technology file.
The [*./lef*](./lef) directory contains the technology, standard cell and macro lef files, the [*./lib*](./lib/) directory contains the standard cell and macro liberty files and the [*./qrc*](./qrc/) directory contains the qrc technology file.
# SKY130HD FakeStack (SKY130HD library, bsg_fakeram memory generation, 9M FkaeStack)
The SKY130HD enablement available in the OpenROAD-flow-script [GitHub repo](https://github.com/The-OpenROAD-Project/OpenROAD-flow-scripts/tree/master/flow/platforms/sky130hd) is a five-metal stack enablement. Memory macro has blockage till metal four so five-metal stack is not enough to route our macro dominant testcases. In this enablement each of the five routing layers and four cut layers has different lef property (.e.g, minimum spacing, width, enclosuer etc.).
Consider the five metal stacks are Ma, Mb, Mc, Md and Me, and this stack configuration is named as 1Ma_1Mb_1Mc_1Md_1Me. We replicate the first four metal layers to genearte the nine-metal layer FakeStack where the configuration is 2Ma_2Mb_2Mc_2Md_1Me. We use this nine-metal layer FakeStack of SKY130HD as our one of the enablement. The [getTechLef.tcl](./lef/genTechLef.tcl) can be used to generate a FakeStack of layer configuration x1Ma_x2Mb_x3Mc_x4Md_1Me, where xi is greater or equal to one.
We use the bsg_fakeram memory generator available in the [bsg_fakeram](https://github.com/jjcherry56/bsg_fakeram) GitHub repo to generate the required SRAMs. The [sky130hd.cfg](./util/sky130hd.cfg) is the configuration file used to generate all the required memories.
With this combined enablement, testcases with SRAMs can be synthesized, placed and routed using both proprietary (commercial) tools such as Cadence Genus/Innovus, and open-source tools such as OpenROAD.
The [*./lef*](./lef) directory contains the technology, standard cell and macro lef files, the [*./lib*](./lib/) directory contains the standard cell and macro liberty files and the [*./qrc*](./qrc/) directory contains the qrc technology file.
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
{
# The process node. This is used to tell cacti what technology to use when
# estimating power, performance and area numbers.
"tech_nm": 130,
# The operating voltage.
"voltage": 1.8,
# String to add in front of every metal layer number for the layer name.
"metalPrefix": "met",
# The pin width for signal pins.
"pinWidth_nm": 460,
# The minimum pin pitch for signal pins (all pins will have a pitch that is a
# multuple of this pitch. The first pin will be a multiple of this pitch from
# the bottom edge of the macro too.
"pinPitch_nm": 460,
# Optional: snap the width and height of the sram to a multiple value.
"snapWidth_nm": 460,
"snapHeight_nm": 1360,
# Flips the pin orientations. Non-fliped assumes metal1 is vertical therefore
# supply pins on metal4 will be horizontal and signal pins will also be on
# metal4. If set to true, supply pins on metal4 will be vertical and signal
# pins will be on metal3.
"flipPins": true,
# List of SRAM configurations (name, width, depth, and banks)
"srams": [
{"name": "fakeram130_256x64", "width": 64, "depth": 256, "banks": 1},
{"name": "fakeram130_256x512", "width": 512, "depth": 256, "banks": 1},
{"name": "fakeram130_256x32", "width": 32, "depth": 256, "banks": 1},
{"name": "fakeram130_256x16", "width": 16, "depth": 256, "banks": 1},
{"name": "fakeram130_64x64", "width": 64, "depth": 64, "banks": 2}
]
}
......@@ -371,7 +371,7 @@ nv_ram_rwsthp_80x15.v
nv_ram_rwsthp_80x17.v
nv_ram_rwsthp_80x72.v
nv_ram_rwsthp_80x9.v
fakeram45_256x64_dp.v
fakeram_256x64_dp.v
-v NV_NVDLA_XXIF_libs.v
# **Synthesis, Place \& Route (SP\&R):**
Here we provide the setup to run SP&R of Ariane design with 133 macros on SKY130HD using commercial and open-source tools. First, we provide the steps for netlist preparation and then discuss the SP&R flow.
- [**SP\&R Flow:**](#spr-flow)
- [**Using Cadence Innovus:**](#using-cadence-innovus)
- [**Using OpenROAD-flow-scripts:**](#using-openroad-flow-scripts)
## **SP\&R Flow:**
We implement the Ariane design on the SKY130HD platform using the proprietary (commercial) tools **Cadence Genus** (Synthesis) and **Cadence Innovus** (P&R), and the open-source tools **Yosys** (Synthesis) and **OpenROAD** (P&R). The required *.lef* and *.lib* files are downloaded from the OpenROAD-flow-scripts (ORFS) [GitHub](https://github.com/The-OpenROAD-Project/OpenROAD-flow-scripts/tree/master/flow/platforms/sky130hd). We use the [fakeram](https://github.com/jjcherry56/bsg_fakeram) generator for the SKY130HD platform to generate the 16-bit (256x16, single-ported SRAM) memory. All the required *.lib* and *.lef* files are copied into the [*Enablements/SKY130HD*](../../../Enablements/SKY130HD/) directory.
### **Using Cadence Innovus:**
All the required scripts are available in the [*./scripts/cadence/*](./scripts/cadence/) directory.
We use an unnamed commercial logic synthesis tool to synthesize the Ariane 133-macro version from Verilog RTL. The synthesized gate-level (standard cells and SRAM macros) netlist is available in [*./netlist/*](./netlist/) directory.
**P\&R:** [run_innovus.tcl](./scripts/cadence/run_invs.tcl) contains the setup for the P&R run using Innvous. It reads the gate-level netlist provided in [*./netlist/*](./netlist/) directory. To launch the P\&R run please use the below command.
```
innovus -64 -init run_invs.tcl -log log/run.log
```
Innovus requires a configuration file to run the macro placement flow. For this we use *proto_design -constraints mp_config.tcl* command. The configuration file [*mp_config.tcl*](./scripts/cadence//mp_config.tcl) is available in the [*./scripts/cadence/*](./scripts/cadence/) directory. Some details of the configuration files are as follows:
1. Provide the memory hierarchy name under the **SEED** section. If you do not provide the memory hierarchy here, then the macro placement constraints (e.g., cell orientation, spacing, etc.) related to that memory may be overlooked.
2. For each macro, valid orientation and spacing rules can be provided under the **MACRO** section. For example, we set valid macro orientation as *R0* for our run, horizontal spacing as *10um*, and vertical spacing as *5um*. Also, when you provide the cell name (ref name, not instance name) add the *isCell=true* option.
Below is the screenshot of the Ariane SP\&R database with 133 memory macros using the Cadence flow.
<img src="./screenshots/Ariane133_Innovus.png" alt="ariane133_cadence" width="400"/>
This script was written and developed by ABKGroup students at UCSD; however, the underlying commands and reports are copyrighted by Cadence. We thank Cadence for granting permission to share our research to help promote and foster the next generation of innovators.
<!--
### **Using OpenROAD-flow-scripts:**
Clone ORFS and build OpenROAD tools following the steps given [here](https://github.com/The-OpenROAD-Project/OpenROAD-flow-scripts). To run SP&R using OpenROAD tools follow the below mentioned steps:
1. Copy [*./scripts/OpenROAD/ariane.tar.gz*](./scripts/OpenROAD/ariane.tar.gz) file to *{ORFS Clone Directory}/OpenROAD-flow-scripts/flow/designs/nangate45* area.
2. Use command *tar -xvf ariane.tar.gz* to untar *ariane.tar.gz*. This will generate *ariane133* directory which contains all the files required to run SP&R using ORFS. The config file contains the *set_dont_touch* (it is called PRESERVE_CELLS in ORFS) for the memory macros.
3. To launch the SP&R job go to the flow directory and use the below command
```
make DESIGN_CONFIG=./designs/nangate45/ariane133/config_hier.mk
```
4. config_hier.mk uses the **RTL-MP** for macro placement. To run macro placement using **Triton Macro Placer** use the below command
```
make DESIGN_CONFIG=./designs/nangate45/ariane133/config.mk
```
Below is a screenshot of the Ariane SP\&R database with 133 memory macros using ORFS (RTL-MP) flow.
<img src="./screenshots/Ariane133_ORFS.png" alt="ariane136_orfs" width="400"/>
-->
#period set in nano-seconds - currently: 4ns = 250 MHz freq
create_clock [get_ports clk_i] -name core_clock -period 4
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
# This script was written and developed by ABKGroup students at UCSD. However, the underlying commands and reports are copyrighted by Cadence.
# We thank Cadence for granting permission to share our research to help promote and foster the next generation of innovators.
set DESIGN ariane
set sdc ../../constraints/${DESIGN}.sdc
# def file with die size and placed IO pins
set floorplan_def ../../def/ariane133_fp.def
#
# Effort level during optimization in syn_generic -physical (or called generic) stage
# possible values are : high, medium or low
set GEN_EFF medium
# Effort level during optimization in syn_map -physical (or called mapping) stage
# possible values are : high, medium or low
set MAP_EFF high
# This script was written and developed by ABKGroup students at UCSD; however, the underlying commands and reports are copyrighted by Cadence.
# We thank Cadence for granting permission to share our research to help promote and foster the next generation of innovators.
puts "VERSION 1.0"
set mem_hier ""
foreach a [dbget [dbget top.insts.cell.name fakeram45_* -p2 ].name ] {
regexp {(.*)(/)([^/]*)} $a c b
lappend mem_hier $b
}
set unique_mem_hier [lsort -unique $mem_hier]
puts "BEGIN SEED"
foreach a $unique_mem_hier {
puts "name=$a util=$util"
}
puts "END SEED"
puts "BEGIN MACRO"
foreach a [dbget top.insts.cell.name fakeram45_* -u] {
puts "name=$a orient={R0} isCell=true minRightSpace=10 minLeftSpace=10 minTopSpace=5 minBottomSpace=5"
}
puts "END MACRO"
puts "BEGIN CONSTRAINT"
puts "END CONSTRAINT"
# This script was written and developed by ABKGroup students at UCSD. However, the underlying commands and reports are copyrighted by Cadence.
# We thank Cadence for granting permission to share our research to help promote and foster the next generation of innovators.
# lib and lef, RC setup
set libdir "../../../../../Enablements/SKY130HD/lib"
set lefdir "../../../../../Enablements/SKY130HD/lef"
set qrcdir "../../../../../Enablements/SKY130HD/qrc"
set_db init_lib_search_path { \
${libdir} \
${lefdir} \
}
set libworst "
${libdir}/sky130_fd_sc_hd__tt_025C_1v80.lib \
${libdir}/fakeram130_256x16.lib \
"
set libbest "
${libdir}/sky130_fd_sc_hd__tt_025C_1v80.lib \
${libdir}/fakeram130_256x16.lib \
"
set lefs "
${lefdir}/9M_li_2Ma_2Mb_2Mc_2Md_1Me.tlef \
${lefdir}/sky130_fd_sc_hd_merged.lef \
${lefdir}/fakeram130_256x16.lef \
"
#set qrc_max "${qrcdir}/NG45.tch"
#set qrc_min "${qrcdir}/NG45.tch"
#
# Ensures proper and consistent library handling between Genus and Innovus
#set_db library_setup_ispatial true
# This script was written and developed by ABKGroup students at UCSD. However, the underlying commands and reports are copyrighted by Cadence.
# We thank Cadence for granting permission to share our research to help promote and foster the next generation of innovators.
create_library_set -name WC_LIB -timing $libworst
create_library_set -name BC_LIB -timing $libbest
#create_opcond -name op_cond_wc -process 1.0 -voltage 0.72 -temperature 125
#create_opcond -name op_cond_bc -process 1.0 -voltage 0.88 -temperature -40
create_timing_condition -name timing_wc -library_sets { WC_LIB }
create_timing_condition -name timing_bc -library_sets { BC_LIB }
create_rc_corner -name Cmax -qrc_tech $qrc_max
create_rc_corner -name Cmin -qrc_tech $qrc_min
create_delay_corner -name WC -early_timing_condition { timing_wc } \
-late_timing_condition { timing_wc } \
-early_rc_corner Cmax \
-late_rc_corner Cmax
create_delay_corner -name BC -early_timing_condition { timing_bc } \
-late_timing_condition { timing_bc } \
-early_rc_corner Cmin \
-late_rc_corner Cmin
create_constraint_mode -name CON -sdc_file $sdc
create_analysis_view -name WC_VIEW -delay_corner WC -constraint_mode CON
create_analysis_view -name BC_VIEW -delay_corner BC -constraint_mode CON
set_analysis_view -setup WC_VIEW -hold BC_VIEW
# This script was written and developed by ABKGroup students at UCSD. However, the underlying commands and reports are copyrighted by Cadence.
# We thank Cadence for granting permission to share our research to help promote and foster the next generation of innovators.
create_library_set -name WC_LIB -timing $libworst
create_library_set -name BC_LIB -timing $libbest
create_rc_corner -name Cmax
create_rc_corner -name Cmin
create_delay_corner -name WC -library_set WC_LIB -rc_corner Cmax
create_delay_corner -name BC -library_set BC_LIB -rc_corner Cmin
create_constraint_mode -name CON -sdc_file $sdc
create_analysis_view -name WC_VIEW -delay_corner WC -constraint_mode CON
create_analysis_view -name BC_VIEW -delay_corner BC -constraint_mode CON
# This script was written and developed by ABKGroup students at UCSD; however, the underlying commands and reports are copyrighted by Cadence.
# We thank Cadence for granting permission to share our research to help promote and foster the next generation of innovators.
##########################################
# Masterplan User Constraint File Template
##########################################
###########################################################
# Syntax Convention: #
# [] means optional #
# <> means filling with real value or name in your design #
# () indicates the unit name for your value #
# | means OR #
# {} is used to enclose a group of names (one or more) #
# ... means more similar items #
###########################################################
###########################################################
# Version section (required on and after Innovus 10.1) #
# If not provided, will be parsed as older format #
# VERSION <N.N> #
# For example: #
###########################################################
VERSION 1.0
######################################################################
# Seed Section (optional) : one single line per seed #
# name=<seedName> [util=<float>] [createFence=true]\ #
# [minWHRatio=<float>] [maxWHRatio=<float>]\ #
# [minFenceToFenceSpace=<(um)>] [minFenceToCoreSpace=<(um)>]\ #
# [minFenceToInsideMacroSpace=<(um)>]\ #
# [minFenceToOutsideMacroSpace=<(um)>]\ #
# [minInsideFenceMacroToMacroSpace=<(um)>]\ #
# [master=<nameOrOtherName>] [cloneOrient={R0|MX|MY|R180}] #
# For example: #
######################################################################
BEGIN SEED
name=i_cache_subsystem/i_icache/sram_block_0__data_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_icache/sram_block_0__data_sram/genblk1_1__i_ram
name=i_cache_subsystem/i_icache/sram_block_0__tag_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_icache/sram_block_1__data_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_icache/sram_block_1__data_sram/genblk1_1__i_ram
name=i_cache_subsystem/i_icache/sram_block_1__tag_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_icache/sram_block_2__data_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_icache/sram_block_2__data_sram/genblk1_1__i_ram
name=i_cache_subsystem/i_icache/sram_block_2__tag_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_icache/sram_block_3__data_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_icache/sram_block_3__data_sram/genblk1_1__i_ram
name=i_cache_subsystem/i_icache/sram_block_3__tag_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_0__data_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_0__data_sram/genblk1_1__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_0__tag_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_1__data_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_1__data_sram/genblk1_1__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_1__tag_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_2__data_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_2__data_sram/genblk1_1__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_2__tag_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_3__data_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_3__data_sram/genblk1_1__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_3__tag_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_4__data_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_4__data_sram/genblk1_1__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_4__tag_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_5__data_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_5__data_sram/genblk1_1__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_5__tag_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_6__data_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_6__data_sram/genblk1_1__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_6__tag_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_7__data_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_7__data_sram/genblk1_1__i_ram
name=i_cache_subsystem/i_nbdcache/sram_block_7__tag_sram/genblk1_0__i_ram
name=i_cache_subsystem/i_nbdcache/valid_dirty_sram/genblk1_0__i_ram
END SEED
######################################################################
# MACRO section syntax : one single line per macro #
# name=<InstOrCell> [minLeftSpace=<(um)>] [minRightSpace=<(um)>]\ #
# [minTopSpace=<(um)>] [minBottomSpace=<(um)>]\ #
# [orient={R0|MX|MY|R180|MX90|R90|R270|MY90}]\ #
# [isCell=true] [minMacroToCoreSpace=<(um)>] #
# For example: #
######################################################################
BEGIN MACRO
name=fakeram45_256x16 orient={R0} isCell=true minRightSpace=10 minLeftSpace=10 minTopSpace=5 minBottomSpace=5
END MACRO
#################################################################################
# relative placement CONSTRAINT section syntax #
# name=<HInstOrGroupOrHM> loc=<T|B|R|L|TL|TR|BL|BR|(x,y)> #
# name=<NewName> members={<Module1> <Module2> <Module3>..} [strength=Soft|Hard] #
# For example: #
#################################################################################
BEGIN CONSTRAINT
END CONSTRAINT
# This script was written and developed by ABKGroup students at UCSD. However, the underlying commands and reports are copyrighted by Cadence.
# We thank Cadence for granting permission to share our research to help promote and foster the next generation of innovators.
#!/bin/tcsh
module unload genus
module load genus/21.1
module unload innovus
module load innovus/21.1
mkdir log -p
genus -overwrite -log log/genus.log -no_gui -files run_genus_iSpatial.tcl
innovus -64 -files run_invs.tcl -overwrite -log log/innovus.log
# This script was written and developed by ABKGroup students at UCSD. However, the underlying commands and reports are copyrighted by Cadence.
# We thank Cadence for granting permission to share our research to help promote and foster the next generation of innovators.
source lib_setup.tcl
source design_setup.tcl
# set the output directories
set OUTPUTS_PATH syn_output
set REPORTS_PATH syn_rpt
set HANDOFF_PATH syn_handoff
if {![file exists ${OUTPUTS_PATH}]} {
file mkdir ${OUTPUTS_PATH}
}
if {![file exists ${REPORTS_PATH}]} {
file mkdir ${REPORTS_PATH}
}
if {![file exists ${HANDOFF_PATH}]} {
file mkdir ${HANDOFF_PATH}
}
#
# set threads
set_db max_cpus_per_server 16
set_db super_thread_servers "localhost"
#
set list_lib "$libworst"
# Target library
set link_library $list_lib
set target_library $list_lib
# set path
set_db hdl_flatten_complex_port true
set_db hdl_record_naming_style %s_%s
set_db auto_ungroup none
set_db library $list_lib
#################################################
# Load Design and Initialize
#################################################
source rtl_list.tcl
foreach rtl_file $rtl_all {
read_hdl -sv $rtl_file
}
elaborate $DESIGN
time_info Elaboration
read_sdc $sdc
init_design
check_design -unresolved
check_timing_intent
# reports the physical layout estimation report from lef and QRC tech file
report_ple > ${REPORTS_PATH}/ple.rpt
# keep hierarchy during synthesis
set_db auto_ungroup none
syn_generic
time_info GENERIC
# generate a summary for the current stage of synthesis
write_hdl -generic > ${HANDOFF_PATH}/${DESIGN}_generic.v
write_reports -directory ${REPORTS_PATH} -tag generic
write_db ${OUTPUTS_PATH}/${DESIGN}_generic.db
syn_map
time_info MAPPED
# generate a summary for the current stage of synthesis
write_reports -directory ${REPORTS_PATH} -tag map
write_db ${OUTPUTS_PATH}/${DESIGN}_map.db
syn_opt
time_info OPT
write_db ${OUTPUTS_PATH}/${DESIGN}_opt.db
##############################################################################
# Write reports
##############################################################################
# summarizes the information, warnings and errors
report_messages > ${REPORTS_PATH}/${DESIGN}_messages.rpt
# generate PPA reports
report_gates > ${REPORTS_PATH}/${DESIGN}_gates.rpt
report_power > ${REPORTS_PATH}/${DESIGN}_power.rpt
report_area > ${REPORTS_PATH}/${DESIGN}_power.rpt
write_reports -directory ${REPORTS_PATH} -tag final
write_sdc >${HANDOFF_PATH}/${DESIGN}.sdc
write_hdl > ${HANDOFF_PATH}/${DESIGN}.v
#write_design -innovus -base_name ${HANDOFF_PATH}/${DESIGN}
exit
# This script was written and developed by ABKGroup students at UCSD. However, the underlying commands and reports are copyrighted by Cadence.
# We thank Cadence for granting permission to share our research to help promote and foster the next generation of innovators.
source lib_setup.tcl
source design_setup.tcl
setDesignMode -process 130
read_mmmc mmmc_iSpatial_setup.tcl
# set the output directories
set OUTPUTS_PATH syn_output
set REPORTS_PATH syn_rpt
set HANDOFF_PATH syn_handoff
if {![file exists ${OUTPUTS_PATH}]} {
file mkdir ${OUTPUTS_PATH}
}
if {![file exists ${REPORTS_PATH}]} {
file mkdir ${REPORTS_PATH}
}
if {![file exists ${HANDOFF_PATH}]} {
file mkdir ${HANDOFF_PATH}
}
#
# set threads
set_db max_cpus_per_server 16
set_db super_thread_servers "localhost"
#
set list_lib "$libworst"
set_db invs_temp_dir ${OUTPUTS_PATH}/invs_tmp_dir
read_physical -lefs $lefs
# Target library
set link_library $list_lib
set target_library $list_lib
# set path
set_db auto_ungroup none
#set_db library $list_lib
#################################################
# Load Design and Initialize
#################################################
source rtl_list.tcl
foreach rtl_file $rtl_all {
read_hdl -sv $rtl_file
}
elaborate $DESIGN
time_info Elaboration
#read_sdc $sdc
init_design
check_design -unresolved
check_timing_intent
# reports the physical layout estimation report from lef and QRC tech file
report_ple > ${REPORTS_PATH}/ple.rpt
###############################################
# Read DEF
###############################################
read_def $floorplan_def
check_floorplan -detailed
# keep hierarchy during synthesis
set_db auto_ungroup none
syn_generic -physical
time_info GENERIC
# generate a summary for the current stage of synthesis
write_reports -directory ${REPORTS_PATH} -tag generic
write_db ${OUTPUTS_PATH}/${DESIGN}_generic.db
syn_map -physical
time_info MAPPED
# generate a summary for the current stage of synthesis
write_reports -directory ${REPORTS_PATH} -tag map
write_db ${OUTPUTS_PATH}/${DESIGN}_map.db
syn_opt -spatial
time_info OPT
write_db ${OUTPUTS_PATH}/${DESIGN}_opt.db
##############################################################################
# Write reports
##############################################################################
# summarizes the information, warnings and errors
report_messages > ${REPORTS_PATH}/${DESIGN}_messages.rpt
# generate PPA reports
report_gates > ${REPORTS_PATH}/${DESIGN}_gates.rpt
report_power > ${REPORTS_PATH}/${DESIGN}_power.rpt
report_area > ${REPORTS_PATH}/${DESIGN}_power.rpt
write_reports -directory ${REPORTS_PATH} -tag final
#write_sdc >${HANDOFF_PATH}/${DESIGN}.sdc
#write_hdl > ${HANDOFF_PATH}/${DESIGN}.v
write_design -innovus -base_name ${HANDOFF_PATH}/${DESIGN}
exit
# This script was written and developed by ABKGroup students at UCSD. However, the underlying commands and reports are copyrighted by Cadence.
# We thank Cadence for granting permission to share our research to help promote and foster the next generation of innovators.
source lib_setup.tcl
source design_setup.tcl
source mmmc_setup.tcl
setMultiCpuUsage -localCpu 16
set util 0.3
set netlist "./syn_handoff/$DESIGN.v"
set sdc "./syn_handoff/$DESIGN.sdc"
set site "unithd"
set rptDir summaryReport/
set encDir enc/
if {![file exists $rptDir/]} {
exec mkdir $rptDir/
}
if {![file exists $encDir/]} {
exec mkdir $encDir/
}
# default settings
set init_pwr_net VDD
set init_gnd_net VSS
# default settings
set init_verilog "$netlist"
set init_design_netlisttype "Verilog"
set init_design_settop 1
set init_top_cell "$DESIGN"
set init_lef_file "$lefs"
# MCMM setup
init_design -setup {WC_VIEW} -hold {BC_VIEW}
set_power_analysis_mode -leakage_power_view WC_VIEW -dynamic_power_view WC_VIEW
set_interactive_constraint_modes {CON}
setDesignMode -process 130
clearGlobalNets
globalNetConnect VDD -type pgpin -pin VDD -inst * -override
globalNetConnect VSS -type pgpin -pin VSS -inst * -override
globalNetConnect VDD -type tiehi -inst * -override
globalNetConnect VSS -type tielo -inst * -override
setOptMode -powerEffort low -leakageToDynamicRatio 0.5
setGenerateViaMode -auto true
generateVias
# basic path groups
createBasicPathGroups -expanded
## Generate the floorplan ##
#floorPlan -r 1.0 $util 10 10 10 10
defIn $floorplan_def
## Macro Placement ##
#redirect mp_config.tcl {source gen_mp_config.tcl}
#proto_design -constraints mp_config.tcl
addHaloToBlock -allMacro 5 5 5 5
place_design -concurrent_macros
refine_macro_place
saveDesign ${encDir}/${DESIGN}_floorplan.enc
## Creating Pin Blcokage for lower and upper pin layers ##
createPinBlkg -name Layer_1 -layer {met2 met3 met9} -edge 0
createPinBlkg -name side_top -edge 1
createPinBlkg -name side_right -edge 2
createPinBlkg -name side_bottom -edge 3
setPlaceMode -place_detail_legalization_inst_gap 1
setFillerMode -fitGap true
setDesignMode -topRoutingLayer 9
setDesignMode -bottomRoutingLayer 2
place_opt_design -out_dir $rptDir -prefix place
saveDesign $encDir/${DESIGN}_placed.enc
set_ccopt_property post_conditioning_enable_routing_eco 1
set_ccopt_property -cts_def_lock_clock_sinks_after_routing true
setOptMode -unfixClkInstForOpt false
create_ccopt_clock_tree_spec
ccopt_design
set_interactive_constraint_modes [all_constraint_modes -active]
set_propagated_clock [all_clocks]
set_clock_propagation propagated
# ------------------------------------------------------------------------------
# Routing
# ------------------------------------------------------------------------------
setNanoRouteMode -drouteVerboseViolationSummary 1
setNanoRouteMode -routeWithSiDriven true
setNanoRouteMode -routeWithTimingDriven true
setNanoRouteMode -routeUseAutoVia true
##Recommended by lib owners
# Prevent router modifying M1 pins shapes
setNanoRouteMode -routeWithViaInPin "1:1"
setNanoRouteMode -routeWithViaOnlyForStandardCellPin "1:1"
## limit VIAs to ongrid only for VIA1 (S1)
setNanoRouteMode -drouteOnGridOnly "via 1:1"
setNanoRouteMode -drouteAutoStop false
setNanoRouteMode -drouteExpAdvancedMarFix true
setNanoRouteMode -routeExpAdvancedTechnology true
#SM suggestion for solving long extraction runtime during GR
setNanoRouteMode -grouteExpWithTimingDriven false
routeDesign
#route_opt_design
saveDesign ${encDir}/${DESIGN}_route.enc
defOut -netlist -floorplan -routing ${DESIGN}_route.def
summaryReport -noHtml -outfile summaryReport/post_route.sum
saveDesign ${encDir}/${DESIGN}.enc
defOut -netlist -floorplan -routing ${DESIGN}.def
exit
# **Synthesis, Place \& Route (SP\&R):**
Here we provide the setup to run SP&R of Ariane design with 136 macros on SKY130HD using commercial and open-source tools.
- [**SP\&R Flow**](#spr-flow)
- [**Cadence tools**](#using-cadence-genus-and-innovus)
- [**OpenROAD tools**](#using-openroad-flow-scripts)
## **SP\&R Flow:**
We implement Ariane design with [136 macros](../../../Testcases/ariane136/) on the SKY130HD platform using the proprietary (commercial) tools **Cadence Genus** (Synthesis) and **Cadence Innovus** (P&R), and the open-source tools **Yosys** (Synthesis) and **OpenROAD** (P&R). The required *.lef* and *.lib* files are downloaded from the OpenROAD-flow-scripts (ORFS) [GitHub](https://github.com/The-OpenROAD-Project/OpenROAD-flow-scripts/tree/master/flow/platforms/sky130hd). We use the [fakeram](https://github.com/jjcherry56/bsg_fakeram) generator for the SKY130HD platform to generate the 16-bit (256x16, single-ported SRAM) memory. All the required *.lib* and *.lef* files are available in the [*Enablements/SKY130HD*](../../../Enablements/SKY130HD/) directory.
### **Using Cadence Genus and Innovus:**
All the required scripts are available in the [*./scripts/cadence/*](./scripts/cadence/) directory.
**Synthesis:** [run_genus.tcl](./scripts/cadence/run_genus.tcl) contains the setup for synthesis using Genus. It reads the .sv files based on the list in [*./scripts/cadence/rtl_list.tcl*](./scripts/cadence/rtl_list.tcl) (changing the order of the file may cause errors). The timing constraints are provided in [*./constrains/ariane.sdc*](./constraints/ariane.sdc) file. To launch the synthesis run please use the below command
```
genus -overwrite -log log/genus.log -no_gui -files run_genus.tcl
```
We also generate a synthesized netlist, which is available in the [*./netlist/*](./netlist/) directory.
**P\&R:** [run_innovus.tcl](./scripts/cadence/run_invs.tcl) contains the setup for the P&R run using Innvous. It reads the netlist provided in [*./netlist/*](./netlist/) directory. To launch the P\&R run please use the below command.
```
innovus -64 -init run_invs.tcl -log log/run.log
```
Innovus requires a configuration file to run the macro placement flow. For this we use *proto_design -constraints mp_config.tcl* command. The configuration file [*mp_config.tcl*](./scripts/cadence/mp_config.tcl) is available in the *./scripts/cadence/* directory. Some details of the configuration files are as follows.
1. Provide the memory hierarchy name under the **SEED** section. If you do not provide the memory hierarchy here, then the macro placement constraints (e.g., cell orientation, spacing, etc.) related to that memory may be overlooked.
2. For each macro, valid orientation and spacing rules can be provided under the **MACRO** section. For example, we set valid macro orientation as *R0* for our run, horizontal spacing as *10um*, and vertical spacing as *5um*. Also, when you provide the cell name (ref name, not instance name) add the *isCell=true* option.
Below is the screenshot of the Ariane SP\&R database with 136 memory macros using Cadence flow.
<img src="./screenshots/Ariane136_Innovus_Genus.png" alt="ariane136_cadence" width="400"/>
This script was written and developed by ABKGroup students at UCSD; however, the underlying commands and reports are copyrighted by Cadence. We thank Cadence for granting permission to share our research to help promote and foster the next generation of innovators.
<!--
### **Using OpenROAD-flow-scripts:**
Clone ORFS and build OpenROAD tools following the steps given [here](https://github.com/The-OpenROAD-Project/OpenROAD-flow-scripts). To run SP&R using OpenROAD tools follow the below mentioned steps:
1. Copy [*./scripts/OpenROAD/ariane.tar.gz*](./scripts/OpenROAD/ariane.tar.gz) file to *{ORFS Clone Directory}/OpenROAD-flow-scripts/flow/designs/nangate45* area.
2. Use command *tar -xvf ariane.tar.gz* to untar *ariane.tar.gz*. This will generate *ariane136* directory which contains all the files required to run SP&R using ORFS.
3. To launch the SP&R job go to the flow directory and use the below command
```
make DESIGN_CONFIG=./designs/nangate45/ariane136/config_hier.mk
```
4. config_hier.mk uses the **RTL-MP** (RTL Macro Placer) for macro placement. If you wish to run macro placement using the older **Triton Macro Placer**, please use the below command:
```
make DESIGN_CONFIG=./designs/nangate45/ariane136/config.mk
```
Below is the screenshot of the Ariane SP\&R database with 136 memory macros using the ORFS (RTL-MP) flow.
<img src="./screenshots/Ariane136_ORFS_SPNR.png" alt="ariane136_orfs" width="400"/>
-->
\ No newline at end of file
# ####################################################################
# Created by Genus(TM) Synthesis Solution 21.10-p002_1 on Fri Jul 01 20:44:40 PDT 2022
# ####################################################################
set sdc_version 2.0
set_units -capacitance 1000fF
set_units -time 1000ps
# Set the current design
current_design ariane
create_clock -name "core_clock" -period 8.0 -waveform {0.0 4.0} [get_ports clk_i]
set_clock_gating_check -setup 0.0
set_wire_load_mode "top"
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
//
// Author: Matthias Baer <baermatt@student.ethz.ch>
// Author: Igor Loi <igor.loi@unibo.it>
// Author: Andreas Traber <atraber@student.ethz.ch>
// Author: Lukas Mueller <lukasmue@student.ethz.ch>
// Author: Florian Zaruba <zaruabf@iis.ee.ethz.ch>
//
// Date: 19.03.2017
// Description: Ariane ALU based on RI5CY's ALU
import ariane_pkg::*;
module alu (
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
input fu_data_t fu_data_i,
output logic [63:0] result_o,
output logic alu_branch_res_o
);
logic [63:0] operand_a_rev;
logic [31:0] operand_a_rev32;
logic [64:0] operand_b_neg;
logic [65:0] adder_result_ext_o;
logic less; // handles both signed and unsigned forms
// bit reverse operand_a for left shifts and bit counting
generate
genvar k;
for(k = 0; k < 64; k++)
assign operand_a_rev[k] = fu_data_i.operand_a[63-k];
for (k = 0; k < 32; k++)
assign operand_a_rev32[k] = fu_data_i.operand_a[31-k];
endgenerate
// ------
// Adder
// ------
logic adder_op_b_negate;
logic adder_z_flag;
logic [64:0] adder_in_a, adder_in_b;
logic [63:0] adder_result;
always_comb begin
adder_op_b_negate = 1'b0;
unique case (fu_data_i.operator)
// ADDER OPS
EQ, NE,
SUB, SUBW: adder_op_b_negate = 1'b1;
default: ;
endcase
end
// prepare operand a
assign adder_in_a = {fu_data_i.operand_a, 1'b1};
// prepare operand b
assign operand_b_neg = {fu_data_i.operand_b, 1'b0} ^ {65{adder_op_b_negate}};
assign adder_in_b = operand_b_neg ;
// actual adder
assign adder_result_ext_o = $unsigned(adder_in_a) + $unsigned(adder_in_b);
assign adder_result = adder_result_ext_o[64:1];
assign adder_z_flag = ~|adder_result;
// get the right branch comparison result
always_comb begin : branch_resolve
// set comparison by default
alu_branch_res_o = 1'b1;
case (fu_data_i.operator)
EQ: alu_branch_res_o = adder_z_flag;
NE: alu_branch_res_o = ~adder_z_flag;
LTS, LTU: alu_branch_res_o = less;
GES, GEU: alu_branch_res_o = ~less;
default: alu_branch_res_o = 1'b1;
endcase
end
// ---------
// Shifts
// ---------
// TODO: this can probably optimized significantly
logic shift_left; // should we shift left
logic shift_arithmetic;
logic [63:0] shift_amt; // amount of shift, to the right
logic [63:0] shift_op_a; // input of the shifter
logic [31:0] shift_op_a32; // input to the 32 bit shift operation
logic [63:0] shift_result;
logic [31:0] shift_result32;
logic [64:0] shift_right_result;
logic [32:0] shift_right_result32;
logic [63:0] shift_left_result;
logic [31:0] shift_left_result32;
assign shift_amt = fu_data_i.operand_b;
assign shift_left = (fu_data_i.operator == SLL) | (fu_data_i.operator == SLLW);
assign shift_arithmetic = (fu_data_i.operator == SRA) | (fu_data_i.operator == SRAW);
// right shifts, we let the synthesizer optimize this
logic [64:0] shift_op_a_64;
logic [32:0] shift_op_a_32;
// choose the bit reversed or the normal input for shift operand a
assign shift_op_a = shift_left ? operand_a_rev : fu_data_i.operand_a;
assign shift_op_a32 = shift_left ? operand_a_rev32 : fu_data_i.operand_a[31:0];
assign shift_op_a_64 = { shift_arithmetic & shift_op_a[63], shift_op_a};
assign shift_op_a_32 = { shift_arithmetic & shift_op_a[31], shift_op_a32};
assign shift_right_result = $unsigned($signed(shift_op_a_64) >>> shift_amt[5:0]);
assign shift_right_result32 = $unsigned($signed(shift_op_a_32) >>> shift_amt[4:0]);
// bit reverse the shift_right_result for left shifts
genvar j;
generate
for(j = 0; j < 64; j++)
assign shift_left_result[j] = shift_right_result[63-j];
for(j = 0; j < 32; j++)
assign shift_left_result32[j] = shift_right_result32[31-j];
endgenerate
assign shift_result = shift_left ? shift_left_result : shift_right_result[63:0];
assign shift_result32 = shift_left ? shift_left_result32 : shift_right_result32[31:0];
// ------------
// Comparisons
// ------------
always_comb begin
logic sgn;
sgn = 1'b0;
if ((fu_data_i.operator == SLTS) ||
(fu_data_i.operator == LTS) ||
(fu_data_i.operator == GES))
sgn = 1'b1;
less = ($signed({sgn & fu_data_i.operand_a[63], fu_data_i.operand_a}) < $signed({sgn & fu_data_i.operand_b[63], fu_data_i.operand_b}));
end
// -----------
// Result MUX
// -----------
always_comb begin
result_o = '0;
unique case (fu_data_i.operator)
// Standard Operations
ANDL: result_o = fu_data_i.operand_a & fu_data_i.operand_b;
ORL: result_o = fu_data_i.operand_a | fu_data_i.operand_b;
XORL: result_o = fu_data_i.operand_a ^ fu_data_i.operand_b;
// Adder Operations
ADD, SUB: result_o = adder_result;
// Add word: Ignore the upper bits and sign extend to 64 bit
ADDW, SUBW: result_o = {{32{adder_result[31]}}, adder_result[31:0]};
// Shift Operations
SLL,
SRL, SRA: result_o = shift_result;
// Shifts 32 bit
SLLW,
SRLW, SRAW: result_o = {{32{shift_result32[31]}}, shift_result32[31:0]};
// Comparison Operations
SLTS, SLTU: result_o = {63'b0, less};
default: ; // default case to suppress unique warning
endcase
end
endmodule
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
//
// Author: Florian Zaruba, ETH Zurich
// Date: 15.09.2018
// Description: Combinatorial AMO unit
module amo_alu (
// AMO interface
input ariane_pkg::amo_t amo_op_i,
input logic [63:0] amo_operand_a_i,
input logic [63:0] amo_operand_b_i,
output logic [63:0] amo_result_o // result of atomic memory operation
);
logic [64:0] adder_sum;
logic [64:0] adder_operand_a, adder_operand_b;
assign adder_sum = adder_operand_a + adder_operand_b;
always_comb begin
adder_operand_a = $signed(amo_operand_a_i);
adder_operand_b = $signed(amo_operand_b_i);
amo_result_o = amo_operand_b_i;
unique case (amo_op_i)
// the default is to output operand_b
ariane_pkg::AMO_SC:;
ariane_pkg::AMO_SWAP:;
ariane_pkg::AMO_ADD: amo_result_o = adder_sum[63:0];
ariane_pkg::AMO_AND: amo_result_o = amo_operand_a_i & amo_operand_b_i;
ariane_pkg::AMO_OR: amo_result_o = amo_operand_a_i | amo_operand_b_i;
ariane_pkg::AMO_XOR: amo_result_o = amo_operand_a_i ^ amo_operand_b_i;
ariane_pkg::AMO_MAX: begin
adder_operand_b = -$signed(amo_operand_b_i);
amo_result_o = adder_sum[64] ? amo_operand_b_i : amo_operand_a_i;
end
ariane_pkg::AMO_MIN: begin
adder_operand_b = -$signed(amo_operand_b_i);
amo_result_o = adder_sum[64] ? amo_operand_a_i : amo_operand_b_i;
end
ariane_pkg::AMO_MAXU: begin
adder_operand_a = $unsigned(amo_operand_a_i);
adder_operand_b = -$unsigned(amo_operand_b_i);
amo_result_o = adder_sum[64] ? amo_operand_b_i : amo_operand_a_i;
end
ariane_pkg::AMO_MINU: begin
adder_operand_a = $unsigned(amo_operand_a_i);
adder_operand_b = -$unsigned(amo_operand_b_i);
amo_result_o = adder_sum[64] ? amo_operand_a_i : amo_operand_b_i;
end
default: amo_result_o = '0;
endcase
end
endmodule
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
//
// Author: Florian Zaruba, ETH Zurich
// Date: 20.09.2018
// Description: Buffers AMO requests
// This unit buffers an atomic memory operations for the cache subsyste.
// Furthermore it handles interfacing with the commit stage
module amo_buffer (
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
input logic flush_i, // pipeline flush
input logic valid_i, // AMO is valid
output logic ready_o, // AMO unit is ready
input ariane_pkg::amo_t amo_op_i, // AMO Operation
input logic [63:0] paddr_i, // physical address of store which needs to be placed in the queue
input logic [63:0] data_i, // data which is placed in the queue
input logic [1:0] data_size_i, // type of request we are making (e.g.: bytes to write)
// D$
output ariane_pkg::amo_req_t amo_req_o, // request to cache subsytem
input ariane_pkg::amo_resp_t amo_resp_i, // response from cache subsystem
// Auxiliary signals
input logic amo_valid_commit_i, // We have a vaild AMO in the commit stage
input logic no_st_pending_i // there is currently no store pending anymore
);
logic flush_amo_buffer;
logic amo_valid;
typedef struct packed {
ariane_pkg::amo_t op;
logic [63:0] paddr;
logic [63:0] data;
logic [1:0] size;
} amo_op_t ;
amo_op_t amo_data_in, amo_data_out;
// validate this request as soon as all stores have drained and the AMO is in the commit stage
assign amo_req_o.req = no_st_pending_i & amo_valid_commit_i & amo_valid;
assign amo_req_o.amo_op = amo_data_out.op;
assign amo_req_o.size = amo_data_out.size;
assign amo_req_o.operand_a = amo_data_out.paddr;
assign amo_req_o.operand_b = amo_data_out.data;
assign amo_data_in.op = amo_op_i;
assign amo_data_in.data = data_i;
assign amo_data_in.paddr = paddr_i;
assign amo_data_in.size = data_size_i;
// only flush if we are currently not committing the AMO
// e.g.: it is not speculative anymore
assign flush_amo_buffer = flush_i & !amo_valid_commit_i;
fifo_v2 #(
.DEPTH ( 1 ),
.ALM_EMPTY_TH ( 0 ),
.ALM_FULL_TH ( 0 ),
.dtype ( amo_op_t )
) i_amo_fifo (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i ( flush_amo_buffer ),
.testmode_i ( 1'b0 ),
.full_o ( amo_valid ),
.empty_o ( ready_o ),
.alm_full_o ( ), // left open
.alm_empty_o ( ), // left open
.data_i ( amo_data_in ),
.push_i ( valid_i ),
.data_o ( amo_data_out ),
.pop_i ( amo_resp_i.ack )
);
endmodule
\ No newline at end of file
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
//
// Florian Zaruba <zarubaf@iis.ee.ethz.ch>
module apb_to_reg (
input logic clk_i,
input logic rst_ni,
input logic penable_i,
input logic pwrite_i,
input logic [31:0] paddr_i,
input logic psel_i,
input logic [31:0] pwdata_i,
output logic [31:0] prdata_o,
output logic pready_o,
output logic pslverr_o,
REG_BUS.out reg_o
);
always_comb begin
reg_o.addr = paddr_i;
reg_o.write = pwrite_i;
reg_o.wdata = pwdata_i;
reg_o.wstrb = '1;
reg_o.valid = psel_i & penable_i;
pready_o = reg_o.ready;
pslverr_o = reg_o.error;
prdata_o = reg_o.rdata;
end
endmodule
/* Copyright 2018 ETH Zurich and University of Bologna.
* Copyright and related rights are licensed under the Solderpad Hardware
* License, Version 0.51 (the “License”); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
* or agreed to in writing, software, hardware and materials distributed under
* this 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.
*
* File: ariane_axi_pkg.sv
* Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
* Date: 17.8.2018
*
* Description: Contains Ariane's AXI ports, does not contain user ports
*/
package ariane_axi;
// used in axi_adapter.sv
typedef enum logic { SINGLE_REQ, CACHE_LINE_REQ } ad_req_t;
// 4 is recommended by AXI standard, so lets stick to it, do not change
localparam IdWidth = 4;
localparam UserWidth = 1;
localparam AddrWidth = 64;
localparam DataWidth = 64;
localparam StrbWidth = DataWidth / 8;
typedef logic [IdWidth-1:0] id_t;
typedef logic [AddrWidth-1:0] addr_t;
typedef logic [DataWidth-1:0] data_t;
typedef logic [StrbWidth-1:0] strb_t;
typedef logic [UserWidth-1:0] user_t;
// AW Channel
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
axi_pkg::atop_t atop;
} aw_chan_t;
// W Channel
typedef struct packed {
data_t data;
strb_t strb;
logic last;
} w_chan_t;
// B Channel
typedef struct packed {
id_t id;
axi_pkg::resp_t resp;
} b_chan_t;
// AR Channel
typedef struct packed {
id_t id;
addr_t addr;
axi_pkg::len_t len;
axi_pkg::size_t size;
axi_pkg::burst_t burst;
logic lock;
axi_pkg::cache_t cache;
axi_pkg::prot_t prot;
axi_pkg::qos_t qos;
axi_pkg::region_t region;
} ar_chan_t;
// R Channel
typedef struct packed {
id_t id;
data_t data;
axi_pkg::resp_t resp;
logic last;
} r_chan_t;
typedef struct packed {
aw_chan_t aw;
logic aw_valid;
w_chan_t w;
logic w_valid;
logic b_ready;
ar_chan_t ar;
logic ar_valid;
logic r_ready;
} req_t;
typedef struct packed {
logic aw_ready;
logic ar_ready;
logic w_ready;
logic b_valid;
b_chan_t b;
logic r_valid;
r_chan_t r;
} resp_t;
endpackage
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
//
// Engineer: Francesco Conti - f.conti@unibo.it
//
// Additional contributions by:
// Markus Wegmann - markus.wegmann@technokrat.ch
//
// Design Name: RISC-V register file
// Project Name: zero-riscy
// Language: SystemVerilog
//
// Description: Register file with 31 or 15x 32 bit wide registers.
// Register 0 is fixed to 0. This register file is based on
// flip flops.
//
module ariane_regfile #(
parameter int unsigned DATA_WIDTH = 32,
parameter int unsigned NR_READ_PORTS = 2,
parameter int unsigned NR_WRITE_PORTS = 2,
parameter bit ZERO_REG_ZERO = 0
)(
// clock and reset
input logic clk_i,
input logic rst_ni,
// disable clock gates for testing
input logic test_en_i,
// read port
input logic [NR_READ_PORTS-1:0][4:0] raddr_i,
output logic [NR_READ_PORTS-1:0][DATA_WIDTH-1:0] rdata_o,
// write port
input logic [NR_WRITE_PORTS-1:0][4:0] waddr_i,
input logic [NR_WRITE_PORTS-1:0][DATA_WIDTH-1:0] wdata_i,
input logic [NR_WRITE_PORTS-1:0] we_i
);
localparam ADDR_WIDTH = 5;
localparam NUM_WORDS = 2**ADDR_WIDTH;
logic [NUM_WORDS-1:0][DATA_WIDTH-1:0] mem;
logic [NR_WRITE_PORTS-1:0][NUM_WORDS-1:0] we_dec;
always_comb begin : we_decoder
for (int unsigned j = 0; j < NR_WRITE_PORTS; j++) begin
for (int unsigned i = 0; i < NUM_WORDS; i++) begin
if (waddr_i[j] == i)
we_dec[j][i] = we_i[j];
else
we_dec[j][i] = 1'b0;
end
end
end
// loop from 1 to NUM_WORDS-1 as R0 is nil
always_ff @(posedge clk_i, negedge rst_ni) begin : register_write_behavioral
if (~rst_ni) begin
mem <= '{default: '0};
end else begin
for (int unsigned j = 0; j < NR_WRITE_PORTS; j++) begin
for (int unsigned i = 0; i < NUM_WORDS; i++) begin
if (we_dec[j][i]) begin
mem[i] <= wdata_i[j];
end
end
if (ZERO_REG_ZERO) begin
mem[0] <= '0;
end
end
end
end
for (genvar i = 0; i < NR_READ_PORTS; i++) begin
assign rdata_o[i] = mem[raddr_i[i]];
end
endmodule
// Copyright 2014-2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the “License”); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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 axi2apb_wrap #(
parameter int unsigned AXI_ADDR_WIDTH = 32,
parameter int unsigned AXI_DATA_WIDTH = 32,
parameter int unsigned AXI_USER_WIDTH = 6,
parameter int unsigned AXI_ID_WIDTH = 6,
parameter int unsigned APB_ADDR_WIDTH = 32,
parameter int unsigned APB_DATA_WIDTH = 32
)(
input logic clk_i,
input logic rst_ni,
input logic test_en_i,
AXI_BUS.Slave axi_slave,
APB_BUS.Master apb_master
);
// ----------------
// AXI2APB WRAPER
// ----------------
generate if (AXI_DATA_WIDTH == APB_DATA_WIDTH) begin
axi2apb #(
.AXI4_ADDRESS_WIDTH ( AXI_ADDR_WIDTH ),
.AXI4_RDATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI4_WDATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI4_ID_WIDTH ( AXI_ID_WIDTH ),
.AXI4_USER_WIDTH ( AXI_USER_WIDTH ),
.BUFF_DEPTH_SLAVE ( 2 ),
.APB_ADDR_WIDTH ( APB_ADDR_WIDTH )
) axi2apb_i (
.ACLK ( clk_i ),
.ARESETn ( rst_ni ),
.test_en_i ( test_en_i ),
.AWID_i ( axi_slave.aw_id ),
.AWADDR_i ( axi_slave.aw_addr ),
.AWLEN_i ( axi_slave.aw_len ),
.AWSIZE_i ( axi_slave.aw_size ),
.AWBURST_i ( axi_slave.aw_burst ),
.AWLOCK_i ( axi_slave.aw_lock ),
.AWCACHE_i ( axi_slave.aw_cache ),
.AWPROT_i ( axi_slave.aw_prot ),
.AWREGION_i ( axi_slave.aw_region ),
.AWUSER_i ( axi_slave.aw_user ),
.AWQOS_i ( axi_slave.aw_qos ),
.AWVALID_i ( axi_slave.aw_valid ),
.AWREADY_o ( axi_slave.aw_ready ),
.WDATA_i ( axi_slave.w_data ),
.WSTRB_i ( axi_slave.w_strb ),
.WLAST_i ( axi_slave.w_last ),
.WUSER_i ( axi_slave.w_user ),
.WVALID_i ( axi_slave.w_valid ),
.WREADY_o ( axi_slave.w_ready ),
.BID_o ( axi_slave.b_id ),
.BRESP_o ( axi_slave.b_resp ),
.BVALID_o ( axi_slave.b_valid ),
.BUSER_o ( axi_slave.b_user ),
.BREADY_i ( axi_slave.b_ready ),
.ARID_i ( axi_slave.ar_id ),
.ARADDR_i ( axi_slave.ar_addr ),
.ARLEN_i ( axi_slave.ar_len ),
.ARSIZE_i ( axi_slave.ar_size ),
.ARBURST_i ( axi_slave.ar_burst ),
.ARLOCK_i ( axi_slave.ar_lock ),
.ARCACHE_i ( axi_slave.ar_cache ),
.ARPROT_i ( axi_slave.ar_prot ),
.ARREGION_i ( axi_slave.ar_region ),
.ARUSER_i ( axi_slave.ar_user ),
.ARQOS_i ( axi_slave.ar_qos ),
.ARVALID_i ( axi_slave.ar_valid ),
.ARREADY_o ( axi_slave.ar_ready ),
.RID_o ( axi_slave.r_id ),
.RDATA_o ( axi_slave.r_data ),
.RRESP_o ( axi_slave.r_resp ),
.RLAST_o ( axi_slave.r_last ),
.RUSER_o ( axi_slave.r_user ),
.RVALID_o ( axi_slave.r_valid ),
.RREADY_i ( axi_slave.r_ready ),
.PENABLE ( apb_master.penable ),
.PWRITE ( apb_master.pwrite ),
.PADDR ( apb_master.paddr ),
.PSEL ( apb_master.psel ),
.PWDATA ( apb_master.pwdata ),
.PRDATA ( apb_master.prdata ),
.PREADY ( apb_master.pready ),
.PSLVERR ( apb_master.pslverr )
);
end else if (AXI_DATA_WIDTH == 64 && APB_DATA_WIDTH == 32) begin
axi2apb_64_32 #(
.AXI4_ADDRESS_WIDTH ( AXI_ADDR_WIDTH ),
.AXI4_RDATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI4_WDATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI4_ID_WIDTH ( AXI_ID_WIDTH ),
.AXI4_USER_WIDTH ( AXI_USER_WIDTH ),
.BUFF_DEPTH_SLAVE ( 2 ),
.APB_ADDR_WIDTH ( APB_ADDR_WIDTH )
) axi2apb_i (
.ACLK ( clk_i ),
.ARESETn ( rst_ni ),
.test_en_i ( test_en_i ),
.AWID_i ( axi_slave.aw_id ),
.AWADDR_i ( axi_slave.aw_addr ),
.AWLEN_i ( axi_slave.aw_len ),
.AWSIZE_i ( axi_slave.aw_size ),
.AWBURST_i ( axi_slave.aw_burst ),
.AWLOCK_i ( axi_slave.aw_lock ),
.AWCACHE_i ( axi_slave.aw_cache ),
.AWPROT_i ( axi_slave.aw_prot ),
.AWREGION_i ( axi_slave.aw_region ),
.AWUSER_i ( axi_slave.aw_user ),
.AWQOS_i ( axi_slave.aw_qos ),
.AWVALID_i ( axi_slave.aw_valid ),
.AWREADY_o ( axi_slave.aw_ready ),
.WDATA_i ( axi_slave.w_data ),
.WSTRB_i ( axi_slave.w_strb ),
.WLAST_i ( axi_slave.w_last ),
.WUSER_i ( axi_slave.w_user ),
.WVALID_i ( axi_slave.w_valid ),
.WREADY_o ( axi_slave.w_ready ),
.BID_o ( axi_slave.b_id ),
.BRESP_o ( axi_slave.b_resp ),
.BVALID_o ( axi_slave.b_valid ),
.BUSER_o ( axi_slave.b_user ),
.BREADY_i ( axi_slave.b_ready ),
.ARID_i ( axi_slave.ar_id ),
.ARADDR_i ( axi_slave.ar_addr ),
.ARLEN_i ( axi_slave.ar_len ),
.ARSIZE_i ( axi_slave.ar_size ),
.ARBURST_i ( axi_slave.ar_burst ),
.ARLOCK_i ( axi_slave.ar_lock ),
.ARCACHE_i ( axi_slave.ar_cache ),
.ARPROT_i ( axi_slave.ar_prot ),
.ARREGION_i ( axi_slave.ar_region ),
.ARUSER_i ( axi_slave.ar_user ),
.ARQOS_i ( axi_slave.ar_qos ),
.ARVALID_i ( axi_slave.ar_valid ),
.ARREADY_o ( axi_slave.ar_ready ),
.RID_o ( axi_slave.r_id ),
.RDATA_o ( axi_slave.r_data ),
.RRESP_o ( axi_slave.r_resp ),
.RLAST_o ( axi_slave.r_last ),
.RUSER_o ( axi_slave.r_user ),
.RVALID_o ( axi_slave.r_valid ),
.RREADY_i ( axi_slave.r_ready ),
.PENABLE ( apb_master.penable ),
.PWRITE ( apb_master.pwrite ),
.PADDR ( apb_master.paddr ),
.PSEL ( apb_master.psel ),
.PWDATA ( apb_master.pwdata ),
.PRDATA ( apb_master.prdata ),
.PREADY ( apb_master.pready ),
.PSLVERR ( apb_master.pslverr )
);
end
endgenerate
endmodule
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
// Davide Rossi <davide.rossi@unibo.it>
module axi_ar_buffer #(
parameter int ID_WIDTH = -1,
parameter int ADDR_WIDTH = -1,
parameter int USER_WIDTH = -1,
parameter int BUFFER_DEPTH = -1
)(
input logic clk_i,
input logic rst_ni,
input logic test_en_i,
input logic slave_valid_i,
input logic [ADDR_WIDTH-1:0] slave_addr_i,
input logic [2:0] slave_prot_i,
input logic [3:0] slave_region_i,
input logic [7:0] slave_len_i,
input logic [2:0] slave_size_i,
input logic [1:0] slave_burst_i,
input logic slave_lock_i,
input logic [3:0] slave_cache_i,
input logic [3:0] slave_qos_i,
input logic [ID_WIDTH-1:0] slave_id_i,
input logic [USER_WIDTH-1:0] slave_user_i,
output logic slave_ready_o,
output logic master_valid_o,
output logic [ADDR_WIDTH-1:0] master_addr_o,
output logic [2:0] master_prot_o,
output logic [3:0] master_region_o,
output logic [7:0] master_len_o,
output logic [2:0] master_size_o,
output logic [1:0] master_burst_o,
output logic master_lock_o,
output logic [3:0] master_cache_o,
output logic [3:0] master_qos_o,
output logic [ID_WIDTH-1:0] master_id_o,
output logic [USER_WIDTH-1:0] master_user_o,
input logic master_ready_i
);
logic [29+ADDR_WIDTH+USER_WIDTH+ID_WIDTH-1:0] s_data_in;
logic [29+ADDR_WIDTH+USER_WIDTH+ID_WIDTH-1:0] s_data_out;
assign s_data_in = {slave_cache_i, slave_prot_i, slave_lock_i, slave_burst_i, slave_size_i, slave_len_i, slave_qos_i, slave_region_i, slave_addr_i, slave_user_i, slave_id_i} ;
assign {master_cache_o, master_prot_o, master_lock_o, master_burst_o, master_size_o, master_len_o, master_qos_o, master_region_o, master_addr_o, master_user_o, master_id_o} = s_data_out;
axi_single_slice #(.BUFFER_DEPTH(BUFFER_DEPTH), .DATA_WIDTH(29+ADDR_WIDTH+USER_WIDTH+ID_WIDTH)) i_axi_single_slice (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.testmode_i ( test_en_i ),
.valid_i ( slave_valid_i ),
.ready_o ( slave_ready_o ),
.data_i ( s_data_in ),
.ready_i ( master_ready_i ),
.valid_o ( master_valid_o ),
.data_o ( s_data_out )
);
endmodule
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
// Davide Rossi <davide.rossi@unibo.it>
module axi_aw_buffer #(
parameter int ID_WIDTH = -1,
parameter int ADDR_WIDTH = -1,
parameter int USER_WIDTH = -1,
parameter int BUFFER_DEPTH = -1
)(
input logic clk_i,
input logic rst_ni,
input logic test_en_i,
input logic slave_valid_i,
input logic [ADDR_WIDTH-1:0] slave_addr_i,
input logic [2:0] slave_prot_i,
input logic [3:0] slave_region_i,
input logic [7:0] slave_len_i,
input logic [2:0] slave_size_i,
input logic [1:0] slave_burst_i,
input logic slave_lock_i,
input logic [3:0] slave_cache_i,
input logic [3:0] slave_qos_i,
input logic [ID_WIDTH-1:0] slave_id_i,
input logic [USER_WIDTH-1:0] slave_user_i,
output logic slave_ready_o,
output logic master_valid_o,
output logic [ADDR_WIDTH-1:0] master_addr_o,
output logic [2:0] master_prot_o,
output logic [3:0] master_region_o,
output logic [7:0] master_len_o,
output logic [2:0] master_size_o,
output logic [1:0] master_burst_o,
output logic master_lock_o,
output logic [3:0] master_cache_o,
output logic [3:0] master_qos_o,
output logic [ID_WIDTH-1:0] master_id_o,
output logic [USER_WIDTH-1:0] master_user_o,
input logic master_ready_i
);
logic [29+ADDR_WIDTH+USER_WIDTH+ID_WIDTH-1:0] s_data_in;
logic [29+ADDR_WIDTH+USER_WIDTH+ID_WIDTH-1:0] s_data_out;
assign s_data_in = {slave_cache_i, slave_prot_i, slave_lock_i, slave_burst_i, slave_size_i, slave_len_i, slave_qos_i, slave_region_i, slave_addr_i, slave_user_i, slave_id_i};
assign {master_cache_o, master_prot_o, master_lock_o, master_burst_o, master_size_o, master_len_o, master_qos_o, master_region_o, master_addr_o, master_user_o, master_id_o} = s_data_out;
axi_single_slice #(.BUFFER_DEPTH(BUFFER_DEPTH), .DATA_WIDTH(29+ADDR_WIDTH+USER_WIDTH+ID_WIDTH)) i_axi_single_slice (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.testmode_i ( test_en_i ),
.valid_i ( slave_valid_i ),
.ready_o ( slave_ready_o ),
.data_i ( s_data_in ),
.ready_i ( master_ready_i ),
.valid_o ( master_valid_o ),
.data_o ( s_data_out )
);
endmodule
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
// Davide Rossi <davide.rossi@unibo.it>
module axi_b_buffer #(
parameter int ID_WIDTH = -1,
parameter int USER_WIDTH = -1,
parameter int BUFFER_DEPTH = -1
)(
input logic clk_i,
input logic rst_ni,
input logic test_en_i,
input logic slave_valid_i,
input logic [1:0] slave_resp_i,
input logic [ID_WIDTH-1:0] slave_id_i,
input logic [USER_WIDTH-1:0] slave_user_i,
output logic slave_ready_o,
output logic master_valid_o,
output logic [1:0] master_resp_o,
output logic [ID_WIDTH-1:0] master_id_o,
output logic [USER_WIDTH-1:0] master_user_o,
input logic master_ready_i
);
logic [2+USER_WIDTH+ID_WIDTH-1:0] s_data_in;
logic [2+USER_WIDTH+ID_WIDTH-1:0] s_data_out;
assign s_data_in = {slave_id_i, slave_user_i, slave_resp_i};
assign {master_id_o, master_user_o, master_resp_o} = s_data_out;
axi_single_slice #(.BUFFER_DEPTH(BUFFER_DEPTH), .DATA_WIDTH(2+USER_WIDTH+ID_WIDTH)) i_axi_single_slice (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.testmode_i ( test_en_i ),
.valid_i ( slave_valid_i ),
.ready_o ( slave_ready_o ),
.data_i ( s_data_in ),
.ready_i ( master_ready_i ),
.valid_o ( master_valid_o ),
.data_o ( s_data_out )
);
endmodule
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the “License”); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
//
// Author: Florian Zaruba, ETH Zurich
// Date: 17/07/2017
// Description: AXI Lite compatible interface
//
module axi_lite_interface #(
parameter int unsigned AXI_ADDR_WIDTH = 64,
parameter int unsigned AXI_DATA_WIDTH = 64,
parameter int unsigned AXI_ID_WIDTH = 10
)(
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
input ariane_axi::req_t axi_req_i,
output ariane_axi::resp_t axi_resp_o,
output logic [AXI_ADDR_WIDTH-1:0] address_o,
output logic en_o, // transaction is valid
output logic we_o, // write
input logic [AXI_DATA_WIDTH-1:0] data_i, // data
output logic [AXI_DATA_WIDTH-1:0] data_o
);
// The RLAST signal is not required, and is considered asserted for every transfer on the read data channel.
enum logic [1:0] { IDLE, READ, WRITE, WRITE_B} CS, NS;
// save the trans id, we will need it for reflection otherwise we are not plug compatible to the AXI standard
logic [AXI_ID_WIDTH-1:0] trans_id_n, trans_id_q;
// address register
logic [AXI_ADDR_WIDTH-1:0] address_n, address_q;
// pass through read data on the read data channel
assign axi_resp_o.r.data = data_i;
// send back the transaction id we've latched
assign axi_resp_o.r.id = trans_id_q;
assign axi_resp_o.b.id = trans_id_q;
// set r_last to one as defined by the AXI4 - Lite standard
assign axi_resp_o.r.last = 1'b1;
// we do not support any errors so set response flag to all zeros
assign axi_resp_o.b.resp = 2'b0;
assign axi_resp_o.r.resp = 2'b0;
// output data which we want to write to the slave
assign data_o = axi_req_i.w.data;
// ------------------------
// AXI4-Lite State Machine
// ------------------------
always_comb begin
// default signal assignment
NS = CS;
address_n = address_q;
trans_id_n = trans_id_q;
// we'll answer a write request only if we got address and data
axi_resp_o.aw_ready = 1'b0;
axi_resp_o.w_ready = 1'b0;
axi_resp_o.b_valid = 1'b0;
axi_resp_o.ar_ready = 1'b1;
axi_resp_o.r_valid = 1'b0;
address_o = '0;
we_o = 1'b0;
en_o = 1'b0;
case (CS)
// we are ready to accept a new request
IDLE: begin
// we've git a valid write request, we also know that we have asserted the aw_ready
if (axi_req_i.aw_valid) begin
axi_resp_o.aw_ready = 1'b1;
// this costs performance but the interconnect does not obey the AXI standard
NS = WRITE;
// save address
address_n = axi_req_i.aw.addr;
// save the transaction id for reflection
trans_id_n = axi_req_i.aw.id;
// we've got a valid read request, we also know that we have asserted the ar_ready
end else if (axi_req_i.ar_valid) begin
NS = READ;
address_n = axi_req_i.ar.addr;
// also request the word from the memory-like interface
address_o = axi_req_i.ar.addr;
// save the transaction id for reflection
trans_id_n = axi_req_i.ar.id;
end
end
// We've got a read request at least one cycle earlier
// so data_i will already contain the data we'd like tor read
READ: begin
// enable the ram-like
en_o = 1'b1;
// we are not ready for another request here
axi_resp_o.ar_ready = 1'b0;
// further assert the correct address
address_o = address_q;
// the read is valid
axi_resp_o.r_valid = 1'b1;
// check if we got a valid r_ready and go back to IDLE
if (axi_req_i.r_ready)
NS = IDLE;
end
// We've got a write request at least one cycle earlier
// wait here for the data
WRITE: begin
if (axi_req_i.w_valid) begin
// we are not ready for another request here
axi_resp_o.ar_ready = 1'b0;
axi_resp_o.w_ready = 1'b1;
// use the latched address
address_o = address_q;
en_o = 1'b1;
we_o = 1'b1;
// close this request
NS = WRITE_B;
end
end
WRITE_B: begin
axi_resp_o.b_valid = 1'b1;
// we've already performed the write here so wait for the ready signal
if (axi_req_i.b_ready)
NS = IDLE;
end
default:;
endcase
end
// ------------------------
// Registers
// ------------------------
always_ff @(posedge clk_i or negedge rst_ni) begin
if (~rst_ni) begin
CS <= IDLE;
address_q <= '0;
trans_id_q <= '0;
end else begin
CS <= NS;
address_q <= address_n;
trans_id_q <= trans_id_n;
end
end
// ------------------------
// Assertions
// ------------------------
// Listen for illegal transactions
//pragma translate_off
`ifndef VERILATOR
// check that burst length is just one
assert property (@(posedge clk_i) axi_req_i.ar_valid |-> ((axi_req_i.ar.len == 8'b0)))
else begin $error("AXI Lite does not support bursts larger than 1 or byte length unequal to the native bus size"); $stop(); end
// do the same for the write channel
assert property (@(posedge clk_i) axi_req_i.aw_valid |-> ((axi_req_i.aw.len == 8'b0)))
else begin $error("AXI Lite does not support bursts larger than 1 or byte length unequal to the native bus size"); $stop(); end
`endif
//pragma translate_on
endmodule
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
//
// Description: Connects SV AXI interface to structs used by Ariane
// Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
module axi_master_connect (
input ariane_axi::req_t axi_req_i,
output ariane_axi::resp_t axi_resp_o,
AXI_BUS.out master
);
assign master.aw_id = axi_req_i.aw.id;
assign master.aw_addr = axi_req_i.aw.addr;
assign master.aw_len = axi_req_i.aw.len;
assign master.aw_size = axi_req_i.aw.size;
assign master.aw_burst = axi_req_i.aw.burst;
assign master.aw_lock = axi_req_i.aw.lock;
assign master.aw_cache = axi_req_i.aw.cache;
assign master.aw_prot = axi_req_i.aw.prot;
assign master.aw_qos = axi_req_i.aw.qos;
assign master.aw_region = axi_req_i.aw.region;
assign master.aw_user = '0;
assign master.aw_valid = axi_req_i.aw_valid;
assign axi_resp_o.aw_ready = master.aw_ready;
assign master.w_data = axi_req_i.w.data;
assign master.w_strb = axi_req_i.w.strb;
assign master.w_last = axi_req_i.w.last;
assign master.w_user = '0;
assign master.w_valid = axi_req_i.w_valid;
assign axi_resp_o.w_ready = master.w_ready;
assign axi_resp_o.b.id = master.b_id;
assign axi_resp_o.b.resp = master.b_resp;
assign axi_resp_o.b_valid = master.b_valid;
assign master.b_ready = axi_req_i.b_ready;
assign master.ar_id = axi_req_i.ar.id;
assign master.ar_addr = axi_req_i.ar.addr;
assign master.ar_len = axi_req_i.ar.len;
assign master.ar_size = axi_req_i.ar.size;
assign master.ar_burst = axi_req_i.ar.burst;
assign master.ar_lock = axi_req_i.ar.lock;
assign master.ar_cache = axi_req_i.ar.cache;
assign master.ar_prot = axi_req_i.ar.prot;
assign master.ar_qos = axi_req_i.ar.qos;
assign master.ar_region = axi_req_i.ar.region;
assign master.ar_user = '0;
assign master.ar_valid = axi_req_i.ar_valid;
assign axi_resp_o.ar_ready = master.ar_ready;
assign axi_resp_o.r.id = master.r_id;
assign axi_resp_o.r.data = master.r_data;
assign axi_resp_o.r.resp = master.r_resp;
assign axi_resp_o.r.last = master.r_last;
assign axi_resp_o.r_valid = master.r_valid;
assign master.r_ready = axi_req_i.r_ready;
endmodule
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
//
// Description: Connects SV AXI interface to structs used by Ariane
// Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
module axi_master_connect_rev (
output ariane_axi::req_t axi_req_o,
input ariane_axi::resp_t axi_resp_i,
AXI_BUS.in master
);
assign axi_req_o.aw.atop = '0; // not supported at the moment
assign axi_req_o.aw.id = master.aw_id;
assign axi_req_o.aw.addr = master.aw_addr;
assign axi_req_o.aw.len = master.aw_len;
assign axi_req_o.aw.size = master.aw_size;
assign axi_req_o.aw.burst = master.aw_burst;
assign axi_req_o.aw.lock = master.aw_lock;
assign axi_req_o.aw.cache = master.aw_cache;
assign axi_req_o.aw.prot = master.aw_prot;
assign axi_req_o.aw.qos = master.aw_qos;
assign axi_req_o.aw.region = master.aw_region;
// assign = master.aw_user;
assign axi_req_o.aw_valid = master.aw_valid;
assign master.aw_ready = axi_resp_i.aw_ready;
assign axi_req_o.w.data = master.w_data;
assign axi_req_o.w.strb = master.w_strb;
assign axi_req_o.w.last = master.w_last;
// assign = master.w_user;
assign axi_req_o.w_valid = master.w_valid;
assign master.w_ready = axi_resp_i.w_ready;
assign master.b_id = axi_resp_i.b.id;
assign master.b_resp = axi_resp_i.b.resp;
assign master.b_valid = axi_resp_i.b_valid;
assign axi_req_o.b_ready = master.b_ready;
assign axi_req_o.ar.id = master.ar_id;
assign axi_req_o.ar.addr = master.ar_addr;
assign axi_req_o.ar.len = master.ar_len;
assign axi_req_o.ar.size = master.ar_size;
assign axi_req_o.ar.burst = master.ar_burst;
assign axi_req_o.ar.lock = master.ar_lock;
assign axi_req_o.ar.cache = master.ar_cache;
assign axi_req_o.ar.prot = master.ar_prot;
assign axi_req_o.ar.qos = master.ar_qos;
assign axi_req_o.ar.region = master.ar_region;
// assign = master.ar_user;
assign axi_req_o.ar_valid = master.ar_valid;
assign master.ar_ready = axi_resp_i.ar_ready;
assign master.r_id = axi_resp_i.r.id;
assign master.r_data = axi_resp_i.r.data;
assign master.r_resp = axi_resp_i.r.resp;
assign master.r_last = axi_resp_i.r.last;
assign master.r_valid = axi_resp_i.r_valid;
assign axi_req_o.r_ready = master.r_ready;
endmodule
// Copyright (c) 2014-2018 ETH Zurich, University of Bologna
//
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
//
// Fabian Schuiki <fschuiki@iis.ee.ethz.ch>
package axi_pkg;
typedef logic [1:0] burst_t;
typedef logic [1:0] resp_t;
typedef logic [3:0] cache_t;
typedef logic [2:0] prot_t;
typedef logic [3:0] qos_t;
typedef logic [3:0] region_t;
typedef logic [7:0] len_t;
typedef logic [2:0] size_t;
typedef logic [5:0] atop_t; // atomic operations
typedef logic [3:0] nsaid_t; // non-secure address identifier
localparam BURST_FIXED = 2'b00;
localparam BURST_INCR = 2'b01;
localparam BURST_WRAP = 2'b10;
localparam RESP_OKAY = 2'b00;
localparam RESP_EXOKAY = 2'b01;
localparam RESP_SLVERR = 2'b10;
localparam RESP_DECERR = 2'b11;
localparam CACHE_BUFFERABLE = 4'b0001;
localparam CACHE_MODIFIABLE = 4'b0010;
localparam CACHE_RD_ALLOC = 4'b0100;
localparam CACHE_WR_ALLOC = 4'b1000;
// 4 is recommended by AXI standard, so lets stick to it, do not change
localparam IdWidth = 4;
localparam UserWidth = 1;
localparam AddrWidth = 64;
localparam DataWidth = 64;
localparam StrbWidth = DataWidth / 8;
typedef logic [IdWidth-1:0] id_t;
typedef logic [AddrWidth-1:0] addr_t;
typedef logic [DataWidth-1:0] data_t;
typedef logic [StrbWidth-1:0] strb_t;
typedef logic [UserWidth-1:0] user_t;
// AW Channel
typedef struct packed {
id_t id;
addr_t addr;
len_t len;
size_t size;
burst_t burst;
logic lock;
cache_t cache;
prot_t prot;
qos_t qos;
region_t region;
atop_t atop;
} aw_chan_t;
// W Channel
typedef struct packed {
data_t data;
strb_t strb;
logic last;
} w_chan_t;
// B Channel
typedef struct packed {
id_t id;
resp_t resp;
} b_chan_t;
// AR Channel
typedef struct packed {
id_t id;
addr_t addr;
len_t len;
size_t size;
burst_t burst;
logic lock;
cache_t cache;
prot_t prot;
qos_t qos;
region_t region;
} ar_chan_t;
// R Channel
typedef struct packed {
id_t id;
data_t data;
resp_t resp;
logic last;
} r_chan_t;
endpackage
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
// Davide Rossi <davide.rossi@unibo.it>
module axi_r_buffer #(
parameter ID_WIDTH = 4,
parameter DATA_WIDTH = 64,
parameter USER_WIDTH = 6,
parameter BUFFER_DEPTH = 8,
parameter STRB_WIDTH = DATA_WIDTH/8 // DO NOT OVERRIDE
)(
input logic clk_i,
input logic rst_ni,
input logic test_en_i,
input logic slave_valid_i,
input logic [DATA_WIDTH-1:0] slave_data_i,
input logic [1:0] slave_resp_i,
input logic [USER_WIDTH-1:0] slave_user_i,
input logic [ID_WIDTH-1:0] slave_id_i,
input logic slave_last_i,
output logic slave_ready_o,
output logic master_valid_o,
output logic [DATA_WIDTH-1:0] master_data_o,
output logic [1:0] master_resp_o,
output logic [USER_WIDTH-1:0] master_user_o,
output logic [ID_WIDTH-1:0] master_id_o,
output logic master_last_o,
input logic master_ready_i
);
logic [2+DATA_WIDTH+USER_WIDTH+ID_WIDTH:0] s_data_in;
logic [2+DATA_WIDTH+USER_WIDTH+ID_WIDTH:0] s_data_out;
assign s_data_in = {slave_id_i, slave_user_i, slave_data_i, slave_resp_i, slave_last_i};
assign {master_id_o, master_user_o, master_data_o, master_resp_o, master_last_o} = s_data_out;
axi_single_slice #(.BUFFER_DEPTH(BUFFER_DEPTH), .DATA_WIDTH(3+DATA_WIDTH+USER_WIDTH+ID_WIDTH)) i_axi_single_slice (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.testmode_i ( test_en_i ),
.valid_i ( slave_valid_i ),
.ready_o ( slave_ready_o ),
.data_i ( s_data_in ),
.ready_i ( master_ready_i ),
.valid_o ( master_valid_o ),
.data_o ( s_data_out )
);
endmodule
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
/// Wrapper for a generic fifo
module axi_single_slice #(
parameter int BUFFER_DEPTH = -1,
parameter int DATA_WIDTH = -1
) (
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
input logic testmode_i,
input logic valid_i,
output logic ready_o,
input logic [DATA_WIDTH-1:0] data_i,
input logic ready_i,
output logic valid_o,
output logic [DATA_WIDTH-1:0] data_o
);
logic full, empty;
assign ready_o = ~full;
assign valid_o = ~empty;
fifo #(
.FALL_THROUGH ( 1'b0 ),
.DATA_WIDTH ( DATA_WIDTH ),
.DEPTH ( BUFFER_DEPTH )
) i_fifo (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i ( 1'b0 ),
.threshold_o (), // NC
.testmode_i ( testmode_i ),
.full_o ( full ),
.empty_o ( empty ),
.data_i ( data_i ),
.push_i ( valid_i & ready_o ),
.data_o ( data_o ),
.pop_i ( ready_i & valid_o )
);
endmodule
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
//
// Description: Connects SV AXI interface to structs used by Ariane
// Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
module axi_slave_connect (
output ariane_axi::req_t axi_req_o,
input ariane_axi::resp_t axi_resp_i,
AXI_BUS.in slave
);
assign axi_req_o.aw.atop = '0; // not supported at the moment
assign axi_req_o.aw.id = slave.aw_id;
assign axi_req_o.aw.addr = slave.aw_addr;
assign axi_req_o.aw.len = slave.aw_len;
assign axi_req_o.aw.size = slave.aw_size;
assign axi_req_o.aw.burst = slave.aw_burst;
assign axi_req_o.aw.lock = slave.aw_lock;
assign axi_req_o.aw.cache = slave.aw_cache;
assign axi_req_o.aw.prot = slave.aw_prot;
assign axi_req_o.aw.qos = slave.aw_qos;
assign axi_req_o.aw.region = slave.aw_region;
// assign = slave.aw_user;
assign axi_req_o.aw_valid = slave.aw_valid;
assign slave.aw_ready = axi_resp_i.aw_ready;
assign axi_req_o.w.data = slave.w_data;
assign axi_req_o.w.strb = slave.w_strb;
assign axi_req_o.w.last = slave.w_last;
// assign = slave.w_user;
assign axi_req_o.w_valid = slave.w_valid;
assign slave.w_ready = axi_resp_i.w_ready;
assign slave.b_id = axi_resp_i.b.id;
assign slave.b_resp = axi_resp_i.b.resp;
assign slave.b_valid = axi_resp_i.b_valid;
assign slave.b_user = 1'b0;
assign axi_req_o.b_ready = slave.b_ready;
assign axi_req_o.ar.id = slave.ar_id;
assign axi_req_o.ar.addr = slave.ar_addr;
assign axi_req_o.ar.len = slave.ar_len;
assign axi_req_o.ar.size = slave.ar_size;
assign axi_req_o.ar.burst = slave.ar_burst;
assign axi_req_o.ar.lock = slave.ar_lock;
assign axi_req_o.ar.cache = slave.ar_cache;
assign axi_req_o.ar.prot = slave.ar_prot;
assign axi_req_o.ar.qos = slave.ar_qos;
assign axi_req_o.ar.region = slave.ar_region;
// assign = slave.ar_user;
assign axi_req_o.ar_valid = slave.ar_valid;
assign slave.ar_ready = axi_resp_i.ar_ready;
assign slave.r_id = axi_resp_i.r.id;
assign slave.r_data = axi_resp_i.r.data;
assign slave.r_resp = axi_resp_i.r.resp;
assign slave.r_last = axi_resp_i.r.last;
assign slave.r_valid = axi_resp_i.r_valid;
assign slave.r_user = 1'b0;
assign axi_req_o.r_ready = slave.r_ready;
endmodule
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
//
// Description: Connects SV AXI interface to structs used by Ariane
// Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
module axi_slave_connect_rev (
input ariane_axi::req_t axi_req_i,
output ariane_axi::resp_t axi_resp_o,
AXI_BUS.out slave
);
assign slave.aw_id = axi_req_i.aw.id;
assign slave.aw_addr = axi_req_i.aw.addr;
assign slave.aw_len = axi_req_i.aw.len;
assign slave.aw_size = axi_req_i.aw.size;
assign slave.aw_burst = axi_req_i.aw.burst;
assign slave.aw_lock = axi_req_i.aw.lock;
assign slave.aw_cache = axi_req_i.aw.cache;
assign slave.aw_prot = axi_req_i.aw.prot;
assign slave.aw_qos = axi_req_i.aw.qos;
assign slave.aw_region = axi_req_i.aw.region;
assign slave.aw_user = '0;
assign slave.aw_valid = axi_req_i.aw_valid;
assign axi_resp_o.aw_ready = slave.aw_ready;
assign slave.w_data = axi_req_i.w.data;
assign slave.w_strb = axi_req_i.w.strb;
assign slave.w_last = axi_req_i.w.last;
assign slave.w_user = '0;
assign slave.w_valid = axi_req_i.w_valid;
assign axi_resp_o.w_ready = slave.w_ready;
assign axi_resp_o.b.id = slave.b_id;
assign axi_resp_o.b.resp = slave.b_resp;
assign axi_resp_o.b_valid = slave.b_valid;
assign slave.b_ready = axi_req_i.b_ready;
assign slave.ar_id = axi_req_i.ar.id;
assign slave.ar_addr = axi_req_i.ar.addr;
assign slave.ar_len = axi_req_i.ar.len;
assign slave.ar_size = axi_req_i.ar.size;
assign slave.ar_burst = axi_req_i.ar.burst;
assign slave.ar_lock = axi_req_i.ar.lock;
assign slave.ar_cache = axi_req_i.ar.cache;
assign slave.ar_prot = axi_req_i.ar.prot;
assign slave.ar_qos = axi_req_i.ar.qos;
assign slave.ar_region = axi_req_i.ar.region;
assign slave.ar_user = '0;
assign slave.ar_valid = axi_req_i.ar_valid;
assign axi_resp_o.ar_ready = slave.ar_ready;
assign axi_resp_o.r.id = slave.r_id;
assign axi_resp_o.r.data = slave.r_data;
assign axi_resp_o.r.resp = slave.r_resp;
assign axi_resp_o.r.last = slave.r_last;
assign axi_resp_o.r_valid = slave.r_valid;
assign slave.r_ready = axi_req_i.r_ready;
endmodule
module axi_slice_wrap #(
parameter AXI_ADDR_WIDTH = 32,
parameter AXI_DATA_WIDTH = 64,
parameter AXI_USER_WIDTH = 6,
parameter AXI_ID_WIDTH = 3,
parameter SLICE_DEPTH = 2,
parameter AXI_STRB_WIDTH = AXI_DATA_WIDTH/8
)(
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
input logic test_en_i,
AXI_BUS.Slave axi_slave,
AXI_BUS.Master axi_master
);
axi_slice #(
.AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_USER_WIDTH ( AXI_USER_WIDTH ),
.AXI_ID_WIDTH ( AXI_ID_WIDTH ),
.SLICE_DEPTH ( SLICE_DEPTH ),
.AXI_STRB_WIDTH ( AXI_STRB_WIDTH )
) i_axi_slice (
.axi_slave_aw_valid_i ( axi_slave.aw_valid ),
.axi_slave_aw_addr_i ( axi_slave.aw_addr ),
.axi_slave_aw_prot_i ( axi_slave.aw_prot ),
.axi_slave_aw_region_i ( axi_slave.aw_region ),
.axi_slave_aw_len_i ( axi_slave.aw_len ),
.axi_slave_aw_size_i ( axi_slave.aw_size ),
.axi_slave_aw_burst_i ( axi_slave.aw_burst ),
.axi_slave_aw_lock_i ( axi_slave.aw_lock ),
.axi_slave_aw_cache_i ( axi_slave.aw_cache ),
.axi_slave_aw_qos_i ( axi_slave.aw_qos ),
.axi_slave_aw_id_i ( axi_slave.aw_id ),
.axi_slave_aw_user_i ( axi_slave.aw_user ),
.axi_slave_aw_ready_o ( axi_slave.aw_ready ),
.axi_slave_ar_valid_i ( axi_slave.ar_valid ),
.axi_slave_ar_addr_i ( axi_slave.ar_addr ),
.axi_slave_ar_prot_i ( axi_slave.ar_prot ),
.axi_slave_ar_region_i ( axi_slave.ar_region ),
.axi_slave_ar_len_i ( axi_slave.ar_len ),
.axi_slave_ar_size_i ( axi_slave.ar_size ),
.axi_slave_ar_burst_i ( axi_slave.ar_burst ),
.axi_slave_ar_lock_i ( axi_slave.ar_lock ),
.axi_slave_ar_cache_i ( axi_slave.ar_cache ),
.axi_slave_ar_qos_i ( axi_slave.ar_qos ),
.axi_slave_ar_id_i ( axi_slave.ar_id ),
.axi_slave_ar_user_i ( axi_slave.ar_user ),
.axi_slave_ar_ready_o ( axi_slave.ar_ready ),
.axi_slave_w_valid_i ( axi_slave.w_valid ),
.axi_slave_w_data_i ( axi_slave.w_data ),
.axi_slave_w_strb_i ( axi_slave.w_strb ),
.axi_slave_w_user_i ( axi_slave.w_user ),
.axi_slave_w_last_i ( axi_slave.w_last ),
.axi_slave_w_ready_o ( axi_slave.w_ready ),
.axi_slave_r_valid_o ( axi_slave.r_valid ),
.axi_slave_r_data_o ( axi_slave.r_data ),
.axi_slave_r_resp_o ( axi_slave.r_resp ),
.axi_slave_r_last_o ( axi_slave.r_last ),
.axi_slave_r_id_o ( axi_slave.r_id ),
.axi_slave_r_user_o ( axi_slave.r_user ),
.axi_slave_r_ready_i ( axi_slave.r_ready ),
.axi_slave_b_valid_o ( axi_slave.b_valid ),
.axi_slave_b_resp_o ( axi_slave.b_resp ),
.axi_slave_b_id_o ( axi_slave.b_id ),
.axi_slave_b_user_o ( axi_slave.b_user ),
.axi_slave_b_ready_i ( axi_slave.b_ready ),
.axi_master_aw_valid_o ( axi_master.aw_valid ),
.axi_master_aw_addr_o ( axi_master.aw_addr ),
.axi_master_aw_prot_o ( axi_master.aw_prot ),
.axi_master_aw_region_o ( axi_master.aw_region ),
.axi_master_aw_len_o ( axi_master.aw_len ),
.axi_master_aw_size_o ( axi_master.aw_size ),
.axi_master_aw_burst_o ( axi_master.aw_burst ),
.axi_master_aw_lock_o ( axi_master.aw_lock ),
.axi_master_aw_cache_o ( axi_master.aw_cache ),
.axi_master_aw_qos_o ( axi_master.aw_qos ),
.axi_master_aw_id_o ( axi_master.aw_id ),
.axi_master_aw_user_o ( axi_master.aw_user ),
.axi_master_aw_ready_i ( axi_master.aw_ready ),
.axi_master_ar_valid_o ( axi_master.ar_valid ),
.axi_master_ar_addr_o ( axi_master.ar_addr ),
.axi_master_ar_prot_o ( axi_master.ar_prot ),
.axi_master_ar_region_o ( axi_master.ar_region ),
.axi_master_ar_len_o ( axi_master.ar_len ),
.axi_master_ar_size_o ( axi_master.ar_size ),
.axi_master_ar_burst_o ( axi_master.ar_burst ),
.axi_master_ar_lock_o ( axi_master.ar_lock ),
.axi_master_ar_cache_o ( axi_master.ar_cache ),
.axi_master_ar_qos_o ( axi_master.ar_qos ),
.axi_master_ar_id_o ( axi_master.ar_id ),
.axi_master_ar_user_o ( axi_master.ar_user ),
.axi_master_ar_ready_i ( axi_master.ar_ready ),
.axi_master_w_valid_o ( axi_master.w_valid ),
.axi_master_w_data_o ( axi_master.w_data ),
.axi_master_w_strb_o ( axi_master.w_strb ),
.axi_master_w_user_o ( axi_master.w_user ),
.axi_master_w_last_o ( axi_master.w_last ),
.axi_master_w_ready_i ( axi_master.w_ready ),
.axi_master_r_valid_i ( axi_master.r_valid ),
.axi_master_r_data_i ( axi_master.r_data ),
.axi_master_r_resp_i ( axi_master.r_resp ),
.axi_master_r_last_i ( axi_master.r_last ),
.axi_master_r_id_i ( axi_master.r_id ),
.axi_master_r_user_i ( axi_master.r_user ),
.axi_master_r_ready_o ( axi_master.r_ready ),
.axi_master_b_valid_i ( axi_master.b_valid ),
.axi_master_b_resp_i ( axi_master.b_resp ),
.axi_master_b_id_i ( axi_master.b_id ),
.axi_master_b_user_i ( axi_master.b_user ),
.axi_master_b_ready_o ( axi_master.b_ready ),
.*
);
endmodule
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
// Davide Rossi <davide.rossi@unibo.it>
module axi_w_buffer #(
parameter int DATA_WIDTH = -1,
parameter int USER_WIDTH = -1,
parameter int BUFFER_DEPTH = -1,
parameter int STRB_WIDTH = DATA_WIDTH/8 // DO NOT OVERRIDE
)(
input logic clk_i,
input logic rst_ni,
input logic test_en_i,
input logic slave_valid_i,
input logic [DATA_WIDTH-1:0] slave_data_i,
input logic [STRB_WIDTH-1:0] slave_strb_i,
input logic [USER_WIDTH-1:0] slave_user_i,
input logic slave_last_i,
output logic slave_ready_o,
output logic master_valid_o,
output logic [DATA_WIDTH-1:0] master_data_o,
output logic [STRB_WIDTH-1:0] master_strb_o,
output logic [USER_WIDTH-1:0] master_user_o,
output logic master_last_o,
input logic master_ready_i
);
logic [DATA_WIDTH+STRB_WIDTH+USER_WIDTH:0] s_data_in;
logic [DATA_WIDTH+STRB_WIDTH+USER_WIDTH:0] s_data_out;
assign s_data_in = { slave_user_i, slave_strb_i, slave_data_i, slave_last_i };
assign { master_user_o, master_strb_o, master_data_o, master_last_o } = s_data_out;
axi_single_slice #(.BUFFER_DEPTH(BUFFER_DEPTH), .DATA_WIDTH(1+DATA_WIDTH+STRB_WIDTH+USER_WIDTH)) i_axi_single_slice (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.testmode_i ( test_en_i ),
.valid_i ( slave_valid_i ),
.ready_o ( slave_ready_o ),
.data_i ( s_data_in ),
.ready_i ( master_ready_i ),
.valid_o ( master_valid_o ),
.data_o ( s_data_out )
);
endmodule
//Copyright (C) 2018 to present,
// Copyright and related rights are licensed under the Solderpad Hardware
// 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://solderpad.org/licenses/SHL-2.0. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.//
// Author: Florian Zaruba, ETH Zurich
// Date: 08.02.2018
// Migrated: Luis Vitorio Cargnini, IEEE
// Date: 09.06.2018
// branch history table - 2 bit saturation counter
module bht #(
parameter int unsigned NR_ENTRIES = 1024
)(
input logic clk_i,
input logic rst_ni,
input logic flush_i,
input logic debug_mode_i,
input logic [63:0] vpc_i,
input ariane_pkg::bht_update_t bht_update_i,
output ariane_pkg::bht_prediction_t bht_prediction_o
);
localparam OFFSET = 2; // we are using compressed instructions so do not use the lower 2 bits for prediction
localparam ANTIALIAS_BITS = 8;
// number of bits we should use for prediction
localparam PREDICTION_BITS = $clog2(NR_ENTRIES) + OFFSET;
struct packed {
logic valid;
logic [1:0] saturation_counter;
} bht_d[NR_ENTRIES-1:0], bht_q[NR_ENTRIES-1:0];
logic [$clog2(NR_ENTRIES)-1:0] index, update_pc;
logic [1:0] saturation_counter;
assign index = vpc_i[PREDICTION_BITS - 1:OFFSET];
assign update_pc = bht_update_i.pc[PREDICTION_BITS - 1:OFFSET];
// prediction assignment
assign bht_prediction_o.valid = bht_q[index].valid;
assign bht_prediction_o.taken = bht_q[index].saturation_counter == 2'b10;
assign bht_prediction_o.strongly_taken = (bht_q[index].saturation_counter == 2'b11);
always_comb begin : update_bht
bht_d = bht_q;
saturation_counter = bht_q[update_pc].saturation_counter;
if (bht_update_i.valid && !debug_mode_i) begin
bht_d[update_pc].valid = 1'b1;
if (saturation_counter == 2'b11) begin
// we can safely decrease it
if (~bht_update_i.taken)
bht_d[update_pc].saturation_counter = saturation_counter - 1;
// then check if it saturated in the negative regime e.g.: branch not taken
end else if (saturation_counter == 2'b00) begin
// we can safely increase it
if (bht_update_i.taken)
bht_d[update_pc].saturation_counter = saturation_counter + 1;
end else begin // otherwise we are not in any boundaries and can decrease or increase it
if (bht_update_i.taken)
bht_d[update_pc].saturation_counter = saturation_counter + 1;
else
bht_d[update_pc].saturation_counter = saturation_counter - 1;
end
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (~rst_ni) begin
for (int unsigned i = 0; i < NR_ENTRIES; i++)
bht_q[i] <= '0;
end else begin
// evict all entries
if (flush_i) begin
for (int i = 0; i < NR_ENTRIES; i++) begin
bht_q[i].valid <= 1'b0;
bht_q[i].saturation_counter <= 2'b10;
end
end else begin
bht_q <= bht_d;
end
end
end
endmodule
/* Copyright 2018 ETH Zurich and University of Bologna.
* Copyright and related rights are licensed under the Solderpad Hardware
* License, Version 0.51 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
* or agreed to in writing, software, hardware and materials distributed under
* this 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.
*
* File: $filename.v
*
* Description: Auto-generated bootrom
*/
// Auto-generated code
module bootrom (
input logic clk_i,
input logic req_i,
input logic [63:0] addr_i,
output logic [63:0] rdata_o
);
localparam int RomSize = 226;
const logic [RomSize-1:0][63:0] mem = {
64'h00006874_6469772d,
64'h6f692d67_65720074,
64'h66696873_2d676572,
64'h00737470_75727265,
64'h746e6900_746e6572,
64'h61702d74_70757272,
64'h65746e69_00646565,
64'h70732d74_6e657272,
64'h75630076_65646e2c,
64'h76637369_72007974,
64'h69726f69_72702d78,
64'h616d2c76_63736972,
64'h0073656d_616e2d67,
64'h65720064_65646e65,
64'h7478652d_73747075,
64'h72726574_6e690073,
64'h65676e61_7200656c,
64'h646e6168_702c7875,
64'h6e696c00_72656c6c,
64'h6f72746e_6f632d74,
64'h70757272_65746e69,
64'h00736c6c_65632d74,
64'h70757272_65746e69,
64'h23007469_6c70732d,
64'h626c7400_65707974,
64'h2d756d6d_00617369,
64'h2c766373_69720073,
64'h75746174_73006765,
64'h72006570_79745f65,
64'h63697665_64007963,
64'h6e657571_6572662d,
64'h6b636f6c_63007963,
64'h6e657571_6572662d,
64'h65736162_656d6974,
64'h006c6564_6f6d0065,
64'h6c626974_61706d6f,
64'h6300736c_6c65632d,
64'h657a6973_2300736c,
64'h6c65632d_73736572,
64'h64646123_09000000,
64'h02000000_02000000,
64'h02000000_04000000,
64'h2e010000_04000000,
64'h03000000_02000000,
64'h24010000_04000000,
64'h03000000_01000000,
64'h19010000_04000000,
64'h03000000_02000000,
64'h08010000_04000000,
64'h03000000_00c20100,
64'hfa000000_04000000,
64'h03000000_80f0fa02,
64'h3f000000_04000000,
64'h03000000_00100000,
64'h00000000_00000010,
64'h00000000_5b000000,
64'h10000000_03000000,
64'h00303537_3631736e,
64'h1b000000_08000000,
64'h03000000_00000030,
64'h30303030_30303140,
64'h74726175_01000000,
64'h02000000_006c6f72,
64'h746e6f63_d2000000,
64'h08000000_03000000,
64'h00100000_00000000,
64'h00000000_00000000,
64'h5b000000_10000000,
64'h03000000_ffff0000,
64'h01000000_be000000,
64'h08000000_03000000,
64'h00333130_2d677562,
64'h65642c76_63736972,
64'h1b000000_10000000,
64'h03000000_00003040,
64'h72656c6c_6f72746e,
64'h6f632d67_75626564,
64'h01000000_02000000,
64'h02000000_af000000,
64'h04000000_03000000,
64'h02000000_a9000000,
64'h04000000_03000000,
64'h02000000_ef000000,
64'h04000000_03000000,
64'h07000000_dc000000,
64'h04000000_03000000,
64'h00000004_00000000,
64'h0000000c_00000000,
64'h5b000000_10000000,
64'h03000000_09000000,
64'h01000000_0b000000,
64'h01000000_be000000,
64'h10000000_03000000,
64'h94000000_00000000,
64'h03000000_00000030,
64'h63696c70_2c766373,
64'h69720030_2e302e31,
64'h2d63696c_702c6576,
64'h69666973_1b000000,
64'h1e000000_03000000,
64'h01000000_83000000,
64'h04000000_03000000,
64'h00000000_00000000,
64'h04000000_03000000,
64'h00000000_30303030,
64'h30306340_72656c6c,
64'h6f72746e_6f632d74,
64'h70757272_65746e69,
64'h01000000_02000000,
64'h006c6f72_746e6f63,
64'hd2000000_08000000,
64'h03000000_00000c00,
64'h00000000_00000002,
64'h00000000_5b000000,
64'h10000000_03000000,
64'h07000000_01000000,
64'h03000000_01000000,
64'hbe000000_10000000,
64'h03000000_00000000,
64'h30746e69_6c632c76,
64'h63736972_1b000000,
64'h0d000000_03000000,
64'h00000030_30303030,
64'h30324074_6e696c63,
64'h01000000_b7000000,
64'h00000000_03000000,
64'h00007375_622d656c,
64'h706d6973_00636f73,
64'h2d657261_622d656e,
64'h61697261_2c687465,
64'h1b000000_1f000000,
64'h03000000_02000000,
64'h0f000000_04000000,
64'h03000000_02000000,
64'h00000000_04000000,
64'h03000000_00636f73,
64'h01000000_02000000,
64'h00008001_00000000,
64'h00000080_00000000,
64'h5b000000_10000000,
64'h03000000_00007972,
64'h6f6d656d_4f000000,
64'h07000000_03000000,
64'h00303030_30303030,
64'h38407972_6f6d656d,
64'h01000000_02000000,
64'h02000000_02000000,
64'h01000000_af000000,
64'h04000000_03000000,
64'h01000000_a9000000,
64'h04000000_03000000,
64'h00006374_6e692d75,
64'h70632c76_63736972,
64'h1b000000_0f000000,
64'h03000000_94000000,
64'h00000000_03000000,
64'h01000000_83000000,
64'h04000000_03000000,
64'h00000000_72656c6c,
64'h6f72746e_6f632d74,
64'h70757272_65746e69,
64'h01000000_79000000,
64'h00000000_03000000,
64'h00003933_76732c76,
64'h63736972_70000000,
64'h0b000000_03000000,
64'h00007573_63616d69,
64'h34367672_66000000,
64'h0b000000_03000000,
64'h00000076_63736972,
64'h00656e61_69726120,
64'h2c687465_1b000000,
64'h12000000_03000000,
64'h00000000_79616b6f,
64'h5f000000_05000000,
64'h03000000_00000000,
64'h5b000000_04000000,
64'h03000000_00757063,
64'h4f000000_04000000,
64'h03000000_80f0fa02,
64'h3f000000_04000000,
64'h03000000_00000030,
64'h40757063_01000000,
64'h00800000_2c000000,
64'h04000000_03000000,
64'h00000000_0f000000,
64'h04000000_03000000,
64'h01000000_00000000,
64'h04000000_03000000,
64'h00000000_73757063,
64'h01000000_00657261,
64'h622d656e_61697261,
64'h2c687465_26000000,
64'h10000000_03000000,
64'h00766564_2d657261,
64'h622d656e_61697261,
64'h2c687465_1b000000,
64'h14000000_03000000,
64'h02000000_0f000000,
64'h04000000_03000000,
64'h02000000_00000000,
64'h04000000_03000000,
64'h00000000_01000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h1c050000_3b010000,
64'h00000000_10000000,
64'h11000000_28000000,
64'h54050000_38000000,
64'h8f060000_edfe0dd0,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_0000bff5,
64'h10500073_03c58593,
64'h00000597_f1402573,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00000000_00000000,
64'h00008402_07458593,
64'h00000597_f1402573,
64'h01f41413_0010041b
};
logic [$clog2(RomSize)-1:0] addr_q;
always_ff @(posedge clk_i) begin
if (req_i) begin
addr_q <= addr_i[$clog2(RomSize)-1+3:3];
end
end
// this prevents spurious Xes from propagating into
// the speculative fetch stage of the core
assign rdata_o = (addr_q < RomSize) ? mem[addr_q] : '0;
endmodule
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
//
// Author: Florian Zaruba, ETH Zurich
// Date: 09.05.2017
// Description: Branch target calculation and comparison
import ariane_pkg::*;
module branch_unit (
input fu_data_t fu_data_i,
input logic [63:0] pc_i, // PC of instruction
input logic is_compressed_instr_i,
input logic fu_valid_i, // any functional unit is valid, check that there is no accidental mis-predict
input logic branch_valid_i,
input logic branch_comp_res_i, // branch comparison result from ALU
output logic [63:0] branch_result_o,
input branchpredict_sbe_t branch_predict_i, // this is the address we predicted
output branchpredict_t resolved_branch_o, // this is the actual address we are targeting
output logic resolve_branch_o, // to ID to clear that we resolved the branch and we can
// accept new entries to the scoreboard
output exception_t branch_exception_o // branch exception out
);
logic [63:0] target_address;
logic [63:0] next_pc;
// here we handle the various possibilities of mis-predicts
always_comb begin : mispredict_handler
// set the jump base, for JALR we need to look at the register, for all other control flow instructions we can take the current PC
automatic logic [63:0] jump_base;
jump_base = (fu_data_i.operator == JALR) ? fu_data_i.operand_a : pc_i;
resolve_branch_o = 1'b0;
resolved_branch_o.target_address = 64'b0;
resolved_branch_o.is_taken = 1'b0;
resolved_branch_o.valid = branch_valid_i;
resolved_branch_o.is_mispredict = 1'b0;
resolved_branch_o.clear = 1'b0;
resolved_branch_o.cf_type = branch_predict_i.cf_type;
// calculate next PC, depending on whether the instruction is compressed or not this may be different
next_pc = pc_i + ((is_compressed_instr_i) ? 64'h2 : 64'h4);
// calculate target address simple 64 bit addition
target_address = $unsigned($signed(jump_base) + $signed(fu_data_i.imm));
// on a JALR we are supposed to reset the LSB to 0 (according to the specification)
if (fu_data_i.operator == JALR)
target_address[0] = 1'b0;
// if we need to put the branch target address in a destination register, output it here to WB
branch_result_o = next_pc;
// save PC - we need this to get the target row in the branch target buffer
// we play this trick with the branch instruction which wraps a word boundary:
// /---------- Place the prediction on this PC
// \/
// ____________________________________________________
// |branch [15:0] | branch[31:16] | compressed 1[15:0] |
// |____________________________________________________
// This will relief the pre-fetcher to re-fetch partially fetched unaligned branch instructions e.g.:
// we don't have a back arch between the pre-fetcher and decoder/instruction FIFO.
resolved_branch_o.pc = (is_compressed_instr_i || pc_i[1] == 1'b0) ? pc_i : ({pc_i[63:2], 2'b0} + 64'h4);
if (branch_valid_i) begin
// write target address which goes to pc gen
resolved_branch_o.target_address = (branch_comp_res_i) ? target_address : next_pc;
resolved_branch_o.is_taken = branch_comp_res_i;
// we've detected a branch in ID with the following parameters
// we mis-predicted e.g.: the predicted address is unequal to the actual address
if (target_address[0] == 1'b0) begin
// we've got a valid branch prediction
if (branch_predict_i.valid) begin
// if the outcome doesn't match we've got a mis-predict
if (branch_predict_i.predict_taken != branch_comp_res_i) begin
resolved_branch_o.is_mispredict = 1'b1;
end
// check if the address of the predict taken branch is correct
if (branch_predict_i.predict_taken && target_address != branch_predict_i.predict_address) begin
resolved_branch_o.is_mispredict = 1'b1;
end
// branch-prediction didn't do anything (e.g.: it fetched PC + 2/4), so if this branch is taken
// we also have a mis-predict
end else begin
if (branch_comp_res_i) begin
resolved_branch_o.is_mispredict = 1'b1;
end
end
end
// to resolve the branch in ID
resolve_branch_o = 1'b1;
// the other case would be that this instruction was no branch but branch prediction thought that it was one
// this is essentially also a mis-predict
end else if (fu_valid_i && branch_predict_i.valid && branch_predict_i.predict_taken) begin
// re-set the branch to the next PC
resolved_branch_o.is_mispredict = 1'b1;
resolved_branch_o.target_address = next_pc;
// clear this entry so that we are not constantly mis-predicting
resolved_branch_o.clear = 1'b1;
resolved_branch_o.valid = 1'b1;
resolve_branch_o = 1'b1;
end
end
// use ALU exception signal for storing instruction fetch exceptions if
// the target address is not aligned to a 2 byte boundary
always_comb begin : exception_handling
branch_exception_o.cause = riscv::INSTR_ADDR_MISALIGNED;
branch_exception_o.valid = 1'b0;
branch_exception_o.tval = pc_i;
// only throw exception if this is indeed a branch
if (branch_valid_i && target_address[0] != 1'b0)
branch_exception_o.valid = 1'b1;
end
endmodule
//Copyright (C) 2018 to present,
// Copyright and related rights are licensed under the Solderpad Hardware
// 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://solderpad.org/licenses/SHL-2.0. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
//
// Author: Florian Zaruba, ETH Zurich
// Date: 08.02.2018
// Migrated: Luis Vitorio Cargnini, IEEE
// Date: 09.06.2018
// ------------------------------
// Branch Prediction
// ------------------------------
// branch target buffer
module btb #(
parameter int NR_ENTRIES = 8
)(
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
input logic flush_i, // flush the btb
input logic debug_mode_i,
input logic [63:0] vpc_i, // virtual PC from IF stage
input ariane_pkg::btb_update_t btb_update_i, // update btb with this information
output ariane_pkg::btb_prediction_t btb_prediction_o // prediction from btb
);
// number of bits which are not used for indexing
localparam OFFSET = 1; // we are using compressed instructions so do use the lower 2 bits for prediction
localparam ANTIALIAS_BITS = 8;
// number of bits we should use for prediction
localparam PREDICTION_BITS = $clog2(NR_ENTRIES) + OFFSET;
// typedef for all branch target entries
// we may want to try to put a tag field that fills the rest of the PC in-order to mitigate aliasing effects
ariane_pkg::btb_prediction_t btb_d [NR_ENTRIES-1:0], btb_q [NR_ENTRIES-1:0];
logic [$clog2(NR_ENTRIES)-1:0] index, update_pc;
assign index = vpc_i[PREDICTION_BITS - 1:OFFSET];
assign update_pc = btb_update_i.pc[PREDICTION_BITS - 1:OFFSET];
// output matching prediction
assign btb_prediction_o = btb_q[index];
// -------------------------
// Update Branch Prediction
// -------------------------
// update on a mis-predict
always_comb begin : update_branch_predict
btb_d = btb_q;
if (btb_update_i.valid && !debug_mode_i) begin
btb_d[update_pc].valid = 1'b1;
// the target address is simply updated
btb_d[update_pc].target_address = btb_update_i.target_address;
// check if we should invalidate this entry, this happens in case we predicted a branch
// where actually none-is (aliasing)
if (btb_update_i.clear) begin
btb_d[update_pc].valid = 1'b0;
end
end
end
// sequential process
always_ff @(posedge clk_i or negedge rst_ni) begin
if (~rst_ni) begin
// Bias the branches to be taken upon first arrival
for (int i = 0; i < NR_ENTRIES; i++)
btb_q[i] <= '{default: 0};
end else begin
// evict all entries
if (flush_i) begin
for (int i = 0; i < NR_ENTRIES; i++) begin
btb_q[i].valid <= 1'b0;
end
end else begin
btb_q <= btb_d;
end
end
end
endmodule
// Copyright 2018 ETH Zurich and University of Bologna.
//
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
//
// Fabian Schuiki <fschuiki@iis.ee.ethz.ch>
/// A two-phase clock domain crossing.
///
/// CONSTRAINT: Requires max_delay of min_period(src_clk_i, dst_clk_i) through
/// the paths async_req, async_ack, async_data.
/* verilator lint_off DECLFILENAME */
module cdc_2phase #(
parameter type T = logic
)(
input logic src_rst_ni,
input logic src_clk_i,
input T src_data_i,
input logic src_valid_i,
output logic src_ready_o,
input logic dst_rst_ni,
input logic dst_clk_i,
output T dst_data_o,
output logic dst_valid_o,
input logic dst_ready_i
);
// Asynchronous handshake signals.
(* dont_touch = "true" *) logic async_req;
(* dont_touch = "true" *) logic async_ack;
(* dont_touch = "true" *) T async_data;
// The sender in the source domain.
cdc_2phase_src #(.T(T)) i_src (
.rst_ni ( src_rst_ni ),
.clk_i ( src_clk_i ),
.data_i ( src_data_i ),
.valid_i ( src_valid_i ),
.ready_o ( src_ready_o ),
.async_req_o ( async_req ),
.async_ack_i ( async_ack ),
.async_data_o ( async_data )
);
// The receiver in the destination domain.
cdc_2phase_dst #(.T(T)) i_dst (
.rst_ni ( dst_rst_ni ),
.clk_i ( dst_clk_i ),
.data_o ( dst_data_o ),
.valid_o ( dst_valid_o ),
.ready_i ( dst_ready_i ),
.async_req_i ( async_req ),
.async_ack_o ( async_ack ),
.async_data_i ( async_data )
);
endmodule
/// Half of the two-phase clock domain crossing located in the source domain.
module cdc_2phase_src #(
parameter type T = logic
)(
input logic rst_ni,
input logic clk_i,
input T data_i,
input logic valid_i,
output logic ready_o,
output logic async_req_o,
input logic async_ack_i,
output T async_data_o
);
(* dont_touch = "true" *)
logic req_src_q, ack_src_q, ack_q;
(* dont_touch = "true" *)
T data_src_q;
// The req_src and data_src registers change when a new data item is accepted.
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
req_src_q <= 0;
data_src_q <= '0;
end else if (valid_i && ready_o) begin
req_src_q <= ~req_src_q;
data_src_q <= data_i;
end
end
// The ack_src and ack registers act as synchronization stages.
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
ack_src_q <= 0;
ack_q <= 0;
end else begin
ack_src_q <= async_ack_i;
ack_q <= ack_src_q;
end
end
// Output assignments.
assign ready_o = (req_src_q == ack_q);
assign async_req_o = req_src_q;
assign async_data_o = data_src_q;
endmodule
/// Half of the two-phase clock domain crossing located in the destination
/// domain.
module cdc_2phase_dst #(
parameter type T = logic
)(
input logic rst_ni,
input logic clk_i,
output T data_o,
output logic valid_o,
input logic ready_i,
input logic async_req_i,
output logic async_ack_o,
input T async_data_i
);
(* dont_touch = "true" *)
(* async_reg = "true" *)
logic req_dst_q, req_q0, req_q1, ack_dst_q;
(* dont_touch = "true" *)
T data_dst_q;
// The ack_dst register changes when a new data item is accepted.
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
ack_dst_q <= 0;
end else if (valid_o && ready_i) begin
ack_dst_q <= ~ack_dst_q;
end
end
// The data_dst register changes when a new data item is presented. This is
// indicated by the async_req line changing levels.
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
data_dst_q <= '0;
end else if (req_q0 != req_q1 && !valid_o) begin
data_dst_q <= async_data_i;
end
end
// The req_dst and req registers act as synchronization stages.
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
req_dst_q <= 0;
req_q0 <= 0;
req_q1 <= 0;
end else begin
req_dst_q <= async_req_i;
req_q0 <= req_dst_q;
req_q1 <= req_q0;
end
end
// Output assignments.
assign valid_o = (ack_dst_q != req_q1);
assign data_o = data_dst_q;
assign async_ack_o = ack_dst_q;
endmodule
/* verilator lint_on DECLFILENAME */
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the “License”); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
//
// Author: Florian Zaruba, ETH Zurich
// Date: 15/07/2017
// Description: A RISC-V privilege spec 1.11 (WIP) compatible CLINT (core local interrupt controller)
//
// Platforms provide a real-time counter, exposed as a memory-mapped machine-mode register, mtime. mtime must run at
// constant frequency, and the platform must provide a mechanism for determining the timebase of mtime (device tree).
module clint #(
parameter int unsigned AXI_ADDR_WIDTH = 64,
parameter int unsigned AXI_DATA_WIDTH = 64,
parameter int unsigned AXI_ID_WIDTH = 10,
parameter int unsigned NR_CORES = 1 // Number of cores therefore also the number of timecmp registers and timer interrupts
) (
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
input logic testmode_i,
input ariane_axi::req_t axi_req_i,
output ariane_axi::resp_t axi_resp_o,
input logic rtc_i, // Real-time clock in (usually 32.768 kHz)
output logic [NR_CORES-1:0] timer_irq_o, // Timer interrupts
output logic [NR_CORES-1:0] ipi_o // software interrupt (a.k.a inter-process-interrupt)
);
// register offset
localparam logic [15:0] MSIP_BASE = 16'h0;
localparam logic [15:0] MTIMECMP_BASE = 16'h4000;
localparam logic [15:0] MTIME_BASE = 16'hbff8;
localparam AddrSelWidth = (NR_CORES == 1) ? 1 : $clog2(NR_CORES);
// signals from AXI 4 Lite
logic [AXI_ADDR_WIDTH-1:0] address;
logic en;
logic we;
logic [63:0] wdata;
logic [63:0] rdata;
// bit 11 and 10 are determining the address offset
logic [15:0] register_address;
assign register_address = address[15:0];
// actual registers
logic [63:0] mtime_n, mtime_q;
logic [NR_CORES-1:0][63:0] mtimecmp_n, mtimecmp_q;
logic [NR_CORES-1:0] msip_n, msip_q;
// increase the timer
logic increase_timer;
// -----------------------------
// AXI Interface Logic
// -----------------------------
axi_lite_interface #(
.AXI_ADDR_WIDTH ( AXI_ADDR_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_ID_WIDTH ( AXI_ID_WIDTH )
) axi_lite_interface_i (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.axi_req_i ( axi_req_i ),
.axi_resp_o ( axi_resp_o ),
.address_o ( address ),
.en_o ( en ),
.we_o ( we ),
.data_i ( rdata ),
.data_o ( wdata )
);
// -----------------------------
// Register Update Logic
// -----------------------------
// APB register write logic
always_comb begin
mtime_n = mtime_q;
mtimecmp_n = mtimecmp_q;
msip_n = msip_q;
// RTC says we should increase the timer
if (increase_timer)
mtime_n = mtime_q + 1;
// written from APB bus - gets priority
if (en && we) begin
case (register_address) inside
[MSIP_BASE:MSIP_BASE+8*NR_CORES]: begin
msip_n[$unsigned(address[AddrSelWidth-1+3:3])] = wdata[0];
end
[MTIMECMP_BASE:MTIMECMP_BASE+8*NR_CORES]: begin
mtimecmp_n[$unsigned(address[AddrSelWidth-1+3:3])] = wdata;
end
MTIME_BASE: begin
mtime_n = wdata;
end
default:;
endcase
end
end
// APB register read logic
always_comb begin
rdata = 'b0;
if (en && !we) begin
case (register_address) inside
[MSIP_BASE:MSIP_BASE+8*NR_CORES]: begin
rdata = msip_q[$unsigned(address[AddrSelWidth-1+3:3])];
end
[MTIMECMP_BASE:MTIMECMP_BASE+8*NR_CORES]: begin
rdata = mtimecmp_q[$unsigned(address[AddrSelWidth-1+3:3])];
end
MTIME_BASE: begin
rdata = mtime_q;
end
default:;
endcase
end
end
// -----------------------------
// IRQ Generation
// -----------------------------
// The mtime register has a 64-bit precision on all RV32, RV64, and RV128 systems. Platforms provide a 64-bit
// memory-mapped machine-mode timer compare register (mtimecmp), which causes a timer interrupt to be posted when the
// mtime register contains a value greater than or equal (mtime >= mtimecmp) to the value in the mtimecmp register.
// The interrupt remains posted until it is cleared by writing the mtimecmp register. The interrupt will only be taken
// if interrupts are enabled and the MTIE bit is set in the mie register.
always_comb begin : irq_gen
// check that the mtime cmp register is set to a meaningful value
for (int unsigned i = 0; i < NR_CORES; i++) begin
if (mtime_q >= mtimecmp_q[i]) begin
timer_irq_o[i] = 1'b1;
end else begin
timer_irq_o[i] = 1'b0;
end
end
end
// -----------------------------
// RTC time tracking facilities
// -----------------------------
// 1. Put the RTC input through a classic two stage edge-triggered synchronizer to filter out any
// metastability effects (or at least make them unlikely :-))
sync_wedge i_sync_edge (
.clk_i,
.rst_ni,
.en_i ( ~testmode_i ),
.serial_i ( rtc_i ),
.r_edge_o ( increase_timer ),
.f_edge_o ( ), // left open
.serial_o ( ) // left open
);
// Registers
always_ff @(posedge clk_i or negedge rst_ni) begin
if (~rst_ni) begin
mtime_q <= 64'b0;
mtimecmp_q <= 'b0;
msip_q <= '0;
end else begin
mtime_q <= mtime_n;
mtimecmp_q <= mtimecmp_n;
msip_q <= msip_n;
end
end
assign ipi_o = msip_q;
// -------------
// Assertions
// --------------
//pragma translate_off
`ifndef VERILATOR
// Static assertion check for appropriate bus width
initial begin
assert (AXI_DATA_WIDTH == 64) else $fatal("Timer needs to interface with a 64 bit bus, everything else is not supported");
end
`endif
//pragma translate_on
endmodule
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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 cluster_clock_inverter
(
input logic clk_i,
output logic clk_o
);
assign clk_o = ~clk_i;
endmodule
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
//
// Author: Florian Zaruba, ETH Zurich
// Date: 08.05.2017
// Description: Flush controller
import ariane_pkg::*;
module controller (
input logic clk_i,
input logic rst_ni,
output logic set_pc_commit_o, // Set PC om PC Gen
output logic flush_if_o, // Flush the IF stage
output logic flush_unissued_instr_o, // Flush un-issued instructions of the scoreboard
output logic flush_id_o, // Flush ID stage
output logic flush_ex_o, // Flush EX stage
output logic flush_icache_o, // Flush ICache
output logic flush_dcache_o, // Flush DCache
input logic flush_dcache_ack_i, // Acknowledge the whole DCache Flush
output logic flush_tlb_o, // Flush TLBs
input logic halt_csr_i, // Halt request from CSR (WFI instruction)
output logic halt_o, // Halt signal to commit stage
input logic eret_i, // Return from exception
input logic ex_valid_i, // We got an exception, flush the pipeline
input logic set_debug_pc_i, // set the debug pc from CSR
input branchpredict_t resolved_branch_i, // We got a resolved branch, check if we need to flush the front-end
input logic flush_csr_i, // We got an instruction which altered the CSR, flush the pipeline
input logic fence_i_i, // fence.i in
input logic fence_i, // fence in
input logic sfence_vma_i, // We got an instruction to flush the TLBs and pipeline
input logic flush_commit_i // Flush request from commit stage
);
// active fence - high if we are currently flushing the dcache
logic fence_active_d, fence_active_q;
logic flush_dcache;
// ------------
// Flush CTRL
// ------------
always_comb begin : flush_ctrl
fence_active_d = fence_active_q;
set_pc_commit_o = 1'b0;
flush_if_o = 1'b0;
flush_unissued_instr_o = 1'b0;
flush_id_o = 1'b0;
flush_ex_o = 1'b0;
flush_dcache = 1'b0;
flush_icache_o = 1'b0;
flush_tlb_o = 1'b0;
// ------------
// Mis-predict
// ------------
// flush on mispredict
if (resolved_branch_i.is_mispredict) begin
// flush only un-issued instructions
flush_unissued_instr_o = 1'b1;
// and if stage
flush_if_o = 1'b1;
end
// ---------------------------------
// FENCE
// ---------------------------------
if (fence_i) begin
// this can be seen as a CSR instruction with side-effect
set_pc_commit_o = 1'b1;
flush_if_o = 1'b1;
flush_unissued_instr_o = 1'b1;
flush_id_o = 1'b1;
flush_ex_o = 1'b1;
flush_dcache = 1'b1;
fence_active_d = 1'b1;
end
// ---------------------------------
// FENCE.I
// ---------------------------------
if (fence_i_i) begin
set_pc_commit_o = 1'b1;
flush_if_o = 1'b1;
flush_unissued_instr_o = 1'b1;
flush_id_o = 1'b1;
flush_ex_o = 1'b1;
flush_icache_o = 1'b1;
flush_dcache = 1'b1;
fence_active_d = 1'b1;
end
// wait for the acknowledge here
if (flush_dcache_ack_i && fence_active_q) begin
fence_active_d = 1'b0;
// keep the flush dcache signal high as long as we didn't get the acknowledge from the cache
end else if (fence_active_q) begin
flush_dcache = 1'b1;
end
// ---------------------------------
// SFENCE.VMA
// ---------------------------------
if (sfence_vma_i) begin
set_pc_commit_o = 1'b1;
flush_if_o = 1'b1;
flush_unissued_instr_o = 1'b1;
flush_id_o = 1'b1;
flush_ex_o = 1'b1;
flush_tlb_o = 1'b1;
end
// Set PC to commit stage and flush pipleine
if (flush_csr_i || flush_commit_i) begin
set_pc_commit_o = 1'b1;
flush_if_o = 1'b1;
flush_unissued_instr_o = 1'b1;
flush_id_o = 1'b1;
flush_ex_o = 1'b1;
end
// ---------------------------------
// 1. Exception
// 2. Return from exception
// ---------------------------------
if (ex_valid_i || eret_i || set_debug_pc_i) begin
// don't flush pcgen as we want to take the exception: Flush PCGen is not a flush signal
// for the PC Gen stage but instead tells it to take the PC we gave it
set_pc_commit_o = 1'b0;
flush_if_o = 1'b1;
flush_unissued_instr_o = 1'b1;
flush_id_o = 1'b1;
flush_ex_o = 1'b1;
end
end
// ----------------------
// Halt Logic
// ----------------------
always_comb begin
// halt the core if the fence is active
halt_o = halt_csr_i || fence_active_q;
end
// ----------------------
// Registers
// ----------------------
always_ff @(posedge clk_i or negedge rst_ni) begin
if(~rst_ni) begin
fence_active_q <= 1'b0;
flush_dcache_o <= 1'b0;
end else begin
fence_active_q <= fence_active_d;
// register on the flush signal, this signal might be critical
flush_dcache_o <= flush_dcache;
end
end
endmodule
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
//
// Author: Florian Zaruba, ETH Zurich
// Date: 05.05.2017
// Description: Buffer to hold CSR address, this acts like a functional unit
// to the scoreboard.
import ariane_pkg::*;
module csr_buffer (
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
input logic flush_i,
input fu_data_t fu_data_i,
output logic csr_ready_o, // FU is ready e.g. not busy
input logic csr_valid_i, // Input is valid
output logic [63:0] csr_result_o,
input logic csr_commit_i, // commit the pending CSR OP
// to CSR file
output logic [11:0] csr_addr_o // CSR address to commit stage
);
// this is a single entry store buffer for the address of the CSR
// which we are going to need in the commit stage
struct packed {
logic [11:0] csr_address;
logic valid;
} csr_reg_n, csr_reg_q;
// control logic, scoreboard signals
assign csr_result_o = fu_data_i.operand_a;
assign csr_addr_o = csr_reg_q.csr_address;
// write logic
always_comb begin : write
csr_reg_n = csr_reg_q;
// by default we are ready
csr_ready_o = 1'b1;
// if we have a valid uncomiited csr req or are just getting one WITHOUT a commit in, we are not ready
if ((csr_reg_q.valid || csr_valid_i) && ~csr_commit_i)
csr_ready_o = 1'b0;
// if we got a valid from the scoreboard
// store the CSR address
if (csr_valid_i) begin
csr_reg_n.csr_address = fu_data_i.operand_b[11:0];
csr_reg_n.valid = 1'b1;
end
// if we get a commit and no new valid instruction -> clear the valid bit
if (csr_commit_i && ~csr_valid_i) begin
csr_reg_n.valid = 1'b0;
end
// clear the buffer if we flushed
if (flush_i)
csr_reg_n.valid = 1'b0;
end
// sequential process
always_ff @(posedge clk_i or negedge rst_ni) begin
if(~rst_ni) begin
csr_reg_q <= '{default: 0};
end else begin
csr_reg_q <= csr_reg_n;
end
end
endmodule
/* Copyright 2018 ETH Zurich and University of Bologna.
* Copyright and related rights are licensed under the Solderpad Hardware
* License, Version 0.51 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
* or agreed to in writing, software, hardware and materials distributed under
* this 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.
*
* File: $filename.v
*
* Description: Auto-generated bootrom
*/
// Auto-generated code
module debug_rom (
input logic clk_i,
input logic req_i,
input logic [63:0] addr_i,
output logic [63:0] rdata_o
);
localparam int RomSize = 19;
const logic [RomSize-1:0][63:0] mem = {
64'h00000000_7b200073,
64'h7b302573_7b202473,
64'h10852423_f1402473,
64'ha85ff06f_7b302573,
64'h7b202473_10052223,
64'h00100073_7b302573,
64'h10052623_00c51513,
64'h00c55513_00000517,
64'h7b351073_fd5ff06f,
64'hfa041ce3_00247413,
64'h40044403_00a40433,
64'hf1402473_02041c63,
64'h00147413_40044403,
64'h00a40433_10852023,
64'hf1402473_00c51513,
64'h00c55513_00000517,
64'h7b351073_7b241073,
64'h0ff0000f_04c0006f,
64'h07c0006f_00c0006f
};
logic [$clog2(RomSize)-1:0] addr_q;
always_ff @(posedge clk_i) begin
if (req_i) begin
addr_q <= addr_i[$clog2(RomSize)-1+3:3];
end
end
// this prevents spurious Xes from propagating into
// the speculative fetch stage of the core
assign rdata_o = (addr_q < RomSize) ? mem[addr_q] : '0;
endmodule
/* Copyright 2018 ETH Zurich and University of Bologna.
* Copyright and related rights are licensed under the Solderpad Hardware
* License, Version 0.51 (the “License”); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
* or agreed to in writing, software, hardware and materials distributed under
* this 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.
*
* File: dm_pkg.sv
* Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
* Date: 30.6.2018
*
* Description: Debug-module package, contains common system definitions.
*
*/
package dm;
localparam logic [3:0] DbgVersion013 = 4'h2;
// size of program buffer in junks of 32-bit words
localparam logic [4:0] ProgBufSize = 5'h8;
// TODO(zarubaf) This is hard-coded to two at the moment
// amount of data count registers implemented
localparam logic [3:0] DataCount = 4'h2;
// address to which a hart should jump when it was requested to halt
localparam logic [63:0] HaltAddress = 64'h800;
localparam logic [63:0] ResumeAddress = HaltAddress + 4;
localparam logic [63:0] ExceptionAddress = HaltAddress + 8;
// address where data0-15 is shadowed or if shadowed in a CSR
// address of the first CSR used for shadowing the data
localparam logic [11:0] DataAddr = 12'h380; // we are aligned with Rocket here
// debug registers
typedef enum logic [7:0] {
Data0 = 8'h04,
Data1 = 8'h05,
Data2 = 8'h06,
Data3 = 8'h07,
Data4 = 8'h08,
Data5 = 8'h09,
Data6 = 8'h0A,
Data7 = 8'h0B,
Data8 = 8'h0C,
Data9 = 8'h0D,
Data10 = 8'h0E,
Data11 = 8'h0F,
DMControl = 8'h10,
DMStatus = 8'h11, // r/o
Hartinfo = 8'h12,
HaltSum1 = 8'h13,
HAWindowSel = 8'h14,
HAWindow = 8'h15,
AbstractCS = 8'h16,
Command = 8'h17,
AbstractAuto = 8'h18,
DevTreeAddr0 = 8'h19,
DevTreeAddr1 = 8'h1A,
DevTreeAddr2 = 8'h1B,
DevTreeAddr3 = 8'h1C,
NextDM = 8'h1D,
ProgBuf0 = 8'h20,
ProgBuf15 = 8'h2F,
AuthData = 8'h30,
HaltSum2 = 8'h34,
HaltSum3 = 8'h35,
SBAddress3 = 8'h37,
SBCS = 8'h38,
SBAddress0 = 8'h39,
SBAddress1 = 8'h3A,
SBAddress2 = 8'h3B,
SBData0 = 8'h3C,
SBData1 = 8'h3D,
SBData2 = 8'h3E,
SBData3 = 8'h3F,
HaltSum0 = 8'h40
} dm_csr_t;
// debug causes
localparam logic [2:0] CauseBreakpoint = 3'h1;
localparam logic [2:0] CauseTrigger = 3'h2;
localparam logic [2:0] CauseRequest = 3'h3;
localparam logic [2:0] CauseSingleStep = 3'h4;
typedef struct packed {
logic [31:23] zero1;
logic impebreak;
logic [21:20] zero0;
logic allhavereset;
logic anyhavereset;
logic allresumeack;
logic anyresumeack;
logic allnonexistent;
logic anynonexistent;
logic allunavail;
logic anyunavail;
logic allrunning;
logic anyrunning;
logic allhalted;
logic anyhalted;
logic authenticated;
logic authbusy;
logic hasresethaltreq;
logic devtreevalid;
logic [3:0] version;
} dmstatus_t;
typedef struct packed {
logic haltreq;
logic resumereq;
logic hartreset;
logic ackhavereset;
logic zero1;
logic hasel;
logic [25:16] hartsello;
logic [15:6] hartselhi;
logic [5:4] zero0;
logic setresethaltreq;
logic clrresethaltreq;
logic ndmreset;
logic dmactive;
} dmcontrol_t;
typedef struct packed {
logic [31:24] zero1;
logic [23:20] nscratch;
logic [19:17] zero0;
logic dataaccess;
logic [15:12] datasize;
logic [11:0] dataaddr;
} hartinfo_t;
typedef enum logic [2:0] { CmdErrNone, CmdErrBusy, CmdErrNotSupported,
CmdErrorException, CmdErrorHaltResume,
CmdErrorBus, CmdErrorOther = 7
} cmderr_t;
typedef struct packed {
logic [31:29] zero3;
logic [28:24] progbufsize;
logic [23:13] zero2;
logic busy;
logic zero1;
cmderr_t cmderr;
logic [7:4] zero0;
logic [3:0] datacount;
} abstractcs_t;
typedef enum logic [7:0] {
AccessRegister = 8'h0,
QuickAccess = 8'h1,
AccessMemory = 8'h2
} cmd_t;
typedef struct packed {
cmd_t cmdtype;
logic [23:0] control;
} command_t;
typedef struct packed {
logic [31:16] autoexecprogbuf;
logic [15:12] zero0;
logic [11:0] autoexecdata;
} abstractauto_t;
typedef struct packed {
logic zero1;
logic [22:20] aarsize;
logic zero0;
logic postexec;
logic transfer;
logic write;
logic [15:0] regno;
} ac_ar_cmd_t;
// DTM
typedef enum logic [1:0] {
DTM_NOP = 2'h0,
DTM_READ = 2'h1,
DTM_WRITE = 2'h2
} dtm_op_t;
typedef struct packed {
logic [31:29] sbversion;
logic [28:23] zero0;
logic sbbusyerror;
logic sbbusy;
logic sbreadonaddr;
logic [19:17] sbaccess;
logic sbautoincrement;
logic sbreadondata;
logic [14:12] sberror;
logic [11:5] sbasize;
logic sbaccess128;
logic sbaccess64;
logic sbaccess32;
logic sbaccess16;
logic sbaccess8;
} sbcs_t;
localparam logic[1:0] DTM_SUCCESS = 2'h0;
typedef struct packed {
logic [6:0] addr;
dtm_op_t op;
logic [31:0] data;
} dmi_req_t;
typedef struct packed {
logic [31:0] data;
logic [1:0] resp;
} dmi_resp_t;
endpackage
/* Copyright 2018 ETH Zurich and University of Bologna.
* Copyright and related rights are licensed under the Solderpad Hardware
* License, Version 0.51 (the “License”); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
* or agreed to in writing, software, hardware and materials distributed under
* this 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.
*
* File: dm_sba.sv
* Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
* Date: 1.8.2018
*
* Description: System Bus Access Module
*
*/
module dm_sba (
input logic clk_i, // Clock
input logic rst_ni,
input logic dmactive_i, // synchronous reset active low
// AXI port
output ariane_axi::req_t axi_req_o,
input ariane_axi::resp_t axi_resp_i,
input logic [63:0] sbaddress_i,
input logic sbaddress_write_valid_i,
// control signals in
input logic sbreadonaddr_i,
output logic [63:0] sbaddress_o,
input logic sbautoincrement_i,
input logic [2:0] sbaccess_i,
// data in
input logic sbreadondata_i,
input logic [63:0] sbdata_i,
input logic sbdata_read_valid_i,
input logic sbdata_write_valid_i,
// read data out
output logic [63:0] sbdata_o,
output logic sbdata_valid_o,
// control signals
output logic sbbusy_o,
output logic sberror_valid_o, // bus error occurred
output logic [2:0] sberror_o // bus error occurred
);
enum logic [2:0] { Idle, Read, Write, WaitRead, WaitWrite } state_d, state_q;
logic [63:0] address;
logic req;
logic gnt;
logic we;
logic [7:0] be;
assign sbbusy_o = (state_q != Idle) ? 1'b1 : 1'b0;
always_comb begin
req = 1'b0;
address = sbaddress_i;
we = 1'b0;
be = '0;
sberror_o = '0;
sberror_valid_o = 1'b0;
sbaddress_o = sbaddress_i;
state_d = state_q;
case (state_q)
Idle: begin
// debugger requested a read
if (sbaddress_write_valid_i && sbreadonaddr_i) state_d = Read;
// debugger requested a write
if (sbdata_write_valid_i) state_d = Write;
// perform another read
if (sbdata_read_valid_i && sbreadondata_i) state_d = Read;
end
Read: begin
req = 1'b1;
if (gnt) state_d = WaitRead;
end
Write: begin
req = 1'b1;
we = 1'b1;
// generate byte enable mask
case (sbaccess_i)
3'b000: be[ sbaddress_i[2:0]] = '1;
3'b001: be[{sbaddress_i[2:1], 1'b0} +: 2] = '1;
3'b010: be[{sbaddress_i[2:2], 2'b0} +: 4] = '1;
3'b011: be = '1;
default:;
endcase
if (gnt) state_d = WaitWrite;
end
WaitRead: begin
if (sbdata_valid_o) begin
state_d = Idle;
// auto-increment address
if (sbautoincrement_i) sbaddress_o = sbaddress_i + (1 << sbaccess_i);
end
end
WaitWrite: begin
if (sbdata_valid_o) begin
state_d = Idle;
// auto-increment address
if (sbautoincrement_i) sbaddress_o = sbaddress_i + (1 << sbaccess_i);
end
end
endcase
// handle error case
if (sbaccess_i > 3 && state_q != Idle) begin
req = 1'b0;
state_d = Idle;
sberror_valid_o = 1'b1;
sberror_o = 'd3;
end
// further error handling should go here ...
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (~rst_ni) begin
state_q <= Idle;
end else begin
state_q <= state_d;
end
end
axi_adapter #(
.DATA_WIDTH ( 64 )
) i_axi_master (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.req_i ( req ),
.type_i ( ariane_axi::SINGLE_REQ ),
.gnt_o ( gnt ),
.gnt_id_o ( ),
.addr_i ( address ),
.we_i ( we ),
.wdata_i ( sbdata_i ),
.be_i ( be ),
.size_i ( sbaccess_i[1:0] ),
.id_i ( '0 ),
.valid_o ( sbdata_valid_o ),
.rdata_o ( sbdata_o ),
.id_o ( ),
.critical_word_o ( ), // not needed here
.critical_word_valid_o ( ), // not needed here
.axi_req_o,
.axi_resp_i
);
//pragma translate_off
`ifndef VERILATOR
// maybe bump severity to $error if not handled at runtime
dm_sba_access_size: assert property(@(posedge clk_i) disable iff (dmactive_i !== 1'b0) (state_d != Idle) |-> (sbaccess_i < 4)) else $warning ("accesses > 8 byte not supported at the moment");
`endif
//pragma translate_on
endmodule
/* Copyright 2018 ETH Zurich and University of Bologna.
* Copyright and related rights are licensed under the Solderpad Hardware
* License, Version 0.51 (the “License”); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
* or agreed to in writing, software, hardware and materials distributed under
* this 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.
*
* File: axi_riscv_debug_module.sv
* Author: Andreas Traber <atraber@iis.ee.ethz.ch>
* Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
*
* Description: Clock domain crossings for JTAG to DMI very heavily based
* on previous work by Andreas Traber for the PULP project.
* This is mainly a wrapper around the existing CDCs.
*/
module dmi_cdc (
// JTAG side (master side)
input logic tck_i,
input logic trst_ni,
input dm::dmi_req_t jtag_dmi_req_i,
output logic jtag_dmi_ready_o,
input logic jtag_dmi_valid_i,
output dm::dmi_resp_t jtag_dmi_resp_o,
output logic jtag_dmi_valid_o,
input logic jtag_dmi_ready_i,
// core side (slave side)
input logic clk_i,
input logic rst_ni,
output dm::dmi_req_t core_dmi_req_o,
output logic core_dmi_valid_o,
input logic core_dmi_ready_i,
input dm::dmi_resp_t core_dmi_resp_i,
output logic core_dmi_ready_o,
input logic core_dmi_valid_i
);
cdc_2phase #(.T(dm::dmi_req_t)) i_cdc_req (
.src_rst_ni ( trst_ni ),
.src_clk_i ( tck_i ),
.src_data_i ( jtag_dmi_req_i ),
.src_valid_i ( jtag_dmi_valid_i ),
.src_ready_o ( jtag_dmi_ready_o ),
.dst_rst_ni ( rst_ni ),
.dst_clk_i ( clk_i ),
.dst_data_o ( core_dmi_req_o ),
.dst_valid_o ( core_dmi_valid_o ),
.dst_ready_i ( core_dmi_ready_i )
);
cdc_2phase #(.T(dm::dmi_resp_t)) i_cdc_resp (
.src_rst_ni ( rst_ni ),
.src_clk_i ( clk_i ),
.src_data_i ( core_dmi_resp_i ),
.src_valid_i ( core_dmi_valid_i ),
.src_ready_o ( core_dmi_ready_o ),
.dst_rst_ni ( trst_ni ),
.dst_clk_i ( tck_i ),
.dst_data_o ( jtag_dmi_resp_o ),
.dst_valid_o ( jtag_dmi_valid_o ),
.dst_ready_i ( jtag_dmi_ready_i )
);
endmodule
/* Copyright 2018 ETH Zurich and University of Bologna.
* Copyright and related rights are licensed under the Solderpad Hardware
* License, Version 0.51 (the “License”); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
* or agreed to in writing, software, hardware and materials distributed under
* this 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.
*
* File: axi_riscv_debug_module.sv
* Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
* Date: 19.7.2018
*
* Description: JTAG DMI (debug module interface)
*
*/
module dmi_jtag (
input logic clk_i, // DMI Clock
input logic rst_ni, // Asynchronous reset active low
input logic testmode_i,
output logic dmi_rst_no, // hard reset
output dm::dmi_req_t dmi_req_o,
output logic dmi_req_valid_o,
input logic dmi_req_ready_i,
input dm::dmi_resp_t dmi_resp_i,
output logic dmi_resp_ready_o,
input logic dmi_resp_valid_i,
input logic tck_i, // JTAG test clock pad
input logic tms_i, // JTAG test mode select pad
input logic trst_ni, // JTAG test reset pad
input logic td_i, // JTAG test data input pad
output logic td_o, // JTAG test data output pad
output logic tdo_oe_o // Data out output enable
);
assign dmi_rst_no = rst_ni;
logic test_logic_reset;
logic shift_dr;
logic update_dr;
logic capture_dr;
logic dmi_access;
logic dtmcs_select;
logic dmi_reset;
logic dmi_tdi;
logic dmi_tdo;
dm::dmi_req_t dmi_req;
logic dmi_req_ready;
logic dmi_req_valid;
dm::dmi_resp_t dmi_resp;
logic dmi_resp_valid;
logic dmi_resp_ready;
typedef struct packed {
logic [6:0] address;
logic [31:0] data;
logic [1:0] op;
} dmi_t;
typedef enum logic [1:0] {
DMINoError = 2'h0, DMIReservedError = 2'h1,
DMIOPFailed = 2'h2, DMIBusy = 2'h3
} dmi_error_t;
enum logic [2:0] { Idle, Read, WaitReadValid, Write, WaitWriteValid } state_d, state_q;
logic [$bits(dmi_t)-1:0] dr_d, dr_q;
logic [6:0] address_d, address_q;
logic [31:0] data_d, data_q;
dmi_t dmi;
assign dmi = dmi_t'(dr_q);
assign dmi_req.addr = address_q;
assign dmi_req.data = data_q;
assign dmi_req.op = (state_q == Write) ? dm::DTM_WRITE : dm::DTM_READ;
// we'will always be ready to accept the data we requested
assign dmi_resp_ready = 1'b1;
logic error_dmi_busy;
dmi_error_t error_d, error_q;
always_comb begin
error_dmi_busy = 1'b0;
// default assignments
state_d = state_q;
address_d = address_q;
data_d = data_q;
error_d = error_q;
dmi_req_valid = 1'b0;
case (state_q)
Idle: begin
// make sure that no error is sticky
if (dmi_access && update_dr && (error_q == DMINoError)) begin
// save address and value
address_d = dmi.address;
data_d = dmi.data;
if (dm::dtm_op_t'(dmi.op) == dm::DTM_READ) begin
state_d = Read;
end else if (dm::dtm_op_t'(dmi.op) == dm::DTM_WRITE) begin
state_d = Write;
end
// else this is a nop and we can stay here
end
end
Read: begin
dmi_req_valid = 1'b1;
if (dmi_req_ready) begin
state_d = WaitReadValid;
end
end
WaitReadValid: begin
// load data into register and shift out
if (dmi_resp_valid) begin
data_d = dmi_resp.data;
state_d = Idle;
end
end
Write: begin
dmi_req_valid = 1'b1;
// got a valid answer go back to idle
if (dmi_req_ready) begin
state_d = Idle;
end
end
WaitWriteValid: begin
// just wait for idle here
if (dmi_resp_valid) begin
state_d = Idle;
end
end
endcase
// update_dr means we got another request but we didn't finish
// the one in progress, this state is sticky
if (update_dr && state_q != Idle) begin
error_dmi_busy = 1'b1;
end
// if capture_dr goes high while we are in the read state
// or in the corresponding wait state we are not giving back a valid word
// -> throw an error
if (capture_dr && state_q inside {Read, WaitReadValid}) begin
error_dmi_busy = 1'b1;
end
if (error_dmi_busy) begin
error_d = DMIBusy;
end
// clear sticky error flag
if (dmi_reset && dtmcs_select) begin
error_d = DMINoError;
end
end
// shift register
assign dmi_tdo = dr_q[0];
always_comb begin
dr_d = dr_q;
if (capture_dr) begin
if (dmi_access) begin
if (error_q == DMINoError && !error_dmi_busy) begin
dr_d = {address_q, data_q, DMINoError};
// DMI was busy, report an error
end else if (error_q == DMIBusy || error_dmi_busy) begin
dr_d = {address_q, data_q, DMIBusy};
end
end
end
if (shift_dr) begin
if (dmi_access) dr_d = {dmi_tdi, dr_q[$bits(dr_q)-1:1]};
end
if (test_logic_reset) begin
dr_d = '0;
end
end
always_ff @(posedge tck_i or negedge trst_ni) begin
if (~trst_ni) begin
dr_q <= '0;
state_q <= Idle;
address_q <= '0;
data_q <= '0;
error_q <= DMINoError;
end else begin
dr_q <= dr_d;
state_q <= state_d;
address_q <= address_d;
data_q <= data_d;
error_q <= error_d;
end
end
// ---------
// TAP
// ---------
dmi_jtag_tap #(
.IrLength (5)
) i_dmi_jtag_tap (
.tck_i,
.tms_i,
.trst_ni,
.td_i,
.td_o,
.tdo_oe_o,
.testmode_i ( testmode_i ),
.test_logic_reset_o ( test_logic_reset ),
.shift_dr_o ( shift_dr ),
.update_dr_o ( update_dr ),
.capture_dr_o ( capture_dr ),
.dmi_access_o ( dmi_access ),
.dtmcs_select_o ( dtmcs_select ),
.dmi_reset_o ( dmi_reset ),
.dmi_error_i ( error_q ),
.dmi_tdi_o ( dmi_tdi ),
.dmi_tdo_i ( dmi_tdo )
);
// ---------
// CDC
// ---------
dmi_cdc i_dmi_cdc (
// JTAG side (master side)
.tck_i,
.trst_ni,
.jtag_dmi_req_i ( dmi_req ),
.jtag_dmi_ready_o ( dmi_req_ready ),
.jtag_dmi_valid_i ( dmi_req_valid ),
.jtag_dmi_resp_o ( dmi_resp ),
.jtag_dmi_valid_o ( dmi_resp_valid ),
.jtag_dmi_ready_i ( dmi_resp_ready ),
// core side
.clk_i,
.rst_ni,
.core_dmi_req_o ( dmi_req_o ),
.core_dmi_valid_o ( dmi_req_valid_o ),
.core_dmi_ready_i ( dmi_req_ready_i ),
.core_dmi_resp_i ( dmi_resp_i ),
.core_dmi_ready_o ( dmi_resp_ready_o ),
.core_dmi_valid_i ( dmi_resp_valid_i )
);
endmodule
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
// Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
/* verilator lint_off DECLFILENAME */
module fifo #(
parameter bit FALL_THROUGH = 1'b0, // fifo is in fall-through mode
parameter int unsigned DATA_WIDTH = 32, // default data width if the fifo is of type logic
parameter int unsigned DEPTH = 8, // depth can be arbitrary from 0 to 2**32
parameter int unsigned THRESHOLD = 1, // fill count until when to assert threshold_o
parameter type dtype = logic [DATA_WIDTH-1:0]
)(
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
input logic flush_i, // flush the queue
input logic testmode_i, // test_mode to bypass clock gating
// status flags
output logic full_o, // queue is full
output logic empty_o, // queue is empty
output logic threshold_o, // the FIFO is above the specified threshold
// as long as the queue is not full we can push new data
input dtype data_i, // data to push into the queue
input logic push_i, // data is valid and can be pushed to the queue
// as long as the queue is not empty we can pop new elements
output dtype data_o, // output data
input logic pop_i // pop head from queue
);
fifo_v2 #(
.FALL_THROUGH ( FALL_THROUGH ),
.DATA_WIDTH ( DATA_WIDTH ),
.DEPTH ( DEPTH ),
.ALM_FULL_TH ( THRESHOLD ),
.dtype ( dtype )
) impl (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.flush_i ( flush_i ),
.testmode_i ( testmode_i ),
.full_o ( full_o ),
.empty_o ( empty_o ),
.alm_full_o ( threshold_o ),
.alm_empty_o ( ),
.data_i ( data_i ),
.push_i ( push_i ),
.data_o ( data_o ),
.pop_i ( pop_i )
);
endmodule
/* verilator lint_on DECLFILENAME */
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment