Commit 0f1a7547 authored by Grzegorz Daniluk's avatar Grzegorz Daniluk

Merge branch 'greg-swcore' into proposed_master

parents 5f6ac509 1a662f42
......@@ -8,6 +8,8 @@
files = [
"swc_wbgen2_pkg.vhd",
"swc_wishbone_slave.vhd",
"swc_core.vhd",
"swc_multiport_linked_list.vhd",
......@@ -35,7 +37,7 @@ files = [
];
modules = {"local": ["mpm"]}
modules = {"local": ["mpm", "Switched-Multiported-RAM"]}
if (action == "simulation"):
......
Copyright (c) 2014, the University of British Columbia. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the University of British Columbia (UBC) nor the names
of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OF BRITISH COLUMBIA BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
files = [ "utils.vh", "dpram.v", "dpram_bbs.v", "lvt_1ht.v", "lvt_bin.v",
"lvt_reg.v", "mpram_lvt.v", "mpram_reg.v", "mrram.v", "mrram_swt.v" ]
####################################################################################
Copyright (c) 2014, University of British Columbia (UBC) All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the University of British Columbia (UBC) nor the names
of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL University of British Columbia (UBC) BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
####################################################################################
####################################################################################
Switched SRAM-based Multi-ported RAM; University of British Columbia, 2014
Author: Ameer M.S. Abdelhadi (ameer@ece.ubc.ca, ameer.abdelhadi@gmail.com)
A fully parameterized and generic Verilog implementation of the suggested
modular switched multi-ported SRAM-based memory, together with previous
approaches are provided as open source hardware. A run-in-batch flow
manager to simulate and synthesize various designs with various
parameters in batch using Altera's ModelSim and Quartus is also provided.
LICENSE: BSD 3-Clause ("BSD New" or "BSD Simplified") license.
####################################################################################
####################################################################################
This package is part of a journal paper submission for :
ACM Transactions on Reconfigurable Technology and Systems (TRETS)
Special Issue on Reconfigurable Components with Source Code.
Paper title: Modular Switched Multi-ported SRAM-based Memory
Authors: Ameer M. S. Abdelhadi and Guy G. F. Lemieux - UBC
####################################################################################
####################################################################################
CAD Tools Requirements:
=======================
This project has been tested intensively using Altera's Design Suite version 14.0
Specifically:
1) Quartus II version 14.0 has been used to synthesize the Verilog implementation
2) ModelSim Altera Edition version 10.0d (modelsim_ase) has been used to simulate
the Verilog implementation.
Furthermore, the run-in-batch synthesis and simulation flow managers have been
implemented using C-Shell, hence a /bin/csh should be available in the machine
####################################################################################
####################################################################################
Files and directories in this package:
======================================
- README : This file!
- LICENSE : BSD 3-Clause ("BSD New" or "BSD Simplified") license.
- altera.12.0.ubc.csh: C-shell script: Setup environment variables and Altera 12.0
CAD flow from The University of British Columbia (UBC).
Change parameters to your environment if required.
- altera.13.1.ubc.csh: C-shell script: Setup environment variables and Altera 13.1
CAD flow from The University of British Columbia (UBC).
- altera.14.0.ubc.csh: C-shell script: Setup environment variables and Altera 14.0
CAD flow from The University of British Columbia (UBC).
- altera.14.0.fab.csh: C-shell script: Setup environment variables and Altera 14.0
CAD flow from FAbRIC (FPGA Research Infrastructure Cloud);
Texas Advanced Computing Center (TACC); UT Austin
https://wikis.utexas.edu/display/fabric/Home
- sim : C-shell script: A run-in-batch simulation flow manager .
- syn : C-shell script: A run-in-batch synthesis flow manager.
- config.vh : Verilog: Generated by 'syn', contains design parameters.
- utils.vh : Verilog: Design pre-compile utilities.
- mrram.v : Verilog: Multiread-RAM based on bank replication using
generic dual-ported RAM with optional single-stage
or two-stage bypass/ for normal mode ports.
- mrram_swt.v : Verilog: Multiread-RAM based on bank replication using
generic dual-ported RAM with optional single-stage
or two-stage bypass and switched read ports support.
- dpram.v : Verilog: Generic dual-ported RAM .
- dpram_bbs.v : Verilog: Generic dual-ported RAM with optional single-stage
or two-stage bypass.
- mpram_reg.v : Verilog: Generic register-based multiported-RAM. Reading
addresses are registered and old data will be read
in case of RAW. Implemented in FF's if the number
of reading or writing ports exceeds one.
- mpram_xor.v : Verilog: Multiported-RAM based on XOR implementation.
- lvt_reg.v : Verilog: Register-based binary-coded LVT (Live-Value-Table).
- lvt_bin.v : Verilog: Binary-coded I-LVT (Invalidation Live-Value-Table).
- lvt_1ht.v : Verilog: Onehot-coded I-LVT (Invalidation Live-Value-Table).
- mpram_lvt.v : Verilog: LVT/I-LVT-based Multiported-RAM for register-base
and SRAM-based one-hot/binary-coded I-LVT.
- smpram.v : Verilog: Switched multiported-RAM: register-based, XOR-based
,register-based LVT, SRAM-based binary-coded and
one-hot-coded I-LVT.
- smpram_tb.v : Verilog: Switched multiported-RAM testbench.
- smpram.qpf : Quartus II Project File.
- smpram.qsf : Quartus II Settings File.
- sim.res : A list of simulation results, each run in a separate line,
including all architectures.
- syn.res : A list of synthesis results, each run in a separate line,
including: frequency, resources usage, and runtime.
- log/ : A directory containing Altera's logs and reports.
- syn.res.example : Example synthesis results.
- sim.res.example : Example simulation results.
- log.example.tar.xz : xz tarball: archived log directory example
(for the runs listed in syn.res.example).
To extract invoke: tar -xavf log.example.tar.xz
####################################################################################
####################################################################################
Switched multi-ported RAM module instantiation:
===============================================
All *.v & *.vh files in this package should be copied into your work directory.
Copy the following instantiation into your Verilog design, change parameters and
connectivity to fit your design.
// instantiate a multiported-RAM
mpram #(
// parameters
.MEMD (MEMD ), // positive integer: memory depth
.DATW (DATW ), // positive integer: data width
.nRPF (nRPF ), // positive integer: # fixed read ports (nRPF>=1 )
.nWPF (nWPF ), // positive integer: # fixed write ports (nWPF>=0 )
.nRPS (nRPS ), // positive integer: # switched read ports (nRPS<=nRPF )
.nWPS (nWPS ), // positive integer: # switched write ports (nWPS>=0; nWPF+nWPS>=1)
.ARCH (ARCH ), // string: multi-port RAM architecture:
// "AUTO" : Choose automatically
// "REG" : Register-based
// "XOR" : XOR-based
// "LVTREG": Register-based LVT
// "LVTBIN": Binary-coded I-LVT-based
// "LVT1HT": Onehot-coded I-LVT-based
.BYPS (BYPS ), // string: Bypassing type:
// "WAW": Allow Write-After-Write
// "RAW": New data for Read-after-Write
// "RDW": New data for Read-During-Write
.FILE ("" ) // text: initialization file, optional
) mpram_inst (
// ports
.clk (clk ), // clock - input
.rdWr (rdWr ), // switch read/write (write is active low) - input
// the following ports are packed from nWPF fixed & nWPS switched ports
.WEnb (WEnb ), // write enables - input : [ (nWPF+nWPS)-1:0]
.WAddr(WAddr), // write addresses - input : [`log2(MEMD)*(nWPF+nWPS)-1:0]
.WData(WData), // write data - input : [DATW *(nWPF+nWPS)-1:0]
.RAddr(RAddr), // read addresses - input : [`log2(MEMD)*(nRPF+nRPS)-1:0]
.RData(RData) // read data - output: [DATW *(nRPF+nRPS)-1:0]
);
####################################################################################
####################################################################################
`sim`: A Run-in-batch Simulation Flow Manager
=============================================
USAGE:
./sim <Depth List> <Width List> <#Write Ports List (Fixed-Switched)> \
<#Read Ports List (Fixed-Switched)> <Bypass List> <#Cycles> [verbose]
- Use a comma delimited list.
- No spaces.
- May be surrounded by any brackets (), [], {}, or <>.
- RAM depth, data width, and simulation cycles are positive integers.
- Numbers of read and write ports are:
- Pairs of "fixed-switched" port numbers delimited with hyphen "-", or,
- Fixed port number only, if switched ports are not required.
* numbers of read/write ports are integers.
* #switched_read_ports < = #fixed_read_ports
- Bypassing type is one of: NON, WAW, RAW, or RDW.
- NON: No bypassing logic
- WAW: Allow Write-After-Write
- RAW: new data for Read-after-Write
- RDW: new data for Read-During-Write
- "verbose" is an optional argument; use if verbosed logging is required
EXAMPLES:
./sim 1024 32 1-2 2-2 NON 1000000 verbose
Simulate 1M cycles of a 1K lines RAM, 32 bits width, 1 fixed / 2 switched
write & 2 fixed / 2 switched read ports, no bypassing, verbose logging,
./sim 512,1024 8,16,32 2,3,4 1,2,3,4 RAW 1000000
Simulate 1M cycles of RAMs with 512 or 1024 lines, 8, 16, or 32 bits width,
2,3, or 4 fixed write ports, 1,2,3, or 4 fixed read ports, with RAW bypass.
The following files and directories will be created after simulation :
- sim.res : A list of simulation results, each run in a separate line,
including all design styles.
####################################################################################
####################################################################################
syn: A Run-in-batch Synthesis Flow Manager
==========================================
USAGE:
./syn <Depth List> <Width List> <#Write Ports List (Fixed-Switched)> \
<#Read Ports List (Fixed-Switched)> <Bypass List> <Architecture List>
- Use a comma delimited list.
- No spaces.
- May be surrounded by any brackets (), [], {}, or <>.
- RAM depth, data width, and simulation cycles are positive integers.
- Numbers of read and write ports are:
- Pairs of "fixed-switched" port numbers delimited with hyphen "-", or,
- Fixed port number only, if switched ports are not required.
* numbers of read/write ports are integers.
* #switched_read_ports < = #fixed_read_ports
- Bypassing type is one of: NON, WAW, RAW, or RDW.
- NON: No bypassing logic
- WAW: Allow Write-After-Write
- RAW: new data for Read-after-Write
- RDW: new data for Read-During-Write
- Architecture is one of: REG, XOR, LVTREG, LVTBIN, or LVT1HT.
- REG : Register-based multi-ported RAM
- XOR : XOR-based multi-ported RAM
- LVTREG: Register-based LVT multi-ported RAM
- LVTBIN: Binary-coded I-LVT-based multi-ported RAM
- LVT1HT: Onehot-coded I-LVT-based multi-ported RAM
EXAMPLES:
./syn 1024 32 1-2 2-2 NON XOR
Synthesis a XOR-based RAM with no bypassing, 1K lines RAM, 32 bits width,
1 fixed / 2 switched write and 2 fixed / 2 switched read ports.
./syn 512,1024 16,32 3,4 2,3 RAW,RDW LVTBIN,LVT1HT
Synthesis LVTBIN & LVT1HT RAM with new data RAW & RDW bypassing, 512 & 1024
lines, 16 & 32 data width, 3 & 4 fixed write ports, 2 & 3 fixed read ports.
The following files and directories will be created after compilation:
- syn.res : A list of results, each run in a separate line, including:
frequency, resources usage, and runtime
- log/ : Altera's logs and reports
####################################################################################
## Switched Multi-ported SRAM-based Memories ##
## Ameer M. S. Abdelhadi and Guy G. F. Lemieux ##
## The University of British Columbia (UBC) 2014 ##
## { ameer.abdelhadi; guy.lemieux } @ gmail.com ##
A fully parameterized and generic Verilog implementation of the suggested modular switched multi-ported SRAM-based memory, together with previous approaches are provided as open source hardware. A run-in-batch flow manager to simulate and synthesize various designs with various parameters in batch using Altera's ModelSim and Quartus is also provided.
**LICENSE:** BSD 3-Clause ("BSD New" or "BSD Simplified") license.
This package is part of a journal paper submission to:
**ACM Transactions on Reconfigurable Technology and Systems (TRETS); Special Issue on Reconfigurable Components with Source Code.**
* **Paper title:** Modular Switched Multi-ported SRAM-based Memory
* **Authors**: Ameer M.S. Abdelhadi and Guy G.F. Lemieux - UBC
---
## CAD Tools Requirements ##
This project has been tested intensively using Altera's Design Suite version 14.0 Specifically:
1. Quartus II version 14.0 has been used to synthesize the Verilog implementation
1. ModelSim Altera Edition version 10.0d (modelsim\_ase) has been used to simulate the Verilog implementation.
Furthermore, the run-in-batch synthesis and simulation flow managers have been implemented using C-Shell, hence a /bin/csh should be available in the machine
---
## Files and directories in this package ##
* **README:** Read this first!
* **LICENSE:** BSD 3-Clause ("BSD New" or "BSD Simplified") license.
* **altera.12.0.ubc.csh:** C-shell script: Setup environment variables and Altera 12.0 CAD flow from The University of British Columbia (UBC). Change parameters to your environment if required.
* **altera.13.1.ubc.csh:** C-shell script: Setup environment variables and Altera 13.1 CAD flow from The University of British Columbia (UBC).
* **altera.14.0.ubc.csh:** C-shell script: Setup environment variables and Altera 14.0 CAD flow from The University of British Columbia (UBC).
* **altera.14.0.fab.csh:** C-shell script: Setup environment variables and Altera 14.0 CAD flow from FAbRIC (FPGA Research Infrastructure Cloud); Texas Advanced Computing Center (TACC); UT Austin - https://wikis.utexas.edu/display/fabric/Home
* **sim:** C-shell script: A run-in-batch simulation flow manager .
* **syn:** C-shell script: A run-in-batch synthesis flow manager.
* **config.vh:** Verilog: Generated by 'syn' script, contains design parameters.
* **utils.vh:** Verilog: Design pre-compile utilities.
* **mrram.v:** Verilog: Multiread-RAM based on bank replication using generic dual-ported RAM with optional single-stage or two-stage bypass/ for normal mode ports.
* **mrram\_swt.v:** Verilog: Multiread-RAM based on bank replication using generic dual-ported RAM with optional single-stage or two-stage bypass and switched read ports support.
* **dpram.v:** Verilog: Generic dual-ported RAM .
* **dpram\_bbs.v:** Verilog: Generic dual-ported RAM with optional single-stage or two-stage bypass.
* **mpram\_reg.v:** Verilog: Generic register-based multiported-RAM. Reading addresses are registered and old data will be read in case of RAW. Implemented in FF's if the number of reading or writing ports exceeds one.
* **mpram\_xor.v:** Verilog: Multiported-RAM based on XOR implementation.
* **lvt\_reg.v:** Verilog: Register-based binary-coded LVT (Live-Value-Table).
* **lvt\_bin.v:** Verilog: Binary-coded I-LVT (Invalidation Live-Value-Table).
* **lvt\_1ht.v:** Verilog: Onehot-coded I-LVT (Invalidation Live-Value-Table).
* **mpram\_lvt.v:** Verilog: LVT/I-LVT-based Multiported-RAM for register-base and SRAM-based one-hot/binary-coded I-LVT.
* **smpram.v:** Verilog: Switched multiported-RAM: register-based, XOR-based ,register-based LVT, SRAM-based binary-coded and one-hot-coded I-LVT.
* **smpram\_tb.v:** Verilog: Switched multiported-RAM testbench.
* **smpram.qpf:** Quartus II Project File.
* **smpram.qsf:** Quartus II Settings File.
* **sim.res:** A list of simulation results, each run in a separate line, including all architectures.
* **syn.res:** A list of synthesis results, each run in a separate line, including: frequency, resources usage, and runtime.
* **log/:** A directory containing Altera's logs and reports.
* **syn.res.example:** Example synthesis results.
* **sim.res.example:** Example simulation results.
* **log.example.tar.xz:** xz tarball: archived log directory example (for the runs listed in syn.res.example). To extract invoke: tar -xavf log.example.tar.xz
---
## Switched multi-ported RAM module instantiation ##
All **.v &**.vh files in this package should be copied into your work directory. Copy the following instantiation into your Verilog design, change parameters and connectivity to fit your design.
```
// instantiate a multiported-RAM
mpram #(
// parameters
.MEMD (MEMD ), // positive integer: memory depth
.DATW (DATW ), // positive integer: data width
.nRPF (nRPF ), // positive integer: number of fixed (simple) read ports (nRPF>=1 )
.nWPF (nWPF ), // positive integer: number of fixed (simple) write ports (nWPF>=0 )
.nRPS (nRPS ), // positive integer: number of switched read ports (nRPS<=nRPF )
.nWPS (nWPS ), // positive integer: number of switched write ports (nWPS>=0; nWPF+nWPS>=1)
.ARCH (ARCH ), // string: multi-port RAM architecture:
// "AUTO" : Choose automatically
// "REG" : Register-based
// "XOR" : XOR-based
// "LVTREG": Register-based LVT
// "LVTBIN": Binary-coded I-LVT-based
// "LVT1HT": Onehot-coded I-LVT-based
.BYPS (BYPS ), // string: Bypassing type:
// "WAW": Allow Write-After-Write
// "RAW": New data for Read-after-Write
// "RDW": New data for Read-During-Write
.FILE ("" ) // text: initialization file, optional
) mpram_inst (
// ports
.clk (clk ), // clock - input
.rdWr (rdWr ), // switch read/write (write is active low) - input
.WEnb (WEnb ), // write enables - packed from nWPF fixed & nWPS switched ports - input : [ (nWPF+nWPS)-1:0]
.WAddr(WAddr), // write addresses - packed from nWPF fixed & nWPS switched ports - input : [`log2(MEMD)*(nWPF+nWPS)-1:0]
.WData(WData), // write data - packed from nWPF fixed & nWPS switched ports - input : [DATW *(nWPF+nWPS)-1:0]
.RAddr(RAddr), // read addresses - packed from nRPF fixed & nRPS switched ports - input : [`log2(MEMD)*(nRPF+nRPS)-1:0]
.RData(RData) // read data - packed from nRPF fixed & nRPS switched ports - output: [DATW *(nRPF+nRPS)-1:0]
);
```
---
## `sim`: A Run-in-batch Simulation Flow Manager ##
### USAGE: ###
> `./sim <Depth List> <Width List> <#Write Ports List (Fixed-Switched)> <#Read Ports List (Fixed-Switched)> <Bypass List> <#Cycles> [verbose]`
* Use a comma delimited list.
* No spaces.
* May be surrounded by any brackets (), [], {}, or <>.
* RAM depth, data width, and simulation cycles are positive integers.
* Numbers of read and write ports are:
* Pairs of "fixed-switched" port numbers delimited with hyphen "-", or,
* Fixed port number only, if switched ports are not required.
* numbers of read/write ports are integers.
* #switched\_read\_ports < = #fixed\_read\_ports
* Bypassing type is one of: NON, WAW, RAW, or RDW.
* NON: No bypassing logic
* WAW: Allow Write-After-Write
* RAW: new data for Read-after-Write
* RDW: new data for Read-During-Write
* "verbose" is an optional argument; use if verbosed logging is required
### EXAMPLES: ###
* `./sim 1024 32 1-2 2-2 NON 1000000 verbose`
* Simulate 1M cycles of a 1K lines RAM, 32 bits width, 1 fixed / 2 switched write & 2 fixed / 2 switched read ports, no bypassing, verbose logging,
* `./sim 512,1024 8,16,32 2,3,4 1,2,3,4 RAW 1000000`
* Simulate 1M cycles of RAMs with 512 or 1024 lines, 8, 16, or 32 bits width, 2,3, or 4 fixed write ports, 1,2,3, or 4 fixed read ports, with RAW bypass.
The following files and directories will be created after simulation :
* sim.res : A list of simulation results, each run in a separate line, including all design styles.
---
## `syn`: A Run-in-batch Synthesis Flow Manager ##
### USAGE: ###
`./syn <Depth List> <Width List> <#Write Ports List (Fixed-Switched)> <#Read Ports List (Fixed-Switched)> <Bypass List> <Architecture List>`
* Use a comma delimited list.
* No spaces.
* May be surrounded by any brackets (), [], {}, or <>.
* RAM depth, data width, and simulation cycles are positive integers.
* Numbers of read and write ports are:
* Pairs of "fixed-switched" port numbers delimited with hyphen "-", or,
* Fixed port number only, if switched ports are not required.
* numbers of read/write ports are integers.
* #switched\_read\_ports < = #fixed\_read\_ports
* Bypassing type is one of: NON, WAW, RAW, or RDW.
* NON: No bypassing logic
* WAW: Allow Write-After-Write
* RAW: new data for Read-after-Write
* RDW: new data for Read-During-Write
* Architecture is one of: REG, XOR, LVTREG, LVTBIN, or LVT1HT.
* REG : Register-based multi-ported RAM
* XOR : XOR-based multi-ported RAM
* LVTREG: Register-based LVT multi-ported RAM
* LVTBIN: Binary-coded I-LVT-based multi-ported RAM
* LVT1HT: Onehot-coded I-LVT-based multi-ported RAM
### EXAMPLES: ###
* `./syn 1024 32 1-2 2-2 NON XOR`
* Synthesis a XOR-based RAM with no bypassing, 1K lines RAM, 32 bits width, 1 fixed / 2 switched write and 2 fixed / 2 switched read ports.
* `./syn 512,1024 16,32 3,4 2,3 RAW,RDW LVTBIN,LVT1HT`
* Synthesis LVTBIN & LVT1HT RAM with new data RAW & RDW bypassing, 512 & 1024 lines, 16 & 32 data width, 3 & 4 fixed write ports, 2 & 3 fixed read ports.
The following files and directories will be created after compilation:
* syn.res : A list of results, each run in a separate line, including: frequency, resources usage, and runtime
* log/ : Altera's logs and reports
////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2014, University of British Columbia (UBC); All rights reserved. //
// //
// Redistribution and use in source and binary forms, with or without //
// modification, are permitted provided that the following conditions are met: //
// * Redistributions of source code must retain the above copyright //
// notice, this list of conditions and the following disclaimer. //
// * Redistributions in binary form must reproduce the above copyright //
// notice, this list of conditions and the following disclaimer in the //
// documentation and/or other materials provided with the distribution. //
// * Neither the name of the University of British Columbia (UBC) nor the names //
// of its contributors may be used to endorse or promote products //
// derived from this software without specific prior written permission. //
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE //
// DISCLAIMED. IN NO EVENT SHALL University of British Columbia (UBC) BE LIABLE //
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL //
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR //
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER //
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, //
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE //
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// dpram.v: Generic dual-ported RAM //
// //
// Author: Ameer M.S. Abdelhadi (ameer@ece.ubc.ca, ameer.abdelhadi@gmail.com) //
// Switched SRAM-based Multi-ported RAM; University of British Columbia, 2014 //
////////////////////////////////////////////////////////////////////////////////////
`include "utils.vh"
module dpram
#( parameter MEMD = 16, // memory depth
parameter DATW = 32, // data width
parameter ZERO = 0 , // binary / Initial RAM with zeros (has priority over FILE)
parameter FILE = "" // initialization hex file (don't pass extension), optional
)( input clk , // clock
input WEnb_A , // write enable for port A
input WEnb_B , // write enable for port B
input [`log2(MEMD)-1:0] Addr_A , // address for port A
input [`log2(MEMD)-1:0] Addr_B , // address for port B
input [DATW -1:0] WData_A, // write data for port A
input [DATW -1:0] WData_B, // write data for port B
output reg [DATW -1:0] RData_A, // read data for port A
output reg [DATW -1:0] RData_B // read data for port B
);
// initialize RAM, with zeros if ZERO or file if FILE.
integer i;
reg [DATW-1:0] mem [0:MEMD-1]; // memory array
initial
if (ZERO)
for (i=0; i<MEMD; i=i+1) mem[i] = {DATW{1'b0}};
else
if (FILE != "") $readmemh({FILE,".hex"}, mem);
// PORT A
always @(posedge clk) begin
// write/read; nonblocking statement to read old data
if (WEnb_A) begin
mem[Addr_A] <= WData_A; // Change into blocking statement (=) to read new data
RData_A <= WData_A; // flow-through
end else
RData_A <= mem[Addr_A]; //Change into blocking statement (=) to read new data
end
// PORT B
always @(posedge clk) begin
// write/read; nonblocking statement to read old data
if (WEnb_B) begin
mem[Addr_B] <= WData_B; // Change into blocking statement (=) to read new data
RData_B <= WData_B; // flow-through
end else
RData_B <= mem[Addr_B]; //Change into blocking statement (=) to read new data
end
endmodule
////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2014, University of British Columbia (UBC); All rights reserved. //
// //
// Redistribution and use in source and binary forms, with or without //
// modification, are permitted provided that the following conditions are met: //
// * Redistributions of source code must retain the above copyright //
// notice, this list of conditions and the following disclaimer. //
// * Redistributions in binary form must reproduce the above copyright //
// notice, this list of conditions and the following disclaimer in the //
// documentation and/or other materials provided with the distribution. //
// * Neither the name of the University of British Columbia (UBC) nor the names //
// of its contributors may be used to endorse or promote products //
// derived from this software without specific prior written permission. //
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE //
// DISCLAIMED. IN NO EVENT SHALL University of British Columbia (UBC) BE LIABLE //
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL //
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR //
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER //
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, //
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE //
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// dpram_bbs.v: Generic dual-ported RAM with optional 1-stage or 2-stage bypass //
// //
// Author: Ameer M.S. Abdelhadi (ameer@ece.ubc.ca, ameer.abdelhadi@gmail.com) //
// Switched SRAM-based Multi-ported RAM; University of British Columbia, 2014 //
////////////////////////////////////////////////////////////////////////////////////
`include "utils.vh"
module dpram_bbs
#( parameter MEMD = 16, // memory depth
parameter DATW = 32, // data width
parameter BYPS = 1 , // bypass? 0:none; 1: single-stage; 2: two-stage
parameter ZERO = 0 , // binary / Initial RAM with zeros (has priority over FILE)
parameter FILE = "" // initialization hex file (don't pass extension), optional
)( input clk , // clock
input WEnb_A , // write enable for port A
input WEnb_B , // write enable for port B
input [`log2(MEMD)-1:0] Addr_A , // write addresses - packed from nWP write ports
input [`log2(MEMD)-1:0] Addr_B , // write addresses - packed from nWP write ports
input [DATW -1:0] WData_A, // write data - packed from nRP read ports
input [DATW -1:0] WData_B, // write data - packed from nRP read ports
output reg [DATW -1:0] RData_A, // read data - packed from nRP read ports
output reg [DATW -1:0] RData_B // read data - packed from nRP read ports
);
wire [DATW-1:0] RData_Ai; // read ram data (internal) / port A
wire [DATW-1:0] RData_Bi; // read ram data (internal) - port B
dpram #( .MEMD (MEMD ), // memory depth
.DATW (DATW ), // data width
.ZERO (ZERO ), // binary / Initial RAM with zeros (has priority over INITFILE)
.FILE (FILE )) // initializtion file, optional
dprami ( .clk (clk ), // clock
.WEnb_A (WEnb_A ), // write enable / port A - in
.WEnb_B (WEnb_B ), // write enable / port B - in
.Addr_A (Addr_A ), // write address / port A - in [`log2(MEMD)-1:0]
.Addr_B (Addr_B ), // write address / port B - in [`log2(MEMD)-1:0]
.WData_A(WData_A ), // write data / port A - in [DATW -1:0]
.WData_B(WData_B ), // write data / port B - in [DATW -1:0]
.RData_A(RData_Ai), // read data / port A - in [DATW -1:0]
.RData_B(RData_Bi)); // read data / port B - in [DATW -1:0]
// registers; will be removed if unused
reg WEnb_Ar;
reg WEnb_Br;
reg [`log2(MEMD)-1:0] Addr_Ar;
reg [`log2(MEMD)-1:0] Addr_Br;
reg [DATW-1:0] WData_Br;
reg [DATW-1:0] WData_Ar;
always @(posedge clk) begin
WEnb_Ar <= WEnb_A ;
WEnb_Br <= WEnb_B ;
Addr_Ar <= Addr_A;
Addr_Br <= Addr_B;
WData_Ar <= WData_A; // bypass register
WData_Br <= WData_B; // bypass register
end
// bypass: single-staeg, two-stage (logic will be removed if unused)
wire bypsA1,bypsA2,bypsB1,bypsB2;
assign bypsA1 = (BYPS >= 1) && WEnb_Br && !WEnb_Ar && (Addr_Br == Addr_Ar);
assign bypsA2 = (BYPS == 2) && WEnb_B && !WEnb_Ar && (Addr_B == Addr_Ar);
assign bypsB1 = (BYPS >= 1) && WEnb_Ar && !WEnb_Br && (Addr_Ar == Addr_Br);
assign bypsB2 = (BYPS == 2) && WEnb_A && !WEnb_Br && (Addr_A == Addr_Br);
// output mux (mux or mux inputs will be removed if unused)
always @*
if (bypsA2) RData_A = WData_B ;
else if (bypsA1) RData_A = WData_Br;
else RData_A = RData_Ai;
always @*
if (bypsB2) RData_B = WData_A ;
else if (bypsB1) RData_B = WData_Ar;
else RData_B = RData_Bi;
endmodule
////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2014, University of British Columbia (UBC); All rights reserved. //
// //
// Redistribution and use in source and binary forms, with or without //
// modification, are permitted provided that the following conditions are met: //
// * Redistributions of source code must retain the above copyright //
// notice, this list of conditions and the following disclaimer. //
// * Redistributions in binary form must reproduce the above copyright //
// notice, this list of conditions and the following disclaimer in the //
// documentation and/or other materials provided with the distribution. //
// * Neither the name of the University of British Columbia (UBC) nor the names //
// of its contributors may be used to endorse or promote products //
// derived from this software without specific prior written permission. //
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE //
// DISCLAIMED. IN NO EVENT SHALL University of British Columbia (UBC) BE LIABLE //
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL //
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR //
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER //
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, //
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE //
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// lvt_1ht.v: Onehot-coded LVT (Live-Value-Table) //
// //
// Author: Ameer M.S. Abdelhadi (ameer@ece.ubc.ca, ameer.abdelhadi@gmail.com) //
// Switched SRAM-based Multi-ported RAM; University of British Columbia, 2014 //
////////////////////////////////////////////////////////////////////////////////////
`include "utils.vh"
module lvt_1ht
#( parameter MEMD = 16, // memory depth
parameter nRP = 1 , // number of reading ports
parameter nWP = 3 , // number of writing ports
parameter WAWB = 1 , // allow Write-After-Write (need to bypass feedback ram)
parameter RAWB = 1 , // new data for Read-after-Write (need to bypass output ram)
parameter RDWB = 0 , // new data for Read-During-Write
parameter ZERO = 0 , // binary / Initial RAM with zeros (has priority over FILE)
parameter FILE = "" // initialization file, optional
)( input clk , // clock
input [ nWP-1:0] WEnb , // write enable for each writing port
input [`log2(MEMD)*nWP-1:0] WAddr, // write addresses - packed from nWP write ports
input [`log2(MEMD)*nRP-1:0] RAddr, // read addresses - packed from nRP read ports
output reg [nWP *nRP-1:0] RBank); // read bank selector - packed from nRP read ports
localparam ADRW = `log2(MEMD); // address width
localparam LVTW = nWP - 1 ; // required memory width
// Register write addresses, data and enables
reg [ADRW*nWP-1:0] WAddr_r; // registered write addresses - packed from nWP write ports
reg [ nWP-1:0] WEnb_r ; // registered write enable for each writing port
always @(posedge clk) begin
WAddr_r <= WAddr;
WEnb_r <= WEnb ;
end
// unpacked/pack addresses and data
reg [ADRW -1:0] WAddr2D [nWP-1:0] ; // write addresses / 2D
reg [ADRW -1:0] WAddr2D_r [nWP-1:0] ; // registered write addresses / 2D
wire [LVTW*nRP -1:0] RDataOut2D [nWP-1:0] ; // read data out / 2D
reg [LVTW -1:0] RDataOut3D [nWP-1:0][nRP -1:0]; // read data out / 3D
reg [ADRW*LVTW-1:0] RAddrFB2D [nWP-1:0] ; // read address fb / 2D
reg [ADRW -1:0] RAddrFB3D [nWP-1:0][LVTW-1:0]; // read address fb / 3D
wire [LVTW*LVTW-1:0] RDataFB2D [nWP-1:0] ; // read data fb / 2D
reg [LVTW -1:0] RDataFB3D [nWP-1:0][LVTW-1:0]; // read data fb / 3D
reg [LVTW -1:0] WDataFB2D [nWP-1:0] ; // write data / 2D
reg [LVTW -1:0] InvData2D [nWP-1:0] ; // write data / 2D
reg [nWP -1:0] RBank2D [nRP-1:0] ; // read bank selector / 2D
`ARRINIT;
always @* begin
// packing/unpacking arrays into 1D/2D/3D structures; see utils.vh for definitions
`ARR1D2D(nWP, ADRW, WAddr , WAddr2D );
`ARR1D2D(nWP, ADRW, WAddr_r , WAddr2D_r );
`ARR2D1D(nRP, nWP , RBank2D , RBank );
`ARR2D3D(nWP, nRP , LVTW, RDataOut2D, RDataOut3D);
`ARR3D2D(nWP, LVTW, ADRW, RAddrFB3D , RAddrFB2D );
`ARR2D3D(nWP, LVTW, LVTW, RDataFB2D , RDataFB3D );
end
// generate and instantiate mulriread BRAMs
genvar wpi;
generate
for (wpi=0 ; wpi<nWP ; wpi=wpi+1) begin: RPORTwpi
// feedback multiread ram instantiation
mrram #( .MEMD (MEMD ), // memory depth
.DATW (LVTW ), // data width
.nRP (nWP-1 ), // number of reading ports
.BYPS (WAWB||RDWB||RAWB), // bypass? 0:none; 1:single-stage; 2:two-stages
.ZERO (ZERO ), // binary / Initial RAM with zeros (has priority over FILE)
.FILE (FILE )) // initialization file, optional
mrram_fdb ( .clk (clk ), // clock - in
.WEnb (WEnb_r[wpi] ), // write enable (1 port) - in
.WAddr (WAddr2D_r[wpi] ), // write address (1 port) - in : [`log2(MEMD) -1:0]
.WData (WDataFB2D[wpi] ), // write data (1 port) - in : [LVTW -1:0]
.RAddr (RAddrFB2D[wpi] ), // read addresses - packed from nRP read ports - in : [`log2(MEMD)*nRP-1:0]
.RData (RDataFB2D[wpi] )); // read data - packed from nRP read ports - out: [LVTW *nRP-1:0]
// output multiread ram instantiation
mrram #( .MEMD (MEMD ), // memory depth
.DATW (LVTW ), // data width
.nRP (nRP ), // number of reading ports
.BYPS (RDWB ? 2 : RAWB), // bypass? 0:none; 1:single-stage; 2:two-stages
.ZERO (ZERO ), // binary / Initial RAM with zeros (has priority over FILE)
.FILE (FILE )) // initialization file, optional
mrram_out ( .clk (clk ), // clock - in
.WEnb (WEnb_r[wpi] ), // write enable (1 port) - in
.WAddr (WAddr2D_r[wpi] ), // write address (1 port) - in : [`log2(MEMD) -1:0]
.WData (WDataFB2D[wpi] ), // write data (1 port) - in : [LVTW -1:0]
.RAddr (RAddr ), // read addresses - packed from nRP read ports - in : [`log2(MEMD)*nRP-1:0]
.RData (RDataOut2D[wpi])); // read data - packed from nRP read ports - out: [LVTW *nRP-1:0]
end
endgenerate
// combinatorial logic for output and feedback functions
integer wp; // write port counter
integer wf; // write feedback counter
integer rf; // read feedback counter
integer rp; // read port counter
integer lv; // lvt bit counter
integer fi; // feedback bit index
always @* begin
// generate inversion vector
for(wp=0;wp<nWP;wp=wp+1) InvData2D[wp] = (1<<wp)-1; // 2^wp-1
// initialize output read bank
for(rp=0;rp<nRP;rp=rp+1)
for(wp=0;wp<nWP;wp=wp+1)
RBank2D[rp][wp] = 1;
// generate feedback functions
for(wp=0;wp<nWP;wp=wp+1) begin
wf = 0;
for(lv=0;lv<LVTW;lv=lv+1) begin
wf=wf+(lv==wp);
rf=wp-(wf<wp);
fi=wp-(InvData2D[wp][lv]);
RAddrFB3D[wp][lv] = WAddr2D[wf];
WDataFB2D[wp][lv] = RDataFB3D[wf][rf][fi] ^ InvData2D[wp][lv];
for(rp=0;rp<nRP;rp=rp+1) RBank2D[rp][wp] = RBank2D[rp][wp] && (( RDataOut3D[wf][rp][fi] ^ InvData2D[wp][lv]) == RDataOut3D[wp][rp][lv]);
wf=wf+1;
end
end
end
endmodule
////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2014, University of British Columbia (UBC); All rights reserved. //
// //
// Redistribution and use in source and binary forms, with or without //
// modification, are permitted provided that the following conditions are met: //
// * Redistributions of source code must retain the above copyright //
// notice, this list of conditions and the following disclaimer. //
// * Redistributions in binary form must reproduce the above copyright //
// notice, this list of conditions and the following disclaimer in the //
// documentation and/or other materials provided with the distribution. //
// * Neither the name of the University of British Columbia (UBC) nor the names //
// of its contributors may be used to endorse or promote products //
// derived from this software without specific prior written permission. //
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE //
// DISCLAIMED. IN NO EVENT SHALL University of British Columbia (UBC) BE LIABLE //
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL //
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR //
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER //
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, //
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE //
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// lvt_bin.v: Binary-coded LVT (Live-Value-Table) //
// //
// Author: Ameer M.S. Abdelhadi (ameer@ece.ubc.ca, ameer.abdelhadi@gmail.com) //
// Switched SRAM-based Multi-ported RAM; University of British Columbia, 2014 //
////////////////////////////////////////////////////////////////////////////////////
`include "utils.vh"
module lvt_bin
#( parameter MEMD = 16, // memory depth
parameter nRP = 2 , // number of reading ports
parameter nWP = 2 , // number of writing ports
parameter WAWB = 1 , // allow Write-After-Write (need to bypass feedback ram)
parameter RAWB = 1 , // new data for Read-after-Write (need to bypass output ram)
parameter RDWB = 0 , // new data for Read-During-Write
parameter ZERO = 0 , // binary / Initial RAM with zeros (has priority over FILE)
parameter FILE = "" // initialization file, optional
)( input clk , // clock
input [ nWP-1:0] WEnb , // write enable for each writing port
input [`log2(MEMD)*nWP-1:0] WAddr, // write addresses - packed from nWP write ports
input [`log2(MEMD)*nRP-1:0] RAddr, // read addresses - packed from nRP read ports
output reg [`log2(nWP )*nRP-1:0] RBank); // read data - packed from nRP read ports
localparam ADRW = `log2(MEMD); // address width
localparam LVTW = `log2(nWP ); // required memory width
// Generate Bank ID's to write into LVT
wire [LVTW-1:0] WData2D [nWP-1:0];
genvar gi;
generate
for (gi=0;gi<nWP;gi=gi+1) begin: GenerateID
assign WData2D[gi]=gi;
end
endgenerate
// Register write addresses, data and enables
reg [ADRW*nWP-1:0] WAddr_r; // registered write addresses - packed from nWP write ports
reg [ nWP-1:0] WEnb_r ; // registered write enable for each writing port
always @(posedge clk) begin
WAddr_r <= WAddr;
WEnb_r <= WEnb ;
end
// unpacked/pack addresses/data
reg [ADRW -1:0] WAddr2D [nWP-1:0] ; // write addresses / 2D
reg [ADRW -1:0] WAddr2D_r [nWP-1:0] ; // registered write addresses / 2D
wire [LVTW* nRP -1:0] RDataOut2D [nWP-1:0] ; // read data out / 2D
reg [LVTW -1:0] RDataOut3D [nWP-1:0][nRP-1:0]; // read data out / 3D
reg [ADRW*(nWP-1)-1:0] RAddrFB2D [nWP-1:0] ; // read address fb / 2D
reg [ADRW -1:0] RAddrFB3D [nWP-1:0][nWP-2:0]; // read address fb / 3D
wire [LVTW*(nWP-1)-1:0] RDataFB2D [nWP-1:0] ; // read data fb / 2D
reg [LVTW -1:0] RDataFB3D [nWP-1:0][nWP-2:0]; // read data fb / 3D
reg [LVTW -1:0] WDataFB2D [nWP-1:0] ; // write data / 2D
reg [LVTW -1:0] RBank2D [nRP-1:0] ; // read data / 2D
`ARRINIT;
always @* begin
// packing/unpacking arrays into 1D/2D/3D structures; see utils.vh for definitions
`ARR1D2D(nWP, ADRW,WAddr ,WAddr2D );
`ARR1D2D(nWP, ADRW,WAddr_r ,WAddr2D_r );
`ARR2D1D(nRP, LVTW,RBank2D ,RBank );
`ARR2D3D(nWP,nRP ,LVTW,RDataOut2D,RDataOut3D);
`ARR3D2D(nWP,nWP-1,ADRW,RAddrFB3D ,RAddrFB2D );
`ARR2D3D(nWP,nWP-1,LVTW,RDataFB2D ,RDataFB3D );
end
// generate and instantiate mulriread BRAMs
genvar wpi;
generate
for (wpi=0 ; wpi<nWP ; wpi=wpi+1) begin: RPORTwpi
// feedback multiread ram instantiation
mrram #( .MEMD (MEMD ), // memory depth
.DATW (LVTW ), // data width
.nRP (nWP-1 ), // number of reading ports
.BYPS (WAWB||RDWB||RAWB), // bypass? 0:none; 1:single-stage; 2:two-stages
.ZERO (ZERO ), // binary / Initial RAM with zeros (has priority over FILE)
.FILE (FILE )) // initialization file, optional
mrram_fbk ( .clk (clk ), // clock - in
.WEnb (WEnb_r[wpi] ), // write enable (1 port) - in
.WAddr (WAddr2D_r[wpi] ), // write address (1 port) - in : [`log2(MEMD) -1:0]
.WData (WDataFB2D[wpi] ), // write data (1 port) - in : [LVTW -1:0]
.RAddr (RAddrFB2D[wpi] ), // read addresses - packed from nRP read ports - in : [`log2(MEMD)*nRP-1:0]
.RData (RDataFB2D[wpi] )); // read data - packed from nRP read ports - out: [LVTW *nRP-1:0]
// output multiread ram instantiation
mrram #( .MEMD (MEMD ), // memory depth
.DATW (LVTW ), // data width
.nRP (nRP ), // number of reading ports
.BYPS (RDWB ? 2 : RAWB), // bypass? 0:none; 1:single-stage; 2:two-stages
.ZERO (ZERO ), // binary / Initial RAM with zeros (has priority over FILE)
.FILE (FILE )) // initialization file, optional
mrram_out ( .clk (clk ), // clock - in
.WEnb (WEnb_r[wpi] ), // write enable (1 port) - in
.WAddr (WAddr2D_r[wpi] ), // write address (1 port) - in : [`log2(MEMD) -1:0]
.WData (WDataFB2D[wpi] ), // write data (1 port) - in : [LVTW -1:0]
.RAddr (RAddr ), // read addresses - packed from nRP read ports - in : [`log2(MEMD)*nRP-1:0]
.RData (RDataOut2D[wpi])); // read data - packed from nRP read ports - out: [LVTW *nRP-1:0]
end
endgenerate
// combinatorial logic for output and feedback functions
integer i,j,k;
always @* begin
// generate output read functions
for(i=0;i<nRP;i=i+1) begin
RBank2D[i] = RDataOut3D[0][i];
for(j=1;j<nWP;j=j+1) RBank2D[i] = RBank2D[i] ^ RDataOut3D[j][i];
end
// generate feedback functions
for(i=0;i<nWP;i=i+1) WDataFB2D[i] = WData2D[i];
for(i=0;i<nWP;i=i+1) begin
k = 0;
for(j=0;j<nWP-1;j=j+1) begin
k=k+(j==i);
RAddrFB3D[i][j] = WAddr2D[k];
WDataFB2D[k] = WDataFB2D[k] ^ RDataFB3D[i][j];
k=k+1;
end
end
end
endmodule
////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2014, University of British Columbia (UBC); All rights reserved. //
// //
// Redistribution and use in source and binary forms, with or without //
// modification, are permitted provided that the following conditions are met: //
// * Redistributions of source code must retain the above copyright //
// notice, this list of conditions and the following disclaimer. //
// * Redistributions in binary form must reproduce the above copyright //
// notice, this list of conditions and the following disclaimer in the //
// documentation and/or other materials provided with the distribution. //
// * Neither the name of the University of British Columbia (UBC) nor the names //
// of its contributors may be used to endorse or promote products //
// derived from this software without specific prior written permission. //
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE //
// DISCLAIMED. IN NO EVENT SHALL University of British Columbia (UBC) BE LIABLE //
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL //
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR //
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER //
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, //
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE //
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// lvt_reg.v: Register-based binary-coded LVT (Live-Value-Table) //
// //
// Author: Ameer M.S. Abdelhadi (ameer@ece.ubc.ca, ameer.abdelhadi@gmail.com) //
// Switched SRAM-based Multi-ported RAM; University of British Columbia, 2014 //
////////////////////////////////////////////////////////////////////////////////////
`include "utils.vh"
module lvt_reg
#( parameter MEMD = 16, // memory depth
parameter nRP = 2 , // number of reading ports
parameter nWP = 2 , // number of writing ports
parameter RDWB = 0 , // new data for Read-During-Write
parameter ZERO = 0 , // binary / Initial RAM with zeros (has priority over FILE)
parameter FILE = "" // initialization file, optional
)( input clk , // clock
input [ nWP-1:0] WEnb , // write enable for each writing port
input [`log2(MEMD)*nWP-1:0] WAddr, // write addresses - packed from nWP write ports
input [`log2(MEMD)*nRP-1:0] RAddr, // read addresses - packed from nRP read ports
output [`log2(nWP )*nRP-1:0] RBank); // read bank selector - packed from nRP read ports
localparam ADRW = `log2(MEMD); // address width
localparam LVTW = `log2(nWP ); // required memory width
// Generate Bank ID's to write into LVT
reg [LVTW*nWP-1:0] WData1D ;
wire [LVTW -1:0] WData2D [nWP-1:0];
genvar gi;
generate
for (gi=0;gi<nWP;gi=gi+1) begin: GenerateID
assign WData2D[gi]=gi;
end
endgenerate
// packing/unpacking arrays into 1D/2D/3D structures; see utils.vh for definitions
// pack ID's into 1D array
`ARRINIT;
always @* `ARR2D1D(nWP,LVTW,WData2D,WData1D);
mpram_reg #( .MEMD (MEMD ), // memory depth
.DATW (LVTW ), // data width
.nRP (nRP ), // number of reading ports
.nWP (nWP ), // number of writing ports
.RDWB (RDWB ), // provide new data when Read-During-Write?
.ZERO (ZERO ), // binary / Initial RAM with zeros (has priority over FILE)
.FILE (FILE )) // initialization file, optional
mpram_reg_ins ( .clk (clk ), // clock - in
.WEnb (WEnb ), // write enable for each writing port - in : [ nWP-1:0]
.WAddr (WAddr ), // write addresses - packed from nWP write ports - in : [ADRW*nWP-1:0]
.WData (WData1D), // write data - packed from nRP read ports - in : [LVTW*nWP-1:0]
.RAddr (RAddr ), // read addresses - packed from nRP read ports - in : [ADRW*nRP-1:0]
.RData (RBank )); // read data - packed from nRP read ports - out: [LVTW*nRP-1:0]
endmodule
////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2014, University of British Columbia (UBC); All rights reserved. //
// //
// Redistribution and use in source and binary forms, with or without //
// modification, are permitted provided that the following conditions are met: //
// * Redistributions of source code must retain the above copyright //
// notice, this list of conditions and the following disclaimer. //
// * Redistributions in binary form must reproduce the above copyright //
// notice, this list of conditions and the following disclaimer in the //
// documentation and/or other materials provided with the distribution. //
// * Neither the name of the University of British Columbia (UBC) nor the names //
// of its contributors may be used to endorse or promote products //
// derived from this software without specific prior written permission. //
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE //
// DISCLAIMED. IN NO EVENT SHALL University of British Columbia (UBC) BE LIABLE //
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL //
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR //
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER //
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, //
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE //
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// mpram_lvt.v: LVT-based Multiported-RAM for register-base and SRAM-based //
// one-hot/binary-coded I-LVT //
// //
// Author: Ameer M.S. Abdelhadi (ameer@ece.ubc.ca, ameer.abdelhadi@gmail.com) //
// Switched SRAM-based Multi-ported RAM; University of British Columbia, 2014 //
////////////////////////////////////////////////////////////////////////////////////
`include "utils.vh"
module mpram_lvt
#( parameter MEMD = 16, // memory depth
parameter DATW = 32, // data width
parameter nRPF = 2 , // number of fixed read ports
parameter nWPF = 2 , // number of fixed write ports
parameter nRPS = 2 , // number of switched read ports
parameter nWPS = 2 , // number of switched write ports
parameter LVTA = "", // LVT architecture type: LVTREG, LVTBIN, LVT1HT
parameter WAWB = 1 , // allow Write-After-Write (need to bypass feedback ram)
parameter RAWB = 1 , // new data for Read-after-Write (need to bypass output ram)
parameter RDWB = 0 , // new data for Read-During-Write
parameter FILE = "" // initialization file, optional
)( input clk , // clock
input rdWr , // switch read/write (write is active low)
input [ (nWPF+nWPS)-1:0] WEnb , // write enablea - packed from nWPF fixed & nWPS switched write ports
input [`log2(MEMD)*(nWPF+nWPS)-1:0] WAddr, // write addresses - packed from nWPF fixed & nWPS switched write ports
input [DATW *(nWPF+nWPS)-1:0] WData, // write data - packed from nWPF fixed & nWPS switched write ports
input [`log2(MEMD)*(nRPF+nRPS)-1:0] RAddr, // read addresses - packed from nRPF fixed & nRPS switched read ports
output reg [DATW *(nRPF+nRPS)-1:0] RData); // read data - packed from nRPF fixed & nRPS switched read ports
// local parameters
localparam nWPT = nWPF+nWPS ; // total number of write ports
localparam nRPT = nRPF+nRPS ; // total number of read ports
localparam ADRW = `log2(MEMD) ; // address width
localparam LVTW = `log2(nWPT) ; // LVT width
localparam SELW = (LVTA=="LVT1HT")?nWPT:LVTW; // data bank selector width
// unpacked/pack addresses/data
reg [ADRW -1:0] WAddr2D [nWPT-1:0] ; // write addresses / 2D
reg [DATW -1:0] WData2D [nWPT-1:0] ; // write data / 2D
wire [DATW*nRPT-1:0] RData2Di [nWPT-1:0] ; // read data / internal / 2D
reg [DATW -1:0] RData3Di [nWPT-1:0][nRPT-1:0]; // read data / internal / 3D
wire [DATW -1:0] RData2D [nRPT-1:0] ; // read data / output / 2D
wire [SELW*nRPT-1:0] RBank ; // read bank selector / 1D
reg [SELW -1:0] RBank2D [nRPT-1:0] ; // read bank selector / 2D
`ARRINIT;
always @* begin
// packing/unpacking arrays into 1D/2D/3D structures; see utils.vh for definitions
`ARR1D2D(nWPT, ADRW,WAddr ,WAddr2D );
`ARR1D2D(nWPT, DATW,WData ,WData2D );
`ARR2D3D(nWPT,nRPT,DATW,RData2Di,RData3Di);
`ARR2D1D(nRPT, DATW,RData2D ,RData );
`ARR1D2D(nRPT, SELW,RBank ,RBank2D );
end
// generate and instantiate LVT with specific implementation
generate
if (LVTA=="LVTREG") begin
// instantiate LVT / REG type
lvt_reg #( .MEMD (MEMD ), // memory depth
.nRP (nRPT ), // number of reading ports
.nWP (nWPT ), // number of writing ports
.RDWB (RDWB ), // new data for Read-During-Write
.ZERO (FILE!=""), // binary / Initial RAM with zeros (has priority over FILE)
.FILE ("" )) // initialization file, optional
lvt_reg_i ( .clk (clk ), // clock - in
.WEnb (WEnb ), // write enable for each writing port - in : [ nWPT-1:0]
.WAddr (WAddr ), // write addresses - packed from nWPT write ports - in : [ADRW*nWPT-1:0]
.RAddr (RAddr ), // read addresses - packed from nRPT read ports - in : [ADRW*nRPT-1:0]
.RBank (RBank )); // read bank selector - packed from nRPT read ports - out: [LVTW*nRPT-1:0]
end
else if (LVTA=="LVTBIN") begin
// instantiate LVT / BIN type
lvt_bin #( .MEMD (MEMD ), // memory depth
.nRP (nRPT ), // number of reading ports
.nWP (nWPT ), // number of writing ports
.WAWB (WAWB ), // allow Write-After-Write (need to bypass feedback ram)
.RAWB (RAWB ), // new data for Read-after-Write (need to bypass output ram)
.RDWB (RDWB ), // new data for Read-During-Write
.ZERO (FILE!=""), // binary / Initial RAM with zeros (has priority over FILE)
.FILE ("" )) // initialization file, optional
lvt_bin_i ( .clk (clk ), // clock - in
.WEnb (WEnb ), // write enable for each writing port - in : [ nWPT-1:0]
.WAddr (WAddr ), // write addresses - packed from nWPT write ports - in : [ADRW*nWPT-1:0]
.RAddr (RAddr ), // read addresses - packed from nRPT read ports - in : [ADRW*nRPT-1:0]
.RBank (RBank )); // read bank selector - packed from nRPT read ports - out: [LVTW*nRPT-1:0]
end
else begin
// instantiate LVT / 1HT TYPE
lvt_1ht #( .MEMD (MEMD ), // memory depth
.nRP (nRPT ), // number of reading ports
.nWP (nWPT ), // number of writing ports
.WAWB (WAWB ), // allow Write-After-Write (need to bypass feedback ram)
.RAWB (RAWB ), // new data for Read-after-Write (need to bypass output ram)
.RDWB (RDWB ), // new data for Read-During-Write
.ZERO (FILE!=""), // binary / Initial RAM with zeros (has priority over FILE)
.FILE ("" )) // initialization file, optional
lvt_1ht_i ( .clk (clk ), // clock - in
.WEnb (WEnb ), // write enable for each writing port - in : [ nWPT-1:0]
.WAddr (WAddr ), // write addresses - packed from nWPT write ports - in : [ADRW*nWPT-1:0]
.RAddr (RAddr ), // read addresses - packed from nRPT read ports - in : [ADRW*nRPT-1:0]
.RBank (RBank )); // 1hot bank selector - packed from nRPT read ports - out: [nWPT*nRPT-1:0]
end
endgenerate
// generate and instantiate mulriread RAM blocks
genvar wpi,rpi;
generate
for (wpi=0 ; wpi<nWPT ; wpi=wpi+1) begin: RPORTwpi
if (wpi<nWPF)
// noraml multi-read ram instantiation
mrram #( .MEMD (MEMD ), // memory depth
.DATW (DATW ), // data width
.nRP (nRPT ), // number of reading ports
.BYPS (RDWB ), // bypass? 0:none; 1:single-stage; 2:two-stages
.ZERO (0 ), // binary / Initial RAM with zeros (has priority over FILE)
.FILE (wpi?"":FILE )) // initialization file, optional
mrram_i ( .clk (clk ), // clock - in
.WEnb (WEnb[wpi] ), // write enable (1 port) - in
.WAddr (WAddr2D[wpi] ), // write address (1 port) - in : [ADRW -1:0]
.WData (WData2D[wpi] ), // write data (1 port) - in : [DATW -1:0]
.RAddr (RAddr ), // read addresses - packed from nRPT read ports - in : [ADRW*nRPT-1:0]
.RData (RData2Di[wpi])); // read data - packed from nRPT read ports - out: [DATW*nRPT-1:0]
else
// switched multi-read ram instantiation
mrram_swt #( .MEMD (MEMD ), // memory depth
.DATW (DATW ), // data width
.nRPF (nRPF ), // number of fixed read ports
.nRPS (nRPS ), // number of switched read ports
.BYPS (RDWB ), // bypass? 0:none; 1:single-stage; 2:two-stages
.ZERO (0 ), // binary / Initial RAM with zeros (has priority over FILE)
.FILE (wpi?"":FILE )) // initialization file, optional
mrram_swt_i ( .clk (clk ), // clock - in
.rdWr (rdWr ), // switch read/write (write is active low) - in
.WEnb (WEnb[wpi] ), // write enable (1 port) - in
.WAddr (WAddr2D[wpi] ), // write address (1 port) - in : [ADRW -1:0]
.WData (WData2D[wpi] ), // write data (1 port) - in : [DATW -1:0]
.RAddr (RAddr ), // read addresses - packed from nRPF fixed & nRPS switched read ports - in : [ADRW*(nRPF+nRPS)-1:0]
.RData (RData2Di[wpi])); // read data - packed from nRPF fixed & nRPS switched read ports - out: [DATW*(nRPF+nRPS)-1:0]
end
// infer tri-state buffers and connect busses for LVT1HT and muxes for LVTREG/LVTBIN
for (rpi=0 ; rpi<nRPT ; rpi=rpi+1) begin: PORTrpi
if (LVTA=="LVT1HT") begin
// tri-state buffers and busses connection
for (wpi=0 ; wpi<nWPT ; wpi=wpi+1) begin: PORTwpi
assign RData2D[rpi] = RBank2D[rpi][wpi] ? RData3Di[wpi][rpi] : {DATW{1'bz}};
end
end
else begin
// combinatorial logic for output muxes
assign RData2D[rpi] = RData3Di[RBank2D[rpi]][rpi];
end
end
endgenerate
endmodule
////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2014, University of British Columbia (UBC); All rights reserved. //
// //
// Redistribution and use in source and binary forms, with or without //
// modification, are permitted provided that the following conditions are met: //
// * Redistributions of source code must retain the above copyright //
// notice, this list of conditions and the following disclaimer. //
// * Redistributions in binary form must reproduce the above copyright //
// notice, this list of conditions and the following disclaimer in the //
// documentation and/or other materials provided with the distribution. //
// * Neither the name of the University of British Columbia (UBC) nor the names //
// of its contributors may be used to endorse or promote products //
// derived from this software without specific prior written permission. //
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE //
// DISCLAIMED. IN NO EVENT SHALL University of British Columbia (UBC) BE LIABLE //
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL //
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR //
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER //
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, //
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE //
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// mpram_reg.v: generic register-based multiported-RAM. //
// Reading addresses are registered and old data will be read in case of RAW. //
// Implemented in FF's if the number of reading or writing ports exceeds one. //
// //
// Author: Ameer M.S. Abdelhadi (ameer@ece.ubc.ca, ameer.abdelhadi@gmail.com) //
// Switched SRAM-based Multi-ported RAM; University of British Columbia, 2014 //
////////////////////////////////////////////////////////////////////////////////////
`include "utils.vh"
module mpram_reg
#( parameter MEMD = 16, // memory depth
parameter DATW = 32, // data width
parameter nRP = 3 , // number of reading ports
parameter nWP = 2 , // number of writing ports
parameter RDWB = 0 , // provide new data when Read-During-Write?
parameter ZERO = 0 , // binary / Initial RAM with zeros (has priority over INITFILE)
parameter FILE = "" // initialization hex file (don't pass extension), optional
)( input clk , // clock
input [nWP-1:0 ] WEnb , // write enable for each writing port
input [`log2(MEMD)*nWP-1:0] WAddr, // write addresses - packed from nWP write ports
input [DATW *nWP-1:0] WData, // write data - packed from nRP read ports
input [`log2(MEMD)*nRP-1:0] RAddr, // read addresses - packed from nRP read ports
output reg [DATW *nRP-1:0] RData // read data - packed from nRP read ports
);
localparam ADRW = `log2(MEMD); // address width
integer i;
// initialize RAM, with zeros if ZERO or file if IFLE.
(* ramstyle = "logic" *) reg [DATW-1:0] mem [0:MEMD-1]; // memory array; implemented with logic cells (registers)
initial
if (ZERO)
for (i=0; i<MEMD; i=i+1) mem[i] = {DATW{1'b0}};
else
if (FILE != "") $readmemh({FILE,".hex"}, mem);
always @(posedge clk) begin
// write to nWP ports; nonblocking statement to read old data
for (i=1; i<=nWP; i=i+1)
if (WEnb[i-1])
if (RDWB) mem[WAddr[i*ADRW-1 -: ADRW]] = WData[i*DATW-1 -: DATW]; // blocking statement (= ) to read new data
else mem[WAddr[i*ADRW-1 -: ADRW]] <= WData[i*DATW-1 -: DATW]; // non-blocking statement (<=) to read old data
// Read from nRP ports; nonblocking statement to read old data
for (i=1; i<=nRP; i=i+1)
if (RDWB) RData[i*DATW-1 -: DATW] = mem[RAddr[i*ADRW-1 -: ADRW]]; // blocking statement (= ) to read new data
else RData[i*DATW-1 -: DATW] <= mem[RAddr[i*ADRW-1 -: ADRW]]; //non-blocking statement (<=) to read old data
end
endmodule
////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2014, University of British Columbia (UBC); All rights reserved. //
// //
// Redistribution and use in source and binary forms, with or without //
// modification, are permitted provided that the following conditions are met: //
// * Redistributions of source code must retain the above copyright //
// notice, this list of conditions and the following disclaimer. //
// * Redistributions in binary form must reproduce the above copyright //
// notice, this list of conditions and the following disclaimer in the //
// documentation and/or other materials provided with the distribution. //
// * Neither the name of the University of British Columbia (UBC) nor the names //
// of its contributors may be used to endorse or promote products //
// derived from this software without specific prior written permission. //
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE //
// DISCLAIMED. IN NO EVENT SHALL University of British Columbia (UBC) BE LIABLE //
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL //
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR //
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER //
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, //
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE //
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// mpram_xor.v: Multiported-RAM based on XOR implementation //
// //
// Author: Ameer M.S. Abdelhadi (ameer@ece.ubc.ca, ameer.abdelhadi@gmail.com) //
// Switched SRAM-based Multi-ported RAM; University of British Columbia, 2014 //
////////////////////////////////////////////////////////////////////////////////////
`include "utils.vh"
module mpram_xor
#( parameter MEMD = 16, // memory depth
parameter DATW = 32, // data width
parameter nRP = 2 , // number of reading ports
parameter nWP = 2 , // number of writing ports
parameter WAWB = 1 , // allow Write-After-Write (need to bypass feedback ram)
parameter RAWB = 1 , // new data for Read-after-Write (need to bypass output ram)
parameter RDWB = 0 , // new data for Read-During-Write
parameter FILE = "" // initialization file, optional
)( input clk , // clock
input [nWP-1:0 ] WEnb , // write enable for each writing port
input [`log2(MEMD)*nWP-1:0] WAddr, // write addresses - packed from nWP write ports
input [DATW *nWP-1:0] WData, // write data - packed from nWP read ports
input [`log2(MEMD)*nRP-1:0] RAddr, // read addresses - packed from nRP read ports
output reg [DATW *nRP-1:0] RData); // read data - packed from nRP read ports
localparam ADRW = `log2(MEMD); // address width
// Register write addresses, data and enables
reg [ADRW*nWP-1:0] WAddr_r; // registered write addresses - packed from nWP write ports
reg [DATW*nWP-1:0] WData_r; // registered write data - packed from nWP read ports
reg [ nWP-1:0] WEnb_r ; // registered write enable for each writing port
always @(posedge clk) begin
WAddr_r <= WAddr;
WData_r <= WData;
WEnb_r <= WEnb ;
end
// unpacked/pack addresses/data
reg [ADRW -1:0] WAddr2D [nWP-1:0] ; // write addresses / 2D
reg [ADRW -1:0] WAddr2D_r [nWP-1:0] ; // registered write addresses / 2D
reg [DATW -1:0] WData2D [nWP-1:0] ; // write data / 2D
reg [DATW -1:0] WData2D_r [nWP-1:0] ; // registered write data / 2D
wire [DATW* nRP -1:0] RDataOut2D [nWP-1:0] ; // read data out / 2D
reg [DATW -1:0] RDataOut3D [nWP-1:0][nRP-1:0]; // read data out / 3D
reg [ADRW*(nWP-1)-1:0] RAddrFB2D [nWP-1:0] ; // read address fb / 2D
reg [ADRW -1:0] RAddrFB3D [nWP-1:0][nWP-2:0]; // read address fb / 3D
wire [DATW*(nWP-1)-1:0] RDataFB2D [nWP-1:0] ; // read data fb / 2D
reg [DATW -1:0] RDataFB3D [nWP-1:0][nWP-2:0]; // read data fb / 3D
reg [DATW -1:0] WDataFB2D [nWP-1:0] ; // write data / 2D
reg [DATW -1:0] RData2D [nRP-1:0] ; // read data / 2D
`ARRINIT;
always @* begin
// packing/unpacking arrays into 1D/2D/3D structures; see utils.vh for definitions
`ARR1D2D(nWP, ADRW,WAddr ,WAddr2D );
`ARR1D2D(nWP, ADRW,WAddr_r ,WAddr2D_r );
`ARR1D2D(nWP, DATW,WData ,WData2D );
`ARR1D2D(nWP, DATW,WData_r ,WData2D_r );
`ARR2D1D(nRP, DATW,RData2D ,RData );
`ARR2D3D(nWP,nRP ,DATW,RDataOut2D,RDataOut3D);
`ARR3D2D(nWP,nWP-1,ADRW,RAddrFB3D ,RAddrFB2D );
`ARR2D3D(nWP,nWP-1,DATW,RDataFB2D ,RDataFB3D );
end
// generate and instantiate mulriread RAM blocks
genvar wpi;
generate
for (wpi=0 ; wpi<nWP ; wpi=wpi+1) begin: RPORTwpi
// feedback multiread ram instantiation
mrram #( .MEMD (MEMD ), // memory depth
.DATW (DATW ), // data width
.nRP (nWP-1 ), // number of reading ports
.BYPS (WAWB || RDWB || RAWB), // bypass? 0:none; 1:single-stage; 2:two-stages
.ZERO ((wpi>0)&&(FILE!="") ), // binary / Initial RAM with zeros (has priority over FILE)
.FILE (FILE )) // initialization file, optional
mrram_fdb ( .clk (clk ), // clock - in
.WEnb (WEnb_r[wpi] ), // write enable (1 port) - in
.WAddr (WAddr2D_r[wpi] ), // write address (1 port) - in : [`log2(MEMD) -1:0]
.WData (WDataFB2D[wpi] ), // write data (1 port) - in : [DATW -1:0]
.RAddr (RAddrFB2D[wpi] ), // read addresses - packed from nRP read ports - in : [`log2(MEMD)*nRP-1:0]
.RData (RDataFB2D[wpi] )); // read data - packed from nRP read ports - out: [DATW *nRP-1:0]
// output multiread ram instantiation
mrram #( .MEMD (MEMD ), // memory depth
.DATW (DATW ), // data width
.nRP (nRP ), // number of reading ports
.BYPS (RDWB ? 2 : RAWB ), // bypass? 0:none; 1:single-stage; 2:two-stages
.ZERO ((wpi>0)&&(FILE!="") ), // binary / Initial RAM with zeros (has priority over FILE)
.FILE (FILE )) // initialization file, optional
mrram_out ( .clk (clk ), // clock - in
.WEnb (WEnb_r[wpi] ), // write enable (1 port) - in
.WAddr (WAddr2D_r[wpi] ), // write address (1 port) - in : [`log2(MEMD) -1:0]
.WData (WDataFB2D[wpi] ), // write data (1 port) - in : [DATW -1:0]
.RAddr (RAddr ), // read addresses - packed from nRP read ports - in : [`log2(MEMD)*nRP-1:0]
.RData (RDataOut2D[wpi] )); // read data - packed from nRP read ports - out: [DATW *nRP-1:0]
end
endgenerate
// combinatorial logic for output and feedback functions
integer i,j,k;
always @* begin
// generate output read functions
for(i=0;i<nRP;i=i+1) begin
RData2D[i] = RDataOut3D[0][i];
for(j=1;j<nWP;j=j+1) RData2D[i] = RData2D[i] ^ RDataOut3D[j][i];
end
// generate feedback functions
for(i=0;i<nWP;i=i+1) WDataFB2D[i] = WData2D_r[i];
for(i=0;i<nWP;i=i+1) begin
k = 0;
for(j=0;j<nWP-1;j=j+1) begin
k=k+(j==i);
RAddrFB3D[i][j] = WAddr2D[k];
WDataFB2D[k] = WDataFB2D[k] ^ RDataFB3D[i][j];
k=k+1;
end
end
end
endmodule
////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2014, University of British Columbia (UBC); All rights reserved. //
// //
// Redistribution and use in source and binary forms, with or without //
// modification, are permitted provided that the following conditions are met: //
// * Redistributions of source code must retain the above copyright //
// notice, this list of conditions and the following disclaimer. //
// * Redistributions in binary form must reproduce the above copyright //
// notice, this list of conditions and the following disclaimer in the //
// documentation and/or other materials provided with the distribution. //
// * Neither the name of the University of British Columbia (UBC) nor the names //
// of its contributors may be used to endorse or promote products //
// derived from this software without specific prior written permission. //
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE //
// DISCLAIMED. IN NO EVENT SHALL University of British Columbia (UBC) BE LIABLE //
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL //
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR //
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER //
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, //
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE //
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// mrram.v: Multiread-RAM based on bank replication using generic dual-ported RAM //
// with optional single-stage or two-stage bypass/ for normal mode ports //
// //
// Author: Ameer M.S. Abdelhadi (ameer@ece.ubc.ca, ameer.abdelhadi@gmail.com) //
// Switched SRAM-based Multi-ported RAM; University of British Columbia, 2014 //
////////////////////////////////////////////////////////////////////////////////////
`include "utils.vh"
module mrram
#( parameter MEMD = 16, // memory depth
parameter DATW = 32, // data width
parameter nRP = 3 , // number of reading ports
parameter BYPS = 1 , // bypass? 0:none; 1: single-stage; 2:two-stages
parameter ZERO = 0 , // binary / Initial RAM with zeros (has priority over FILE)
parameter FILE = "" // initialization mif file (don't pass extension), optional
)( input clk , // clock
input WEnb , // write enable (1 port)
input [`log2(MEMD) -1:0] WAddr, // write address (1 port)
input [DATW -1:0] WData, // write data (1 port)
input [`log2(MEMD)*nRP-1:0] RAddr, // read addresses - packed from nRP read ports
output reg [DATW *nRP-1:0] RData); // read data - packed from nRP read ports
localparam ADRW = `log2(MEMD); // address width
// unpacked read addresses/data
reg [ADRW-1:0] RAddr_upk [nRP-1:0]; // read addresses - unpacked 2D array
wire [DATW-1:0] RData_upk [nRP-1:0]; // read data - unpacked 2D array
// unpack read addresses; pack read data
`ARRINIT;
always @* begin
// packing/unpacking arrays into 1D/2D/3D structures; see utils.vh for definitions
`ARR1D2D(nRP,ADRW,RAddr,RAddr_upk);
`ARR2D1D(nRP,DATW,RData_upk,RData);
end
// generate and instantiate generic RAM blocks
genvar rpi;
generate
for (rpi=0 ; rpi<nRP ; rpi=rpi+1) begin: RPORTrpi
// generic dual-ported ram instantiation
dpram_bbs #( .MEMD (MEMD ), // memory depth
.DATW (DATW ), // data width
.BYPS (BYPS ), // bypass? 0: none; 1: single-stage; 2:two-stages
.ZERO (ZERO ), // binary / Initial RAM with zeros (has priority over INITFILE)
.FILE (FILE )) // initialization file, optional
dpram_bbsi ( .clk (clk ), // clock - in
.WEnb_A (1'b0 ), // write enable - in
.WEnb_B (WEnb ), // write enable - in
.Addr_A (RAddr_upk[rpi]), // write address - in : [`log2(MEMD)-1:0]
.Addr_B (WAddr ), // write address - in : [`log2(MEMD)-1:0]
.WData_A ({DATW{1'b1}} ), // write data - in : [DATW -1:0] / constant
.WData_B (WData ), // write data - in : [DATW -1:0]
.RData_A (RData_upk[rpi]), // read data - out: [DATW -1:0]
.RData_B ( )); // read data - out: [DATW -1:0]
end
endgenerate
endmodule
////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2014, University of British Columbia (UBC); All rights reserved. //
// //
// Redistribution and use in source and binary forms, with or without //
// modification, are permitted provided that the following conditions are met: //
// * Redistributions of source code must retain the above copyright //
// notice, this list of conditions and the following disclaimer. //
// * Redistributions in binary form must reproduce the above copyright //
// notice, this list of conditions and the following disclaimer in the //
// documentation and/or other materials provided with the distribution. //
// * Neither the name of the University of British Columbia (UBC) nor the names //
// of its contributors may be used to endorse or promote products //
// derived from this software without specific prior written permission. //
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE //
// DISCLAIMED. IN NO EVENT SHALL University of British Columbia (UBC) BE LIABLE //
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL //
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR //
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER //
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, //
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE //
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// mrram_swt.v: Multiread-RAM based on bank replication & generic dual-ported RAM //
// * switched read ports support //
// * optional single-stage or 2-stage bypass //
// //
// Author: Ameer M.S. Abdelhadi (ameer@ece.ubc.ca, ameer.abdelhadi@gmail.com) //
// Switched SRAM-based Multi-ported RAM; University of British Columbia, 2014 //
////////////////////////////////////////////////////////////////////////////////////
`include "utils.vh"
module mrram_swt
#( parameter MEMD = 16, // memory depth
parameter DATW = 32, // data width
parameter nRPF = 2 , // number of fixed read ports
parameter nRPS = 2 , // number of switched read ports
parameter BYPS = 1 , // bypass? 0:none; 1: single-stage; 2:two-stages
parameter ZERO = 0 , // binary / Initial RAM with zeros (has priority over FILE)
parameter FILE = "" // initialization mif file (don't pass extension), optional
)( input clk , // clock
input rdWr , // switch read/write (write is active low)
input WEnb , // write enable (1 port)
input [`log2(MEMD) -1:0] WAddr, // write address (1 port)
input [DATW -1:0] WData, // write data (1 port)
input [`log2(MEMD)*(nRPS+nRPF)-1:0] RAddr, // read addresses - packed from nRPF fixed & nRPS switched read ports
output reg [DATW *(nRPS+nRPF)-1:0] RData); // read data - packed from nRPF fixed & nRPS switched read ports
localparam nRPT = nRPS+nRPF ; // total number of read ports
localparam ADRW = `log2(MEMD); // address width
// unpacked read addresses/data
reg [ADRW-1:0] RAddr_upk [nRPT-1:0]; // read addresses - unpacked 2D array
wire [DATW-1:0] RData_upk [nRPT-1:0]; // read data - unpacked 2D array
// unpack read addresses; pack read data
`ARRINIT;
always @* begin
// packing/unpacking arrays into 1D/2D/3D structures; see utils.vh for definitions
`ARR1D2D(nRPT,ADRW,RAddr,RAddr_upk);
`ARR2D1D(nRPT,DATW,RData_upk,RData);
end
// generate and instantiate generic RAM blocks
genvar rpi;
generate
for (rpi=0 ; rpi<nRPF ; rpi=rpi+1) begin: RPORTrpi
// generic dual-ported ram instantiation
if (rpi<(nRPF-nRPS)) begin
dpram_bbs #( .MEMD (MEMD ), // memory depth
.DATW (DATW ), // data width
.BYPS (BYPS ), // bypass? 0: none; 1: single-stage; 2:two-stages
.ZERO (ZERO ), // binary / Initial RAM with zeros (has priority over INITFILE)
.FILE (FILE )) // initialization file, optional
dpram_bbsi ( .clk (clk ), // clock - in
.WEnb_A (1'b0 ), // write enable - in
.WEnb_B (WEnb && (!rdWr)), // write enable - in
.Addr_A (RAddr_upk[rpi] ), // write address - in : [`log2(MEMD)-1:0]
.Addr_B (WAddr ), // write address - in : [`log2(MEMD)-1:0]
.WData_A ({DATW{1'b1}} ), // change to 1'b0
.WData_B (WData ), // write data - in : [DATW -1:0]
.RData_A (RData_upk[rpi] ), // read data - out: [DATW -1:0]
.RData_B ( )); // read data - out: [DATW -1:0]
end
else begin
dpram_bbs #( .MEMD (MEMD ), // memory depth
.DATW (DATW ), // data width
.BYPS (BYPS ), // bypass? 0: none; 1: single-stage; 2:two-stages
.ZERO (ZERO ), // binary / Initial RAM with zeros (has priority over INITFILE)
.FILE (FILE )) // initialization file, optional
dpram_bbsi ( .clk (clk ), // clock - in
.WEnb_A (1'b0 ), // write enable - in
.WEnb_B (WEnb && (!rdWr) ), // write enable - in
.Addr_A ( RAddr_upk[rpi] ), // write address - in : [`log2(MEMD)-1:0]
.Addr_B (rdWr?RAddr_upk[rpi+nRPS]:WAddr), // write address - in : [`log2(MEMD)-1:0]
.WData_A ({DATW{1'b1}} ), // change to 1'b0
.WData_B (WData ), // write data - in : [DATW -1:0]
.RData_A (RData_upk[rpi] ), // read data - out: [DATW -1:0]
.RData_B (RData_upk[rpi+nRPS] )); // read data - out: [DATW -1:0]
end
end
endgenerate
endmodule
####################################################################################
## Copyright (c) 2014, University of British Columbia (UBC); All rights reserved. ##
## ##
## Redistribution and use in source and binary forms, with or without ##
## modification, are permitted provided that the following conditions are met: ##
## * Redistributions of source code must retain the above copyright ##
## notice, this list of conditions and the following disclaimer. ##
## * Redistributions in binary form must reproduce the above copyright ##
## notice, this list of conditions and the following disclaimer in the ##
## documentation and/or other materials provided with the distribution. ##
## * Neither the name of the University of British Columbia (UBC) nor the names ##
## of its contributors may be used to endorse or promote products ##
## derived from this software without specific prior written permission. ##
## ##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ##
## AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ##
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ##
## DISCLAIMED. IN NO EVENT SHALL University of British Columbia (UBC) BE LIABLE ##
## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ##
## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ##
## SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ##
## CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ##
## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ##
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ##
####################################################################################
####################################################################################
## Synopsys Design Constraints File ( .sdc ) ##
## Design constraints and timing assignments ##
## ##
## Author: Ameer M.S. Abdelhadi (ameer@ece.ubc.ca, ameer.abdelhadi@gmail.com) ##
## Switched SRAM-based Multi-ported RAM; University of British Columbia, 2014 ##
####################################################################################
# Clock constraints
create_clock -name "clk" -period 1.000ns [get_ports {clk}]
# Automatically constrain PLL and other generated clocks
derive_pll_clocks -create_base_clocks
# Automatically calculate clock uncertainty to jitter and other effects.
derive_clock_uncertainty
# tsu/th constraints
#set_input_delay -clock "clk" -max 0.8ns [get_ports {wAddr}]
#set_input_delay -clock "clk" -min 0.100ns [get_ports {wAddr}]
# tco constraints
#set_output_delay -clock "clk" -max 0.8ns [get_ports {rData}]
#set_output_delay -clock "clk" -min -0.100ns [get_ports {rData}]
# disable input/output combinatorial timing (all ports are registered)
set_disable_timing -from [all_inputs] *
set_disable_timing -to [all_outputs] *
////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2014, University of British Columbia (UBC); All rights reserved. //
// //
// Redistribution and use in source and binary forms, with or without //
// modification, are permitted provided that the following conditions are met: //
// * Redistributions of source code must retain the above copyright //
// notice, this list of conditions and the following disclaimer. //
// * Redistributions in binary form must reproduce the above copyright //
// notice, this list of conditions and the following disclaimer in the //
// documentation and/or other materials provided with the distribution. //
// * Neither the name of the University of British Columbia (UBC) nor the names //
// of its contributors may be used to endorse or promote products //
// derived from this software without specific prior written permission. //
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE //
// DISCLAIMED. IN NO EVENT SHALL University of British Columbia (UBC) BE LIABLE //
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL //
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR //
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER //
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, //
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE //
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// smpram.v: Switched multiported-RAM: register-based, XOR-based, register-based //
// LVT, SRAM-based binary-coded and one-hot-coded I-LVT //
// //
// Author: Ameer M.S. Abdelhadi (ameer@ece.ubc.ca, ameer.abdelhadi@gmail.com) //
// Switched SRAM-based Multi-ported RAM; University of British Columbia, 2014 //
////////////////////////////////////////////////////////////////////////////////////
`include "utils.vh"
// include config file for synthesis mode
`ifndef SIM
`include "config.vh"
`endif
module smpram
#( parameter MEMD = `MEMD, // memory depth
parameter DATW = `DATW, // data width
parameter nRPF = `nRPF, // number of fixed (simple) read ports
parameter nWPF = `nWPF, // number of fixed (simple) write ports
parameter nRPS = `nRPS, // number of switched read ports
parameter nWPS = `nWPS, // number of switched write ports
parameter ARCH = `ARCH, // architecture: REG, XOR, LVTREG, LVTBIN, LVT1HT, AUTO
parameter BYPS = `BYPS, // Bypassing type: NON, WAW, RAW, RDW
// WAW: Allow Write-After-Write (need to bypass feedback ram)
// RAW: new data for Read-after-Write (need to bypass output ram)
// RDW: new data for Read-During-Write
parameter FILE = "" // initialization file, optional
)( input clk , // clock
input rdWr , // switch read/write (write is active low)
input [ (nWPF+nWPS)-1:0] WEnb , // write enables - packed from nWPF fixed & nWPS switched write ports
input [`log2(MEMD)*(nWPF+nWPS)-1:0] WAddr, // write addresses - packed from nWPF fixed & nWPS switched write ports
input [DATW *(nWPF+nWPS)-1:0] WData, // write data - packed from nWPF fixed & nWPS switched write ports
input [`log2(MEMD)*(nRPF+nRPS)-1:0] RAddr, // read addresses - packed from nRPF fixed & nRPS switched read ports
output wire [DATW *(nRPF+nRPS)-1:0] RData); // read data - packed from nRPF fixed & nRPS switched read ports
// local parameters
localparam nWPT = nWPF+nWPS ; // total number of write ports
localparam nRPT = nRPF+nRPS ; // total number of read ports
localparam ADDRW = `log2(MEMD); // address width
// Auto calculation of best method when ARCH="AUTO" is selected.
localparam l2nW = `log2(nWPT) ;
localparam nBitsXOR = DATW*(nWPT-1) ;
localparam nBitsBIN = l2nW*(nWPT+nRPT-1);
localparam nBits1HT = (nWPT-1)*(nRPT+1) ;
localparam AUTOARCH = (MEMD<=1024 ) ? "REG" :
( (MEMD<=2048 ) ? "LVTREG" :
( ((nWPS==0)&(nBitsXOR<nBits1HT)&(nBitsXOR<nBitsBIN)) ? "XOR" :
( (nBits1HT<=nBitsBIN ) ? "LVT1HT" : "LVTBIN" )));
// if ARCH is not one of known types (REG, XOR, LVTREG, LVTBIN, LVT1HT) choose auto (best) ARCH
localparam iARCH = ((ARCH!="REG")&&(ARCH!="XOR")&&(ARCH!="LVTREG")&&(ARCH!="LVTBIN")&&(ARCH!="LVT1HT")) ? AUTOARCH : ARCH;
// Bypassing indicators
localparam WAWB = BYPS!="NON" ; // allow Write-After-Write (need to bypass feedback ram)
localparam RAWB = (BYPS=="RAW")||(BYPS=="RDW"); // new data for Read-after-Write (need to bypass output ram)
localparam RDWB = BYPS=="RDW" ; // new data for Read-During-Write
// generate and instantiate RAM with specific implementation
generate
if (nWPT==1) begin
// instantiate multiread RAM
mrram #( .MEMD (MEMD ), // memory depth
.DATW (DATW ), // data width
.nRP (nRPT ), // number of reading ports
.BYPS (RDWB?2:RAWB), // bypass? 0:none; 1:single-stage; 2:two-stages
.FILE (FILE )) // initialization file, optional
mrram_ins ( .clk (clk ), // clock - in
.WEnb (WEnb ), // write enable (1 port) - in
.WAddr (WAddr ), // write address (1 port) - in : [`log2(MEMD) -1:0]
.WData (WData ), // write data (1 port) - in : [DATW -1:0]
.RAddr (RAddr ), // read addresses - packed from nRP read ports - in : [`log2(MEMD)*nRP-1:0]
.RData (RData )); // read data - packed from nRP read ports - out: [DATW *nRP-1:0]
end
else if (iARCH=="REG" ) begin
// instantiate multiported register-based RAM
mpram_reg #( .MEMD (MEMD ), // memory depth
.DATW (DATW ), // data width
.nRP (nRPT ), // number of reading ports
.nWP (nWPT ), // number of writing ports
.RDWB (RDWB ), // provide new data when Read-During-Write?
.FILE (FILE )) // initializtion file, optional
mpram_reg_i ( .clk (clk ), // clock
.WEnb (WEnb ), // write enables - packed from nWP write ports - in : [ nWP-1:0 ]
.WAddr (WAddr), // write addresses - packed from nWP write ports - in : [`log2(MEMD)*nWP-1:0]
.WData (WData), // write data - packed from nWP write ports - in : [DATW *nWP-1:0]
.RAddr (RAddr), // read addresses - packed from nRP read ports - in : [`log2(MEMD)*nRP-1:0]
.RData (RData)); // read data - packed from nRP read ports - out: [DATW *nRP-1:0]
end
else if (iARCH=="XOR" ) begin
// instantiate XOR-based multiported RAM
mpram_xor #( .MEMD (MEMD ), // memory depth
.DATW (DATW ), // data width
.nRP (nRPT ), // number of reading ports
.nWP (nWPT ), // number of writing ports
.WAWB (WAWB ), // allow Write-After-Write (need to bypass feedback ram)
.RAWB (RAWB ), // new data for Read-after-Write (need to bypass output ram)
.RDWB (RDWB ), // new data for Read-During-Write
.FILE (FILE )) // initializtion file, optional
mpram_xor_i ( .clk (clk ), // clock
.WEnb (WEnb ), // write enables - packed from nWp write - in : [ nWPT-1:0]
.WAddr (WAddr), // write addresses - packed from nWP write ports - in : [`log2(MEMD)*nWP-1:0]
.WData (WData), // write data - packed from nWP write ports - in : [DATW *nWP-1:0]
.RAddr (RAddr), // read addresses - packed from nRP read ports - in : [`log2(MEMD)*nRP-1:0]
.RData (RData)); // read data - packed from nRP read ports - out: [DATW *nRP-1:0]
end
else begin
// instantiate an LVT-based multiported RAM
mpram_lvt #( .MEMD (MEMD ), // memory depth
.DATW (DATW ), // data width
.nRPF (nRPF ), // number of fixed read ports
.nWPF (nWPF ), // number of fixed write ports
.nRPS (nRPS ), // number of switched read ports
.nWPS (nWPS ), // number of switched write ports
.LVTA (iARCH), // LVT architecture type: LVTREG, LVTBIN, LVT1HT
.WAWB (WAWB ), // allow Write-After-Write (need to bypass feedback ram)
.RAWB (RAWB ), // new data for Read-after-Write (need to bypass output ram)
.RDWB (RDWB ), // new data for Read-During-Write
.FILE (FILE )) // initializtion file, optional
mpram_lvt_i ( .clk (clk ), // clock
.rdWr (rdWr ), // switch read/write (write is active low)
.WEnb (WEnb ), // write enables - packed from nWPF fixed & nWPS switched write ports - in : [(nWPF+nWPS)-1:0 ]
.WAddr (WAddr), // write addresses - packed from nWPF fixed & nWPS switched write ports - in : [`log2(MEMD)*(nWPF+nWPS)-1:0]
.WData (WData), // write data - packed from nWPF fixed & nWPS switched write ports - in : [DATW *(nWPF+nWPS)-1:0]
.RAddr (RAddr), // read addresses - packed from nRPF fixed & nRPS switched write ports - in : [`log2(MEMD)*(nRPF+nRPS)-1:0]
.RData (RData)); // read data - packed from nRPF fixed & nRPS switched write ports - out: [DATW *(nRPF+nRPS)-1:0]
end
endgenerate
endmodule
////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2014, University of British Columbia (UBC); All rights reserved. //
// //
// Redistribution and use in source and binary forms, with or without //
// modification, are permitted provided that the following conditions are met: //
// * Redistributions of source code must retain the above copyright //
// notice, this list of conditions and the following disclaimer. //
// * Redistributions in binary form must reproduce the above copyright //
// notice, this list of conditions and the following disclaimer in the //
// documentation and/or other materials provided with the distribution. //
// * Neither the name of the University of British Columbia (UBC) nor the names //
// of its contributors may be used to endorse or promote products //
// derived from this software without specific prior written permission. //
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE //
// DISCLAIMED. IN NO EVENT SHALL University of British Columbia (UBC) BE LIABLE //
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL //
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR //
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER //
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, //
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE //
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// smpram_tb.v: switched multiported-RAM testbench //
// //
// Author: Ameer M.S. Abdelhadi (ameer@ece.ubc.ca, ameer.abdelhadi@gmail.com) //
// Switched SRAM-based Multi-ported RAM; University of British Columbia, 2014 //
////////////////////////////////////////////////////////////////////////////////////
`include "utils.vh"
module smpram_tb;
// design parameters
localparam MEMD = `MEMD; // memory depth
localparam DATW = `DATW; // data width
localparam nRPF = `nRPF; // number of fixed (simple) read ports
localparam nWPF = `nWPF; // number of fixed (simple) write ports
localparam nRPS = `nRPS; // number of switched read ports
localparam nWPS = `nWPS; // number of switched write ports
localparam CYCC = `CYCC; // simulation cycles count
localparam BYPS = `BYPS; // set data-dependency and allowance
// bypassing type: NON, WAW, RAW, RDW
// WAW: Allow Write-After-Write
// RAW: new data for Read-after-Write
// RDW: new data for Read-During-Write
localparam VERB = `VERB; // verbose logging (1:yes; 0:no)
// total ports number
localparam nWPT = nWPF+nWPS;
localparam nRPT = nRPF+nRPS;
// bypassing indicators
localparam WDWB = 0 ; // allow Write-During-Write (WDW)
localparam WAWB = BYPS!="NON" ; // allow Write-After-Write (WAW)
localparam RAWB = (BYPS=="RAW")||(BYPS=="RDW"); // new data for Read-After-Write (RAW)
localparam RDWB = BYPS=="RDW" ; // new data for Read-During-Write (RDW)
// local parameters
localparam ADRW = `log2(MEMD); // address size
localparam CYCT = 10 ; // cycle time
localparam RSTT = 5.2*CYCT ; // reset time
localparam TERFAIL = 0 ; // terminate if fail?
localparam TIMEOUT = 2*CYCT*CYCC; // simulation time
reg clk = 1'b0 ; // global clock
reg rst = 1'b1 ; // global reset
reg rdWr ; // switch read/write (write is active low)
reg [ nWPT-1:0] WEnb ; // write enable for each writing port
reg [ADRW*nWPT-1:0] WAddr_pck ; // write addresses - packed from nWPT write ports
reg [ADRW -1:0] WAddr_upk [nWPT-1:0]; // write addresses - unpacked 2D array
reg [ADRW*nRPT-1:0] RAddr_pck ; // read addresses - packed from nRPT read ports
reg [ADRW -1:0] RAddr_upk [nRPT-1:0]; // read addresses - unpacked 2D array
reg [DATW*nWPT-1:0] WData_pck ; // write data - packed from nWPT read ports
reg [DATW -1:0] WData_upk [nWPT-1:0]; // write data - unpacked 2D array
wire [DATW*nRPT-1:0] RData_pck_reg ; // read data - packed from nRPT read ports
reg [DATW -1:0] RData_upk_reg [nRPT-1:0]; // read data - unpacked 2D array
wire [DATW*nRPT-1:0] RData_pck_xor ; // read data - packed from nRPT read ports
reg [DATW -1:0] RData_upk_xor [nRPT-1:0]; // read data - unpacked 2D array
wire [DATW*nRPT-1:0] RData_pck_lvtreg ; // read data - packed from nRPT read ports
reg [DATW -1:0] RData_upk_lvtreg [nRPT-1:0]; // read data - unpacked 2D array
wire [DATW*nRPT-1:0] RData_pck_lvtbin ; // read data - packed from nRPT read ports
reg [DATW -1:0] RData_upk_lvtbin [nRPT-1:0]; // read data - unpacked 2D array
wire [DATW*nRPT-1:0] RData_pck_lvt1ht ; // read data - packed from nRPT read ports
reg [DATW -1:0] RData_upk_lvt1ht [nRPT-1:0]; // read data - unpacked 2D array
integer i,j; // general indeces
// generates random ram hex/mif initializing files
task genInitFiles;
input [31 :0] DEPTH ; // memory depth
input [31 :0] WIDTH ; // memoty width
input [255 :0] INITVAL; // initial vlaue (if not random)
input RAND ; // random value?
input [1:8*20] FILEN ; // memory initializing file name
reg [255 :0] ramdata;
integer addr,hex_fd,mif_fd;
begin
// open hex/mif file descriptors
hex_fd = $fopen({FILEN,".hex"},"w");
mif_fd = $fopen({FILEN,".mif"},"w");
// write mif header
$fwrite(mif_fd,"WIDTH = %0d;\n",WIDTH);
$fwrite(mif_fd,"DEPTH = %0d;\n",DEPTH);
$fwrite(mif_fd,"ADDRESS_RADIX = HEX;\n" );
$fwrite(mif_fd,"DATA_RADIX = HEX;\n\n" );
$fwrite(mif_fd,"CONTENT BEGIN\n" );
// write random memory lines
for(addr=0;addr<DEPTH;addr=addr+1) begin
if (RAND) begin
`GETRAND(ramdata,WIDTH);
end else ramdata = INITVAL;
$fwrite(hex_fd,"%0h\n",ramdata);
$fwrite(mif_fd," %0h : %0h;\n",addr,ramdata);
end
// write mif tail
$fwrite(mif_fd,"END;\n");
// close hex/mif file descriptors
$fclose(hex_fd);
$fclose(mif_fd);
end
endtask
integer rep_fd, ferr;
initial begin
// write header
rep_fd = $fopen("sim.res","r"); // try to open report file for read
$ferror(rep_fd,ferr); // detect error
$fclose(rep_fd);
rep_fd = $fopen("sim.res","a+"); // open report file for append
if (ferr) begin // if file is new (can't open for read); write header
$fwrite(rep_fd,"Multiported RAM Architectural Parameters Simulation Results for Different Designs \n");
$fwrite(rep_fd,"==================================================== =========================================\n");
$fwrite(rep_fd,"Memory Data Write Read Bypass Simulation XOR-based Reg-LVT SRAM-LVT SRAM-LVT\n");
$fwrite(rep_fd,"Depth Width Ports Ports Type Cycles Binary Onehot \n");
$fwrite(rep_fd,"================================================================================================\n");
end
$write("Simulating multi-ported RAM:\n");
$write("Fixed write ports: %0d\n" ,nWPF );
$write("Fixed read ports: %0d\n" ,nRPF );
$write("switched write ports: %0d\n" ,nWPS );
$write("switched read ports: %0d\n" ,nRPS );
$write("Data width : %0d\n" ,DATW );
$write("RAM depth : %0d\n" ,MEMD );
$write("Address width : %0d\n\n",ADRW );
// generate random ram hex/mif initializing file
genInitFiles(MEMD,DATW ,0,1,"init_ram");
// finish simulation
#(TIMEOUT) begin
$write("*** Simulation terminated due to timeout\n");
$finish;
end
end
// generate clock and reset
always #(CYCT/2) clk = ~clk; // toggle clock
initial #(RSTT ) rst = 1'b0; // lower reset
// pack/unpack data and addresses
`ARRINIT;
always @* begin
// packing/unpacking arrays into 1D/2D/3D structures; see utils.vh for definitions
`ARR2D1D(nRPT,ADRW,RAddr_upk ,RAddr_pck );
`ARR2D1D(nWPT,ADRW,WAddr_upk ,WAddr_pck );
`ARR1D2D(nWPT,DATW,WData_pck ,WData_upk );
`ARR1D2D(nRPT,DATW,RData_pck_reg ,RData_upk_reg );
`ARR1D2D(nRPT,DATW,RData_pck_xor ,RData_upk_xor );
`ARR1D2D(nRPT,DATW,RData_pck_lvtreg,RData_upk_lvtreg);
`ARR1D2D(nRPT,DATW,RData_pck_lvtbin,RData_upk_lvtbin);
`ARR1D2D(nRPT,DATW,RData_pck_lvt1ht,RData_upk_lvt1ht);
end
// register write addresses
reg [ADRW-1:0] WAddr_r_upk [nWPT-1:0]; // previous (registerd) write addresses - unpacked 2D array
always @(posedge clk)
//WAddr_r_pck <= WAddr_pck;
for (i=0;i<nWPT;i=i+1) WAddr_r_upk[i] <= WAddr_upk[i];
// register read addresses
reg [ADRW-1:0] RAddr_r_upk [nRPT-1:0]; // previous (registerd) write addresses - unpacked 2D array
always @(posedge clk)
//WAddr_r_pck <= WAddr_pck;
for (i=0;i<nRPF;i=i+1) RAddr_r_upk[i] <= RAddr_upk[i];
// generate random write data and random write/read addresses; on falling edge
reg wdw_addr; // indicates same write addresses on same cycle (Write-During-Write)
reg waw_addr; // indicates same write addresses on next cycle (Write-After-Write)
reg rdw_addr; // indicates same read/write addresses on same cycle (Read-During-Write)
reg raw_addr; // indicates same read address on next cycle (Read-After-Write)
always @(negedge clk) begin
// generate random write addresses; different that current and previous write addresses
for (i=0;i<nWPT;i=i+1) begin
wdw_addr = 1; waw_addr = 1;
while (wdw_addr || waw_addr) begin
`GETRAND(WAddr_upk[i],ADRW);
wdw_addr = 0; waw_addr = 0;
if (!WDWB) for (j=0;j<i ;j=j+1) wdw_addr = wdw_addr || (WAddr_upk[i] == WAddr_upk[j] );
if (!WAWB) for (j=0;j<nWPT;j=j+1) waw_addr = waw_addr || (WAddr_upk[i] == WAddr_r_upk[j]);
end
end
// generate random read addresses; different that current and previous write addresses
for (i=0;i<nRPT;i=i+1) begin
rdw_addr = 1; raw_addr = 1;
while (rdw_addr || raw_addr) begin
`GETRAND(RAddr_upk[i],ADRW);
rdw_addr = 0; raw_addr = 0;
if (!RDWB) for (j=0;j<nWPT;j=j+1) rdw_addr = rdw_addr || (RAddr_upk[i] == WAddr_upk[j] );
if (!RAWB) for (j=0;j<nWPT;j=j+1) raw_addr = raw_addr || (RAddr_upk[i] == WAddr_r_upk[j]);
end
end
// generate random write data and write enables
`GETRAND(WData_pck,DATW*nWPT);
`GETRAND(rdWr ,1 );
`GETRAND(WEnb ,nWPT );
if (rdWr) WEnb={nWPF{1'b1}}&WEnb; // if read mode, disable unused write ports
if (rst ) WEnb={nWPT{1'b0}} ; // if reset, disable all writes
end
integer cycc=1; // cycles count
integer cycp=0; // cycles percentage
integer errc=0; // errors count
integer fail ;
integer pass_xor_cur ; // xor multiported-ram passed in current cycle
integer pass_lvt_reg_cur; // lvt_reg multiported-ram passed in current cycle
integer pass_lvt_bin_cur; // lvt_bin multiported-ram passed in current cycle
integer pass_lvt_1ht_cur; // lvt_1ht multiported-ram passed in current cycle
integer pass_xor = 1; // xor multiported-ram passed
integer pass_lvt_reg = 1; // lvt_reg multiported-ram passed
integer pass_lvt_bin = 1; // lvt_bin multiported-ram passed
integer pass_lvt_1ht = 1; // lvt_qht multiported-ram passed
always @(negedge clk)
if (!rst) begin
#(CYCT/10) // a little after falling edge
if (VERB) begin // write input data
$write("%-7d:\t",cycc);
$write("ReadMode:%1d ",rdWr);
$write("BeforeRise: ");
$write("WEnb=" ); `ARRPRN(nWPT,WEnb ); $write("; " );
$write("WAddr=" ); `ARRPRN(nWPT,WAddr_upk); $write("; " );
$write("WData=" ); `ARRPRN(nWPT,WData_upk); $write("; " );
$write("RAddr=" ); `ARRPRN(nRPT,RAddr_upk); $write(" - ");
end
#(CYCT/2) // a little after rising edge
// compare results: in read mode, campare all ports, in normal mode, compare only first nRPF ports
pass_xor_cur = rdWr ? (RData_pck_reg===RData_pck_xor ) : (RData_pck_reg[nRPF*DATW-1:0]===RData_pck_xor[nRPF*DATW-1:0] );
pass_lvt_reg_cur = rdWr ? (RData_pck_reg===RData_pck_lvtreg) : (RData_pck_reg[nRPF*DATW-1:0]===RData_pck_lvtreg[nRPF*DATW-1:0]);
pass_lvt_bin_cur = rdWr ? (RData_pck_reg===RData_pck_lvtbin) : (RData_pck_reg[nRPF*DATW-1:0]===RData_pck_lvtbin[nRPF*DATW-1:0]);
pass_lvt_1ht_cur = rdWr ? (RData_pck_reg===RData_pck_lvt1ht) : (RData_pck_reg[nRPF*DATW-1:0]===RData_pck_lvt1ht[nRPF*DATW-1:0]);
pass_xor = pass_xor && pass_xor_cur ;
pass_lvt_reg = pass_lvt_reg && pass_lvt_reg_cur;
pass_lvt_bin = pass_lvt_bin && pass_lvt_bin_cur;
pass_lvt_1ht = pass_lvt_1ht && pass_lvt_1ht_cur;
fail = !(pass_xor && pass_lvt_reg && pass_lvt_bin && pass_lvt_1ht);
if (VERB) begin // write outputs
$write("AfterRise: ");
$write("RData_reg=" ); `ARRPRN(nRPT,RData_upk_reg ); $write("; ");
$write("RData_xor=" ); `ARRPRN(nRPT,RData_upk_xor ); $write(":%s",pass_xor_cur ? "pass" : "fail"); $write("; " );
$write("RData_lvt_reg="); `ARRPRN(nRPT,RData_upk_lvtreg); $write(":%s",pass_lvt_reg_cur ? "pass" : "fail"); $write("; " );
$write("RData_lvt_bin="); `ARRPRN(nRPT,RData_upk_lvtbin); $write(":%s",pass_lvt_bin_cur ? "pass" : "fail"); $write("; " );
$write("RData_lvt_1ht="); `ARRPRN(nRPT,RData_upk_lvt1ht); $write(":%s",pass_lvt_1ht_cur ? "pass" : "fail"); $write(";\n");
end else begin
if ((100*cycc/CYCC)!=cycp) begin cycp=100*cycc/CYCC; $write("%-3d%% passed\t(%-7d / %-7d) cycles\n",cycp,cycc,CYCC); end
end
if (fail && TERFAIL) begin
$write("*** Simulation terminated due to a mismatch\n");
$finish;
end
if (cycc==CYCC) begin
$write("*** Simulation terminated after %0d cycles. Simulation results:\n",CYCC);
$write("XOR-based = %s",pass_xor ? "pass;\n" : "fail;\n");
$write("Register-based LVT = %s",pass_lvt_reg ? "pass;\n" : "fail;\n");
$write("Binary I-LVT = %s",pass_lvt_bin ? "pass;\n" : "fail;\n");
$write("Onehot I-LVT = %s",pass_lvt_1ht ? "pass;\n" : "fail;\n");
// Append report file
$fwrite(rep_fd,"%-7d %-5d %2d-%-2d %2d-%-2d %-6s %-10d %-9s %-7s %-8s %-08s\n",MEMD,DATW,nWPF,nWPS,nRPF,nRPS,BYPS,CYCC,pass_xor?"pass":"fail",pass_lvt_reg?"pass":"fail",pass_lvt_bin?"pass":"fail",pass_lvt_1ht?"pass":"fail");
$fclose(rep_fd);
$finish;
end
cycc=cycc+1;
end
// instantiate multiported register-based ram as reference for all other implementations
smpram #( .MEMD (MEMD ), // memory depth
.DATW (DATW ), // data width
.nRPF (nRPF ), // number of fixed (simple) read ports
.nWPF (nWPF ), // number of fixed (simple) write ports
.nRPS (nRPS ), // number of switched read ports
.nWPS (nWPS ), // number of switched write ports
.ARCH ("REG" ), // multi-port RAM implementation type
.BYPS (BYPS ), // Bypassing type: NON, WAW, RAW, RDW
.FILE ("init_ram" )) // initializtion file, optional
smpram_reg_ref ( .clk (clk ), // clock
.rdWr (rdWr ), // switch read/write (write is active low)
.WEnb (WEnb ), // write enable - packed from nWPF fixed and nWPS switched write ports - in : [ (nWPF+nWPS)-1:0]
.WAddr (WAddr_pck ), // write addresses - packed from nWPF fixed and nWPS switched write ports - in : [`log2(MEMD)*(nWPF+nWPS)-1:0]
.WData (WData_pck ), // write data - packed from nWPF fixed and nWPS switched write ports - in : [DATW *(nWPF+nWPS)-1:0]
.RAddr (RAddr_pck ), // read addresses - packed from nRPF fixed and nRPS switched read ports - in : [`log2(MEMD)*(nRPF+nRPS)-1:0]
.RData (RData_pck_reg )); // read data - packed from nRPF fixed and nRPS switched read ports - out: [DATW *(nRPF+nRPS)-1:0]
// instantiate XOR-based multiported-RAM
smpram #( .MEMD (MEMD ), // memory depth
.DATW (DATW ), // data width
.nRPF (nRPF ), // number of fixed (simple) read ports
.nWPF (nWPF ), // number of fixed (simple) write ports
.nRPS (nRPS ), // number of switched read ports
.nWPS (nWPS ), // number of switched write ports
.ARCH ("XOR" ), // multi-port RAM implementation type
.BYPS (BYPS ), // Bypassing type: NON, WAW, RAW, RDW
.FILE ("init_ram" )) // initializtion file, optional
smpram_xor_dut ( .clk (clk ), // clock
.rdWr (rdWr ), // switch read/write (write is active low)
.WEnb (WEnb ), // write enable - packed from nWPF fixed and nWPS switched write ports - in : [ (nWPF+nWPS)-1:0]
.WAddr (WAddr_pck ), // write addresses - packed from nWPF fixed and nWPS switched write ports - in : [`log2(MEMD)*(nWPF+nWPS)-1:0]
.WData (WData_pck ), // write data - packed from nWPF fixed and nWPS switched write ports - in : [DATW *(nWPF+nWPS)-1:0]
.RAddr (RAddr_pck ), // read addresses - packed from nRPF fixed and nRPS switched read ports - in : [`log2(MEMD)*(nRPF+nRPS)-1:0]
.RData (RData_pck_xor )); // read data - packed from nRPF fixed and nRPS switched read ports - out: [DATW *(nRPF+nRPS)-1:0]
// instantiate a multiported-RAM with binary-coded register-based LVT
smpram #( .MEMD (MEMD ), // memory depth
.DATW (DATW ), // data width
.nRPF (nRPF ), // number of fixed (simple) read ports
.nWPF (nWPF ), // number of fixed (simple) write ports
.nRPS (nRPS ), // number of switched read ports
.nWPS (nWPS ), // number of switched write ports
.ARCH ("LVTREG" ), // multi-port RAM implementation type
.BYPS (BYPS ), // Bypassing type: NON, WAW, RAW, RDW
.FILE ("init_ram" )) // initializtion file, optional
smpram_lvtreg_dut ( .clk (clk ), // clock
.rdWr (rdWr ), // switch read/write (write is active low)
.WEnb (WEnb ), // write enable - packed from nWPF fixed and nWPS switched write ports - in : [ (nWPF+nWPS)-1:0]
.WAddr (WAddr_pck ), // write addresses - packed from nWPF fixed and nWPS switched write ports - in : [`log2(MEMD)*(nWPF+nWPS)-1:0]
.WData (WData_pck ), // write data - packed from nWPF fixed and nWPS switched write ports - in : [DATW *(nWPF+nWPS)-1:0]
.RAddr (RAddr_pck ), // read addresses - packed from nRPF fixed and nRPS switched read ports - in : [`log2(MEMD)*(nRPF+nRPS)-1:0]
.RData (RData_pck_lvtreg)); // read data - packed from nRPF fixed and nRPS switched read ports - out: [DATW *(nRPF+nRPS)-1:0]
// instantiate a multiported-RAM with binary-coded SRAM LVT
smpram #( .MEMD (MEMD ), // memory depth
.DATW (DATW ), // data width
.nRPF (nRPF ), // number of fixed (simple) read ports
.nWPF (nWPF ), // number of fixed (simple) write ports
.nRPS (nRPS ), // number of switched read ports
.nWPS (nWPS ), // number of switched write ports
.ARCH ("LVTBIN" ), // multi-port RAM implementation type
.BYPS (BYPS ), // Bypassing type: NON, WAW, RAW, RDW
.FILE ("init_ram" )) // initializtion file, optional
smpram_lvtbin_dut ( .clk (clk ), // clock
.rdWr (rdWr ), // switch read/write (write is active low)
.WEnb (WEnb ), // write enable - packed from nWPF fixed and nWPS switched write ports - in : [ (nWPF+nWPS)-1:0]
.WAddr (WAddr_pck ), // write addresses - packed from nWPF fixed and nWPS switched write ports - in : [`log2(MEMD)*(nWPF+nWPS)-1:0]
.WData (WData_pck ), // write data - packed from nWPF fixed and nWPS switched write ports - in : [DATW *(nWPF+nWPS)-1:0]
.RAddr (RAddr_pck ), // read addresses - packed from nRPF fixed and nRPS switched read ports - in : [`log2(MEMD)*(nRPF+nRPS)-1:0]
.RData (RData_pck_lvtbin)); // read data - packed from nRPF fixed and nRPS switched read ports - out: [DATW *(nRPF+nRPS)-1:0]
// instantiate a multiported-RAM with onehot-coded SRAM LVT
smpram #( .MEMD (MEMD ), // memory depth
.DATW (DATW ), // data width
.nRPF (nRPF ), // number of fixed (simple) read ports
.nWPF (nWPF ), // number of fixed (simple) write ports
.nRPS (nRPS ), // number of switched read ports
.nWPS (nWPS ), // number of switched write ports
.ARCH ("LVT1HT" ), // multi-port RAM implementation type
.BYPS (BYPS ), // Bypassing type: NON, WAW, RAW, RDW
.FILE ("init_ram" )) // initializtion file, optional
smpram_lvt1ht_dut ( .clk (clk ), // clock
.rdWr (rdWr ), // switch read/write (write is active low)
.WEnb (WEnb ), // write enable - packed from nWPF fixed and nWPS switched write ports - in : [ (nWPF+nWPS)-1:0]
.WAddr (WAddr_pck ), // write addresses - packed from nWPF fixed and nWPS switched write ports - in : [`log2(MEMD)*(nWPF+nWPS)-1:0]
.WData (WData_pck ), // write data - packed from nWPF fixed and nWPS switched write ports - in : [DATW *(nWPF+nWPS)-1:0]
.RAddr (RAddr_pck ), // read addresses - packed from nRPF fixed and nRPS switched read ports - in : [`log2(MEMD)*(nRPF+nRPS)-1:0]
.RData (RData_pck_lvt1ht)); // read data - packed from nRPF fixed and nRPS switched read ports - out: [DATW *(nRPF+nRPS)-1:0]
endmodule
////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2014, University of British Columbia (UBC); All rights reserved. //
// //
// Redistribution and use in source and binary forms, with or without //
// modification, are permitted provided that the following conditions are met: //
// * Redistributions of source code must retain the above copyright //
// notice, this list of conditions and the following disclaimer. //
// * Redistributions in binary form must reproduce the above copyright //
// notice, this list of conditions and the following disclaimer in the //
// documentation and/or other materials provided with the distribution. //
// * Neither the name of the University of British Columbia (UBC) nor the names //
// of its contributors may be used to endorse or promote products //
// derived from this software without specific prior written permission. //
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE //
// DISCLAIMED. IN NO EVENT SHALL University of British Columbia (UBC) BE LIABLE //
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL //
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR //
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER //
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, //
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE //
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// utils.vh: Design utilities (pre-compile) //
// //
// Author: Ameer M.S. Abdelhadi (ameer@ece.ubc.ca, ameer.abdelhadi@gmail.com) //
// Switched SRAM-based Multi-ported RAM; University of British Columbia, 2014 //
////////////////////////////////////////////////////////////////////////////////////
`ifndef __UTILS_VH__
`define __UTILS_VH__
`define DEBUG_MODE // debug mode, comment this line for other modes
`define VERBOSE // verbose debug, comment this line for other modes
// Initiate Array structure - use once before calling packing/unpacking modules
`define ARRINIT integer _i_,_j_
// pack/unpack 1D/2D/3D arrays; use in "always @*" if combinatorial
// ARR2D1D: converts an array of vectors (2D) into a vector (1D) - (2D to 1D packing )
// ARR1D2D: converts a vector (1D) into an array of vectors (2D) - (1D to 2D unpacking)
// ARR2D3D: converts an array of vectors (2D) into a 2D array of vectors (3D) - (2D to 3D unpacking)
// ARR3D2D: converts a 2D array of vectors (3D) into an array of vectors (2D) - (3D to 2D packing )
`define ARR2D1D(D1W,D2W, SRC,DST) for(_i_=1;_i_<=(D1W);_i_=_i_+1) DST[((D2W)*_i_-1)-:D2W] = SRC[_i_-1]
`define ARR1D2D(D1W,D2W, SRC,DST) for(_i_=1;_i_<=(D1W);_i_=_i_+1) DST[_i_-1] = SRC[((D2W)*_i_-1)-:D2W]
`define ARR2D3D(D1W,D2W,D3W,SRC,DST) for(_i_=0;_i_< (D1W);_i_=_i_+1) for(_j_=1;_j_<=(D2W);_j_=_j_+1) DST[_i_][_j_-1] = SRC[_i_][((D3W)*_j_-1)-:D3W]
`define ARR3D2D(D1W,D2W,D3W,SRC,DST) for(_i_=0;_i_< (D1W);_i_=_i_+1) for(_j_=1;_j_<=(D2W);_j_=_j_+1) DST[_i_][((D3W)*_j_-1)-:D3W] = SRC[_i_][_j_-1]
// print a 2-D array in a comma-delimited list
`define ARRPRN(ARRLEN,PRNSRC) for (_i_=(ARRLEN)-1;_i_>=0;_i_=_i_-1) $write("%c%h%c",(_i_==(ARRLEN)-1)?"[":"",PRNSRC[_i_],!_i_?"]":",")
// Initialize a vector with a specific width random number; extra bits are zero padded
`define GETRAND(RAND,RANDW) RAND=0; repeat ((RANDW)/32) RAND=(RAND<<32)|{$random}; RAND=(RAND<<((RANDW)%32))|({$random}>>(32-(RANDW)%32))
// factorial (n!)
`define fact(n) ( ( ((n) >= 2 ) ? 2 : 1) * \
( ((n) >= 3 ) ? 3 : 1) * \
( ((n) >= 4 ) ? 4 : 1) * \
( ((n) >= 5 ) ? 5 : 1) * \
( ((n) >= 6 ) ? 6 : 1) * \
( ((n) >= 7 ) ? 7 : 1) * \
( ((n) >= 8 ) ? 8 : 1) * \
( ((n) >= 9 ) ? 9 : 1) * \
( ((n) >= 10 ) ? 10 : 1) )
// ceiling of log2
`define log2(x) ( ( ((x) > 1 ) ? 1 : 0) + \
( ((x) > 2 ) ? 1 : 0) + \
( ((x) > 4 ) ? 1 : 0) + \
( ((x) > 8 ) ? 1 : 0) + \
( ((x) > 16 ) ? 1 : 0) + \
( ((x) > 32 ) ? 1 : 0) + \
( ((x) > 64 ) ? 1 : 0) + \
( ((x) > 128 ) ? 1 : 0) + \
( ((x) > 256 ) ? 1 : 0) + \
( ((x) > 512 ) ? 1 : 0) + \
( ((x) > 1024 ) ? 1 : 0) + \
( ((x) > 2048 ) ? 1 : 0) + \
( ((x) > 4096 ) ? 1 : 0) + \
( ((x) > 8192 ) ? 1 : 0) + \
( ((x) > 16384 ) ? 1 : 0) + \
( ((x) > 32768 ) ? 1 : 0) + \
( ((x) > 65536 ) ? 1 : 0) + \
( ((x) > 131072 ) ? 1 : 0) + \
( ((x) > 262144 ) ? 1 : 0) + \
( ((x) > 524288 ) ? 1 : 0) + \
( ((x) > 1048576) ? 1 : 0) + \
( ((x) > 2097152) ? 1 : 0) + \
( ((x) > 4194304) ? 1 : 0) )
// floor of log2
`define log2f(x) ( ( ((x) >= 2 ) ? 1 : 0) + \
( ((x) >= 4 ) ? 1 : 0) + \
( ((x) >= 8 ) ? 1 : 0) + \
( ((x) >= 16 ) ? 1 : 0) + \
( ((x) >= 32 ) ? 1 : 0) + \
( ((x) >= 64 ) ? 1 : 0) + \
( ((x) >= 128 ) ? 1 : 0) + \
( ((x) >= 256 ) ? 1 : 0) + \
( ((x) >= 512 ) ? 1 : 0) + \
( ((x) >= 1024 ) ? 1 : 0) + \
( ((x) >= 2048 ) ? 1 : 0) + \
( ((x) >= 4096 ) ? 1 : 0) + \
( ((x) >= 8192 ) ? 1 : 0) + \
( ((x) >= 16384 ) ? 1 : 0) + \
( ((x) >= 32768 ) ? 1 : 0) + \
( ((x) >= 65536 ) ? 1 : 0) + \
( ((x) >= 131072 ) ? 1 : 0) + \
( ((x) >= 262144 ) ? 1 : 0) + \
( ((x) >= 524288 ) ? 1 : 0) + \
( ((x) >= 1048576) ? 1 : 0) + \
( ((x) >= 2097152) ? 1 : 0) + \
( ((x) >= 4194304) ? 1 : 0) )
`endif //__UTILS_VH__
......@@ -83,7 +83,6 @@ entity swc_multiport_page_allocator is
g_special_res_num_pages : integer := 256;
g_resource_num : integer := 3; -- this include 1 for unknown
g_resource_num_width : integer := 2;
g_num_dbg_vector_width : integer := 10*3;
g_with_RESOURCE_MGR : boolean := false
);
port (
......@@ -137,7 +136,8 @@ entity swc_multiport_page_allocator is
set_usecnt_succeeded_o : out std_logic_vector(g_num_ports -1 downto 0);
res_full_o : out std_logic_vector(g_num_ports * g_resource_num -1 downto 0);
res_almost_full_o : out std_logic_vector(g_num_ports * g_resource_num -1 downto 0);
dbg_o : out std_logic_vector(g_num_dbg_vector_width - 1 downto 0)
free_pages_o : out std_logic_vector(g_page_addr_width downto 0);
afull_thr_i : in std_logic_vector(g_page_addr_width downto 0)
-- tap_out_o : out std_logic_vector(62 + 49 downto 0)
);
......@@ -160,8 +160,7 @@ architecture syn of swc_multiport_page_allocator is
g_special_res_num_pages : integer := 256;
g_resource_num : integer := 3; -- this include: unknown, special and x* normal , so
-- g_resource_num = 2+x
g_resource_num_width : integer := 2;
g_num_dbg_vector_width : integer );
g_resource_num_width : integer := 2);
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
......@@ -191,7 +190,8 @@ architecture syn of swc_multiport_page_allocator is
set_usecnt_succeeded_o : out std_logic;
res_full_o : out std_logic_vector(g_resource_num -1 downto 0);
res_almost_full_o : out std_logic_vector(g_resource_num -1 downto 0);
dbg_o : out std_logic_vector(g_num_dbg_vector_width - 1 downto 0);
free_pages_o : out std_logic_vector(g_page_addr_width downto 0);
afull_thr_i : in std_logic_vector(g_page_addr_width downto 0);
-----------------------
dbg_double_free_o : out std_logic;
dbg_double_force_free_o : out std_logic;
......@@ -474,8 +474,7 @@ begin -- syn
g_max_pck_size => g_max_pck_size,
g_special_res_num_pages => g_special_res_num_pages,
g_resource_num => g_resource_num,
g_resource_num_width => g_resource_num_width,
g_num_dbg_vector_width => g_num_dbg_vector_width)
g_resource_num_width => g_resource_num_width)
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
......@@ -505,7 +504,8 @@ begin -- syn
rescnt_page_num_i => pg_rescnt_page_num,
res_full_o => pg_res_full,
res_almost_full_o => pg_res_almost_full,
dbg_o => dbg_o,
free_pages_o => free_pages_o,
afull_thr_i => afull_thr_i,
-------------------------------
dbg_double_force_free_o => dbg_double_force_free,
dbg_double_free_o => dbg_double_free,
......
......@@ -100,8 +100,7 @@ entity swc_page_allocator_new is
g_special_res_num_pages : integer := 256;
g_resource_num : integer := 3; -- this include: unknown, special and x* normal , so
-- g_resource_num = 2+x
g_resource_num_width : integer := 2;
g_num_dbg_vector_width : integer
g_resource_num_width : integer := 2
);
port (
......@@ -201,8 +200,8 @@ entity swc_page_allocator_new is
res_full_o : out std_logic_vector(g_resource_num -1 downto 0);
res_almost_full_o : out std_logic_vector(g_resource_num -1 downto 0);
dbg_o : out std_logic_vector(g_num_dbg_vector_width - 1 downto 0);
free_pages_o : out std_logic_vector(g_page_addr_width downto 0);
afull_thr_i : in std_logic_vector(g_page_addr_width downto 0);
----------------------------------------------------------------------
......@@ -567,8 +566,7 @@ begin -- syn
resource_o <= (others => '0');
set_usecnt_succeeded_o <= '1';
res_full_o <= (others => std_logic(out_nomem or initializing));
dbg_o (g_page_addr_width+1-1 downto 0) <= std_logic_vector(free_pages);
dbg_o (g_num_dbg_vector_width-1 downto g_page_addr_width+1) <= (others =>'0');
free_pages_o <= std_logic_vector(free_pages);
set_usecnt_allowed_p1 <= '1';
p_gen_almost_full : process(clk_i)
begin
......@@ -576,7 +574,7 @@ begin -- syn
if rst_n_i = '0' then
res_almost_full_o <= (others => '0');
else
if(free_pages < to_unsigned(40, free_blocks'length) ) then
if(free_pages < unsigned(afull_thr_i) ) then
res_almost_full_o <= (others => '1');
else
res_almost_full_o <= (others => '0');
......@@ -629,8 +627,7 @@ begin -- syn
g_total_num_pages_width => g_page_addr_width,
g_special_res_num_pages => g_special_res_num_pages,
g_resource_num => g_resource_num,
g_resource_num_width => g_resource_num_width,
g_num_dbg_vector_width => g_num_dbg_vector_width
g_resource_num_width => g_resource_num_width
)
port map (
clk_i => clk_i,
......@@ -642,7 +639,7 @@ begin -- syn
rescnt_page_num_i => alloc_req_d1.rescnt_page_num,
res_full_o => res_full_o,
res_almost_full_o => res_almost_full,
dbg_o => dbg_o
dbg_o => open --dbg_o
);
resource_o <= rescnt_rddata_p1;
......
......@@ -136,7 +136,7 @@ entity swc_alloc_resource_manager is
g_resource_num : integer := 3; -- this include 1 for unknown
g_resource_num_width : integer := 2;
g_num_dbg_vector_width : integer
g_num_dbg_vector_width : integer := 30
);
port (
......
......@@ -73,8 +73,7 @@ entity swc_core is
g_mpm_fifo_size : integer ;
g_mpm_fetch_next_pg_in_advance : boolean ;
g_drop_outqueue_head_on_full : boolean ;
g_num_global_pause : integer ;
g_num_dbg_vector_width : integer
g_num_global_pause : integer
);
port (
clk_i : in std_logic;
......@@ -132,15 +131,8 @@ entity swc_core is
-------------------------------------------------------------------------------
pp_req_i : in std_logic_vector(g_num_ports - 1 downto 0);
pp_quanta_i : in std_logic_vector(g_num_ports*16 - 1 downto 0);
pp_classes_i : in std_logic_vector(g_num_ports*8 - 1 downto 0);
------------------------------------------------------------------------------
-- I/F misc
-------------------------------------------------------------------------------
dbg_o : out std_logic_vector(g_num_dbg_vector_width -1 downto 0);
shaper_drop_at_hp_ena_i : in std_logic
);
pp_classes_i : in std_logic_vector(g_num_ports*8 - 1 downto 0)
);
end swc_core;
architecture rtl of swc_core is
......@@ -178,8 +170,7 @@ architecture rtl of swc_core is
g_mpm_fifo_size => g_mpm_fifo_size,
g_mpm_fetch_next_pg_in_advance => g_mpm_fetch_next_pg_in_advance,
g_drop_outqueue_head_on_full => g_drop_outqueue_head_on_full,
g_num_global_pause => g_num_global_pause,
g_num_dbg_vector_width => g_num_dbg_vector_width
g_num_global_pause => g_num_global_pause
)
port map(
clk_i => clk_i,
......@@ -192,13 +183,9 @@ architecture rtl of swc_core is
src_i => src_i,
src_o => src_o,
shaper_drop_at_hp_ena_i => shaper_drop_at_hp_ena_i,
global_pause_i => global_pause_i,
perport_pause_i=> perport_pause_i,
dbg_o => dbg_o,
rtu_rsp_i => rtu_rsp_i,
rtu_ack_o => rtu_rsp_ack_o
);
......
......@@ -3,10 +3,10 @@
-- Project : WhiteRabbit switch
-------------------------------------------------------------------------------
-- File : swc_ll_read_data_validation.vhd
-- Author : Maciej Lipinski
-- Author : Maciej Lipinski, Grzegorz Daniluk
-- Company : CERN BE-Co-HT
-- Created : 2012-01-30
-- Last update: 2012-01-30
-- Last update: 2016-08-31
-- Platform : FPGA-generic
-- Standard : VHDL'87
-------------------------------------------------------------------------------
......@@ -23,7 +23,7 @@
-- can overtake the writting process.
-------------------------------------------------------------------------------
--
-- Copyright (c) 2012 CERN / BE-CO-HT
-- Copyright (c) 2012-2016 CERN / BE-CO-HT
--
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
......@@ -51,16 +51,19 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;
library work;
use work.swc_swcore_pkg.all;
use work.genram_pkg.all;
use work.gencores_pkg.all;
entity swc_ll_read_data_validation is
generic(
g_addr_width : integer ;--:= c_swc_page_addr_width;
g_data_width : integer --:= c_swc_page_addr_width
g_addr_width : integer;
g_data_width : integer;
g_wports : integer
);
port(
clk_i : in std_logic;
......@@ -80,10 +83,9 @@ entity swc_ll_read_data_validation is
read_data_ready_i : in std_logic;
-- data being written to DPRAM
write_addr_i : in std_logic_vector(g_addr_width - 1 downto 0);
write_data_i : in std_logic_vector(g_data_width - 1 downto 0);
write_data_valid_i : in std_logic;
write_data_ready_i : in std_logic;
write_addr_i : in t_lladr_array(g_wports-1 downto 0);
write_data_i : in t_lldat_array(g_wports-1 downto 0);
write_data_ready_i : in std_logic_vector(g_wports-1 downto 0);
-- data read from multiport_linked_list module
read_data_o : out std_logic_vector(g_data_width - 1 downto 0);
......@@ -94,25 +96,46 @@ entity swc_ll_read_data_validation is
architecture syn of swc_ll_read_data_validation is
signal valid_data_read : std_logic; -- data read from the DPRAM is valid (page address written)
signal nonvalid_data_read : std_logic; -- data in DPRAM is not valid (the page is being written to)
signal valid_data_write : std_logic; -- valid data is being written to the address we are hooked to
signal valid_data_write_d0 : std_logic;
signal dpram_read_valid : std_logic; -- data read from the DPRAM is valid (page address written)
signal dpram_read_invalid : std_logic; -- data in DPRAM is not valid (the page is being written to)
signal dpram_write_match : std_logic_vector(g_wports-1 downto 0); -- valid data is being written to the address we are hooked to
signal wait_valid_data_write : std_logic; -- HIGH after a non-valid data was read,
signal mask_read_req : std_logic; -- masks the request to the RR Rabiter which governs
-- the access to DPRAM
signal write_data_d0 : std_logic_vector(g_data_width - 1 downto 0);
signal write_data_muxed_d0 : std_logic_vector(g_data_width - 1 downto 0);
signal read_data_valid : std_logic;
signal write_valid_in : std_logic_vector(g_wports-1 downto 0);
signal write_data_muxed : std_logic_vector(g_data_width-1 downto 0);
signal match_if_idx : integer range 0 to g_wports-1;
signal got_valid_match : std_logic;
signal got_valid_match_d0 : std_logic;
signal read_data_out : std_logic_vector(g_data_width - 1 downto 0);
signal nonvalid_data_reg : std_logic;
begin
-----------------------------
-- READ signals --
-----------------------------
-- the data being read from the Linked List DPRAM is valid,so we just need to pass it
valid_data_read <= '1' when (read_data_ready_i = '1' and read_data_valid_i = '1') else '0';
dpram_read_valid <= '1' when (read_data_ready_i = '1' and read_data_valid_i = '1') else '0';
-- the data being read from the Linked List DPRAM is not valid (it means that data is still
-- being written under the indicated address), this is the case for this module
nonvalid_data_read <= '1' when (read_data_ready_i = '1' and read_data_valid_i = '0') else '0';
dpram_read_invalid <= '1' when (read_data_ready_i = '1' and read_data_valid_i = '0') else '0';
-- the data being written to the Linked List DPRAM is what we are wating for and it's valid.
valid_data_write <= '1' when (read_addr_i = write_addr_i and write_data_valid_i = '1' and write_data_ready_i = '1') else '0';
-----------------------------
-- WRITE signals --
-----------------------------
GEN_WR_SIGS: for I in 0 to g_wports-1 generate
-- check if written data is valid
write_valid_in(I) <= write_data_i(I)(g_data_width-1) and write_data_ready_i(I);
-- the data being written to the Linked List DPRAM is what we are wating for and it's valid.
dpram_write_match(I) <= '1' when (read_addr_i = write_addr_i(I) and write_valid_in(I) = '1') else
'0';
end generate;
got_valid_match <= or_reduce(dpram_write_match);
match_if_idx <= to_integer(unsigned(f_onehot_decode(dpram_write_match, g_wports)));
write_data_muxed <= write_data_i(match_if_idx);
process(clk_i)
begin
......@@ -121,26 +144,25 @@ begin
wait_valid_data_write <= '0';
mask_read_req <= '1';
valid_data_write_d0 <= '0';
write_data_d0 <= (others =>'0' );
got_valid_match_d0 <= '0';
write_data_muxed_d0 <= (others =>'0' );
else
write_data_d0 <= write_data_i;
valid_data_write_d0 <= valid_data_write;
write_data_muxed_d0 <= write_data_muxed;
got_valid_match_d0 <= got_valid_match;
if(nonvalid_data_read = '1' and
valid_data_write = '0' and valid_data_write_d0 = '0') then -- suppress the request, so we don't waste
mask_read_req <= '0'; -- access time to the DPRAM
elsif(valid_data_write = '1' or
valid_data_write = '1' or valid_data_write_d0 = '1') then -- at this point, the request (read_req_i) to
if(dpram_read_invalid = '1' and
got_valid_match = '0' and got_valid_match_d0 = '0') then -- suppress the request, so we don't waste
mask_read_req <= '0'; -- access time to the DPRAM
elsif(got_valid_match = '1' or got_valid_match_d0 = '1') then -- at this point, the request (read_req_i) to
mask_read_req <= '1'; -- the LL should finish, and we get read for new request
end if;
if(nonvalid_data_read = '1' and -- non-valid data was read *and*
valid_data_write = '0' and valid_data_write_d0 = '0') then -- the same time (or 1-cyc- before -- this is a write gap)
if(dpram_read_invalid = '1' and -- non-valid data was read *and*
got_valid_match = '0' and got_valid_match_d0 = '0') then -- the same time (or 1-cyc- before -- this is a write gap)
wait_valid_data_write <= '1'; -- there was no write to the address which is of interest
elsif(valid_data_write = '1') then -- so we need to wait for the proper write
elsif(got_valid_match = '1') then -- so we need to wait for the proper write
wait_valid_data_write <= '0';
end if;
......@@ -149,20 +171,25 @@ begin
end process;
read_data_o <= read_data_i when (valid_data_read = '1' ) else -- normal case, the data being read is valid
write_data_i when (valid_data_write = '1' and -- the data being written is valid *and*
(wait_valid_data_write ='1' or nonvalid_data_read = '1' )) else -- we are waiting for valid dta at that address *or*
-- we are just reading non-valid data
write_data_d0 when (valid_data_write_d0 = '1' and -- there is a 1-cycle gap between writing/reading data *and*
(wait_valid_data_write ='1' or nonvalid_data_read = '1' )) else -- we are waiting for valid dta at that address *or*
-- we are just reading non-valid data
read_data_out <= -- normal case, the data being read is valid
read_data_i when (dpram_read_valid = '1' ) else
-- the data being written is valid *and*
-- we are waiting for valid dta at that address *or* we are just reading non-valid data
write_data_muxed when (got_valid_match = '1' and
(wait_valid_data_write ='1' or dpram_read_invalid = '1' )) else
-- there is a 1-cycle gap between writing/reading data *and*
-- we are waiting for valid dta at that address *or* we are just reading non-valid data
write_data_muxed_d0 when (got_valid_match_d0 = '1' and
(wait_valid_data_write ='1' or dpram_read_invalid = '1' )) else
read_data_i;
read_data_valid_o <= (valid_data_read or -- normal case
(valid_data_write and (wait_valid_data_write or nonvalid_data_read)) or
(valid_data_write_d0 and (wait_valid_data_write or nonvalid_data_read)) ) and -- reading data from LL input
read_data_o <= read_data_out;
read_data_valid <= (dpram_read_valid or -- normal case
(got_valid_match and (wait_valid_data_write or dpram_read_invalid)) or
(got_valid_match_d0 and (wait_valid_data_write or dpram_read_invalid)) ) and -- reading data from LL input
read_req_i; -- no request, no answer :)
read_req_o <= mask_read_req and read_req_i;
read_data_valid_o <= read_data_valid;
read_req_o <= mask_read_req and read_req_i;
end syn;
......@@ -3,17 +3,17 @@
-- Project : WhiteRabbit switch
-------------------------------------------------------------------------------
-- File : swc_multiport_linked_list.vhd
-- Author : Maciej Lipinski
-- Company : CERN BE-Co-HT
-- Author : Maciej Lipinski, Grzegorz Daniluk
-- Company : CERN BE-CO-HT
-- Created : 2010-10-26
-- Last update: 2012-03-18
-- Last update: 2016-08-26
-- Platform : FPGA-generic
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description:
-------------------------------------------------------------------------------
--
-- Copyright (c) 2010 - 2012 CERN / BE-CO-HT
-- Copyright (c) 2010 - 2016 CERN / BE-CO-HT
--
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
......@@ -37,12 +37,15 @@
-- 2010-10-26 1.0 mlipinsk Created
-- 2012-02-02 2.0 mlipinsk generic-azed
-- 2012-02-16 3.0 mlipinsk speeded up & adapted to cut-through & adapted to new MPM
-- 2016-08-26 4.0 greg.d rewritten to use multiport RAM with multiple IB write ports
-- also cleaned up IB write arbiter, now uses simple FSM
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;
use ieee.math_real.CEIL;
use ieee.math_real.log2;
......@@ -80,29 +83,12 @@ entity swc_multiport_linked_list is
rst_n_i : in std_logic;
clk_i : in std_logic;
-- write request
write_i : in std_logic_vector(g_num_ports - 1 downto 0);
-- indicates that the data was written
write_done_o : out std_logic_vector(g_num_ports - 1 downto 0);
-- write address, needs to be valid till write_done_o=HIGH
write_addr_i : in std_logic_vector(g_num_ports * g_addr_width - 1 downto 0);
-- next page [ctrls,address or (size + sel)]
write_data_i : in std_logic_vector(g_num_ports * g_data_width - 1 downto 0);
-- if we already know the address (of the next page to be used), we provide it here, it
-- is invalidated.
write_next_addr_i : in std_logic_vector(g_num_ports * g_addr_width - 1 downto 0);
-- indicates that the next_addr is provided
write_next_addr_valid_i: in std_logic_vector(g_num_ports - 1 downto 0);
ib_i : in t_ib2ll_array(g_num_ports-1 downto 0);
ib_o : out t_ll2ib_array(g_num_ports-1 downto 0);
------------ reading from the Linked List by freeing module ----------
-- request reading
free_pck_rd_req_i : in std_logic_vector(g_num_ports - 1 downto 0);
-- requested address, needs to be valid till write_done_o=HIGH
free_pck_addr_i : in std_logic_vector(g_num_ports * g_addr_width - 1 downto 0);
-- data available on data_o
free_pck_read_done_o : out std_logic_vector(g_num_ports - 1 downto 0);
-- requested data
free_pck_data_o : out std_logic_vector(g_num_ports * g_data_width - 1 downto 0);
free_pck_i : in t_fp2ll_array(g_num_ports-1 downto 0);
free_pck_o : out t_ll2fp_array(g_num_ports-1 downto 0);
-------- reading by Multiport Memory (direct access) -------
-- requested address, needs to be valid till write_done_o=HIGH
......@@ -114,39 +100,93 @@ entity swc_multiport_linked_list is
end swc_multiport_linked_list;
architecture syn of swc_multiport_linked_list is
---------------------- writing process --------------------------------
-- arbitrating writing process
signal write_request_vec : std_logic_vector(g_num_ports-1 downto 0);
signal write_grant_vec : std_logic_vector(g_num_ports-1 downto 0);
signal write_grant_vec_d0 : std_logic_vector(g_num_ports-1 downto 0);
signal write_grant_vec_d1 : std_logic_vector(g_num_ports-1 downto 0);
signal write_grant_index : integer range 0 to g_num_ports-1;
signal write_grant_index_d0 : integer range 0 to g_num_ports-1;
signal write_request_noempty : std_logic;
signal write_done : std_logic_vector(g_num_ports-1 downto 0);
signal in_sel_write : integer range 0 to g_num_ports-1;
-- signals used by writing process
signal ll_write_ena : std_logic;
signal ll_write_next_ena : std_logic;
signal ll_write_addr : std_logic_vector(g_addr_width - 1 downto 0);
signal ll_write_next_addr : std_logic_vector(g_addr_width - 1 downto 0);
signal ll_write_data : std_logic_vector(g_data_width - 1 downto 0);
signal ll_write_data_valid : std_logic;
signal ll_write_end_of_list : std_logic;
signal tmp_write_end_of_list : std_logic_vector(g_num_ports-1 downto 0);
-- signal connected directly to DPRAM (driven/multiplexd by the above
signal ll_wr_addr : std_logic_vector(g_addr_width - 1 downto 0);
signal ll_wr_data : std_logic_vector(g_data_width - 1 downto 0);
signal ll_wr_ena : std_logic;
signal ll_wr_addr_reg : std_logic_vector(g_addr_width - 1 downto 0);
signal ll_wr_data_reg : std_logic_vector(g_data_width - 1 downto 0);
signal ll_wr_ena_reg : std_logic;
constant c_MPRAM_WPORTS : integer := 3;
constant c_MPRAM_RPORTS : integer := 2;
component mpram_lvt
generic (
MEMD : integer;
DATW : integer;
nRPF : integer;
nWPF : integer;
nRPS : integer;
nWPS : integer;
LVTA : string;
WAWB : integer;
RAWB : integer;
RDWB : integer);
port (
clk : in std_logic;
rdWr : in std_logic;
WEnb : in std_logic_vector(nWPF+nWPS-1 downto 0);
WAddr : in std_logic_vector(f_log2_size(MEMD)*(nWPF+nWPS)-1 downto 0);
WData : in std_logic_vector(DATW*(nWPF+nWPS)-1 downto 0);
RAddr : in std_logic_vector(f_log2_size(MEMD)*(nRPF+nRPS)-1 downto 0);
RData : out std_logic_vector(DATW*(nRPF+nRPS)-1 downto 0));
end component;
function ll_split_writes(write_i:std_logic_vector; g_num_ports:integer; idx_h:integer; idx_l:integer) return std_logic_vector is
variable write_split : std_logic_vector(g_num_ports-1 downto 0);
variable nidx : integer range 0 to g_num_ports;
begin
if idx_h > g_num_ports-1 then
nidx := g_num_ports-1;
else
nidx := idx_h;
end if;
if idx_l > g_num_ports-1 then
write_split := (others=>'0');
else
write_split(nidx downto idx_l) := write_i(nidx downto idx_l);
write_split(idx_l-1 downto 0) := (others=>'0');
write_split(g_num_ports-1 downto nidx+1) := (others=>'0');
end if;
return write_split;
end function;
--------------------------------------
-- packing interfaces into records --
--------------------------------------
type t_llports_array is array (natural range <>) of std_logic_vector(g_num_ports-1 downto 0);
-- IB write interface
signal write_done_ored : t_llports_array(c_MPRAM_WPORTS-1 downto 0);
--------------------------------------
-- MPRAM signals --
--------------------------------------
-- packing i/f into records
signal mpram_wadr : std_logic_vector(c_MPRAM_WPORTS*g_addr_width-1 downto 0);
signal mpram_wdat : std_logic_vector(c_MPRAM_WPORTS*g_data_width-1 downto 0);
signal mpram_radr : std_logic_vector(c_MPRAM_RPORTS*g_addr_width-1 downto 0);
signal mpram_rdat : std_logic_vector(c_MPRAM_RPORTS*g_data_width-1 downto 0);
signal x_mpram_wadr, x_mpram_wadr_d0 : t_lladr_array(c_MPRAM_WPORTS-1 downto 0);
signal x_mpram_wdat, x_mpram_wdat_d0 : t_lldat_array(c_MPRAM_WPORTS-1 downto 0);
signal x_mpram_wdone: t_llports_array(c_MPRAM_WPORTS-1 downto 0);
signal x_mpram_radr : t_lladr_array(c_MPRAM_RPORTS-1 downto 0);
signal x_mpram_rdat : t_lldat_array(c_MPRAM_RPORTS-1 downto 0);
signal mpram_write : std_logic_vector(c_MPRAM_WPORTS-1 downto 0);
--------------------------------------
-- writing process --
--------------------------------------
type t_mll_fsm is (WRITE, WRITE_NEXT);
type t_mll_fsm_array is array (natural range <>) of t_mll_fsm;
type t_int_array is array (natural range <>) of integer range 0 to g_num_ports-1;
signal mll_state : t_mll_fsm_array(c_MPRAM_WPORTS-1 downto 0);
signal write_i_vec : std_logic_vector(g_num_ports-1 downto 0);
signal write_next_vec : std_logic_vector(g_num_ports-1 downto 0);
signal write_req : t_llports_array(c_MPRAM_WPORTS-1 downto 0);
signal write_i_split : t_llports_array(c_MPRAM_WPORTS-1 downto 0);
signal write_grant : t_llports_array(c_MPRAM_WPORTS-1 downto 0);
signal write_grant_d0 : t_llports_array(c_MPRAM_WPORTS-1 downto 0);
signal write_idx : t_int_array(c_MPRAM_WPORTS-1 downto 0);
signal write_done : std_logic_vector(c_MPRAM_WPORTS-1 downto 0);
signal wadr_sel : std_logic_vector(c_MPRAM_WPORTS-1 downto 0);
---------------------- reading process (free pck module) --------------------------------
-- arbitrating access
signal free_pck_request_vec : std_logic_vector(g_num_ports-1 downto 0);
......@@ -158,202 +198,187 @@ architecture syn of swc_multiport_linked_list is
signal free_pck_grant_index_d0 : integer range 0 to g_num_ports-1;
signal free_pck_grant_valid : std_logic;
signal free_pck_grant_valid_d0 : std_logic;
signal free_pck_read : std_logic_vector(g_num_ports -1 downto 0);
signal free_pck_read_done : std_logic_vector(g_num_ports -1 downto 0);
-- interface to DPRAM
signal ll_free_pck_ena : std_logic;
signal ll_free_pck_addr : std_logic_vector(g_addr_width - 1 downto 0);
signal ll_free_pck_data : std_logic_vector(g_data_width - 1 downto 0);
-- output
type t_ll_data_array is array (g_num_ports-1 downto 0) of std_logic_vector(g_data_width - 1 downto 0);
signal free_pck_data : t_ll_data_array;
signal free_pck_data_out : t_ll_data_array;
-- helper
signal zeros : std_logic_vector(g_num_ports-1 downto 0);
----------------- translate one hot to binary --------------------------
function f_one_hot_to_binary (
One_Hot : std_logic_vector
) return integer is
variable Bin_Vec_Var : integer range 0 to One_Hot'length -1;
begin
Bin_Vec_Var := 0;
for I in 0 to (One_Hot'length - 1) loop
if One_Hot(I) = '1' then
Bin_Vec_Var := I;
end if;
end loop;
return Bin_Vec_Var;
end function;
-----------------------------------------------------------------------
begin -- syn
signal free_pck_data : t_lldat_array(g_num_ports-1 downto 0);
signal free_pck_data_out : t_lldat_array(g_num_ports-1 downto 0);
zeros <= (others => '0');
begin
PAGE_INDEX_LINKED_LIST_MPM: swc_rd_wr_ram
SWITCHED_MPRAM: mpram_lvt
generic map (
g_data_width => g_data_width,-- one bit for validating the data
g_size => g_page_num)
MEMD => g_page_num,
DATW => g_data_width,
nRPF => c_MPRAM_RPORTS,
nWPF => c_MPRAM_WPORTS,
nRPS => 0,
nWPS => 0,
LVTA => "LVTREG",
WAWB => 0,
RAWB => 0,
RDWB => 1)
port map (
clk_i => clk_i,
we_i => ll_wr_ena_reg,
wa_i => ll_wr_addr_reg,
wd_i => ll_wr_data_reg,
ra_i => mpm_rpath_addr_i,
rd_o => mpm_rpath_data_o);
---- this memory is read by the output of the MPM (called read pump)
--PAGE_INDEX_LINKED_LIST_MPM : generic_dpram
-- generic map (
-- g_data_width => g_data_width,-- one bit for validating the data
-- g_size => g_page_num,
-- g_dual_clock=> false
-- )
-- port map (
-- -- Port A -- writing
-- clka_i => clk_i,
-- bwea_i => (others => '1'),
-- wea_i => ll_wr_ena_reg,
-- aa_i => ll_wr_addr_reg,
-- da_i => ll_wr_data_reg,
-- qa_o => open,
-- -- Port B -- reading
-- clkb_i => clk_i,
-- bweb_i => (others => '1'),
-- web_i => '0',
-- ab_i => mpm_rpath_addr_i,
-- db_i => (others => '0'),
-- qb_o => mpm_rpath_data_o
-- );
PAGE_INDEX_LINKED_LIST_FREE_PCK: swc_rd_wr_ram
generic map (
g_data_width => g_data_width,
g_size => g_page_num)
port map (
clk_i => clk_i,
we_i => ll_wr_ena_reg,
wa_i => ll_wr_addr_reg,
wd_i => ll_wr_data_reg,
ra_i => ll_free_pck_addr,
rd_o => ll_free_pck_data);
---- this memory is read by the process that force-frees pck on error
--PAGE_INDEX_LINKED_LIST_FREE_PCK : generic_dpram
-- generic map (
-- g_data_width => g_data_width,-- one bit for validating the data
-- g_size => g_page_num
-- )
-- port map (
-- -- Port A -- writing
-- clka_i => clk_i,
-- bwea_i => (others => '1'),
-- wea_i => ll_wr_ena_reg,
-- aa_i => ll_wr_addr_reg,
-- da_i => ll_wr_data_reg,
-- qa_o => open,
-- -- Port B -- reading
-- clkb_i => clk_i,
-- bweb_i => (others => '1'),
-- web_i => '0',
-- ab_i => ll_free_pck_addr,
-- db_i => (others => '0'),
-- qb_o => ll_free_pck_data
-- );
gen_write_request_vec : for i in 0 to g_num_ports - 1 generate
tmp_write_end_of_list(i) <= write_data_i((i + 1) * g_data_width - 2);
--write_request_vec(i) <= write_i(i) and (not ((tmp_write_end_of_list(i) and write_grant_vec_d0(i)) or write_grant_vec_d1(i)));
write_request_vec(i) <= write_i(i) and (not ((not write_next_addr_valid_i(i) and write_grant_vec_d0(i)) or write_grant_vec_d1(i)));
clk => clk_i,
rdWr => '0',
WEnb => mpram_write,
WAddr => mpram_wadr,
WData => mpram_wdat,
RAddr => mpram_radr,
RData => mpram_rdat);
-- pack MPRAM interfaces into types
GEN_MPRAM_WIF: for I in 0 to c_MPRAM_WPORTS-1 generate
mpram_wadr((I+1)*g_addr_width-1 downto I*g_addr_width) <= x_mpram_wadr_d0(I);
mpram_wdat((I+1)*g_data_width-1 downto I*g_data_width) <= x_mpram_wdat_d0(I);
end generate;
gen_free_pck_request_vec : for i in 0 to g_num_ports - 1 generate
free_pck_request_vec(i) <= free_pck_read(i) and (not (free_pck_grant_vec_d0(i) or free_pck_grant_vec_d1(i)));
GEN_MPRAM_RIF: for I in 0 to c_MPRAM_RPORTS-1 generate
mpram_radr((I+1)*g_addr_width-1 downto I*g_addr_width) <= x_mpram_radr(I);
x_mpram_rdat(I) <= mpram_rdat((I+1)*g_data_width-1 downto I*g_data_width);
end generate;
-- writing
f_rr_arbitrate(req => write_request_vec,
pre_grant=> write_grant_vec_d0,
grant => write_grant_vec);
-- MPM read interface
x_mpram_radr(0) <= mpm_rpath_addr_i;
mpm_rpath_data_o <= x_mpram_rdat(0);
-- Free PCK read interface
x_mpram_radr(1) <= free_pck_i(free_pck_grant_index).adr;
ll_free_pck_data <= x_mpram_rdat(1);
--------------------------------------
-- Serving write requests from IBs --
--------------------------------------
GEN_WRITE_VEC: for I in 0 to g_num_ports-1 generate
write_i_vec(I) <= ib_i(I).write;
ib_o(I).done <= write_done_ored(c_MPRAM_WPORTS-1)(I);
end generate;
-- we split IBs into write ports
-- IB port ranges for each write port are hardcoded to have similar
-- performance (IBs-per-write port) for 8 and 18 port version.
write_i_split(0) <= ll_split_writes(write_i_vec, g_num_ports, 5, 0);
write_i_split(1) <= ll_split_writes(write_i_vec, g_num_ports, 11, 6);
write_i_split(2) <= ll_split_writes(write_i_vec, g_num_ports, g_num_ports-1, 12);
-- combine together write_done signals from multiple MPRAM write ports
write_done_ored(0) <= x_mpram_wdone(0);
GEN_WDONE: for I in 1 to c_MPRAM_WPORTS-1 generate
write_done_ored(I) <= write_done_ored(I-1) or x_mpram_wdone(I);
end generate;
write_grant_index <= f_one_hot_to_binary(write_grant_vec_d0) ;
write_request_noempty <= '1' when (write_request_vec /= zeros) else '0';
GEN_WRFSM: for I in 0 to c_MPRAM_WPORTS-1 generate
write_idx(I) <= to_integer(unsigned(f_onehot_decode(write_grant(I), g_num_ports)));
-- select address to be written to MPRAM. For requests with
-- write_next_addr_valid = 1 we prefer to write first the "next address" to
-- invalidate this page as soon as possible. Otherwise the output or freeing
-- module could fetch incorrect data for that page.
x_mpram_wadr(I) <= ib_i(write_idx(I)).adr_next when(ib_i(write_idx(I)).next_valid = '1' and wadr_sel(I)='0') else
ib_i(write_idx(I)).adr;
-- the same way we select data to be written with the above address. It's
-- either data passed with the request from the IB or zeros to invalidate
-- next page (next addr from the request).
x_mpram_wdat(I) <= (others=>'0') when (ib_i(write_idx(I)).next_valid = '1' and wadr_sel(I)='0') else
ib_i(write_idx(I)).data;
x_mpram_wdone(I) <= write_grant_d0(I) when(write_done(I) = '1') else
(others=>'0');
f_rr_arbitrate(write_req(I), write_grant_d0(I), write_grant(I));
process(clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i='0' then
mll_state(I) <= WRITE;
wadr_sel(I) <= '0';
write_grant_d0(I) <= (others=>'0');
write_req(I) <= (others=>'0');
write_done(I) <= '0';
x_mpram_wadr_d0(I)<= (others=>'0');
x_mpram_wdat_d0(I)<= (others=>'0');
else
-- address and data delayed by 1 cycle to align with mpram_write from
-- the state machine.
x_mpram_wadr_d0(I)<= x_mpram_wadr(I);
x_mpram_wdat_d0(I)<= x_mpram_wdat(I);
case(mll_state(I)) is
when WRITE =>
if (or_reduce(write_grant(I)) = '1' and ib_i(write_idx(I)).next_valid = '1') then
mll_state(I) <= WRITE_NEXT;
wadr_sel(I) <= '1'; -- switch the address to be written
mpram_write(I) <= '1';
write_done(I) <= '0';
elsif (or_reduce(write_grant(I)) = '1') then
wadr_sel(I) <= '0';
mpram_write(I) <= '1';
write_done(I) <= '1';
write_grant_d0(I) <= write_grant(I);
write_req(I) <= write_i_split(I) and (not write_grant(I)) and (not write_grant_d0(I));
else
wadr_sel(I) <= '0';
mpram_write(I) <= '0';
write_done(I) <= '0';
write_grant_d0(I) <= write_grant(I);
write_req(I) <= write_i_split(I) and (not write_grant(I)) and (not write_grant_d0(I));
end if;
when WRITE_NEXT =>
mpram_write(I) <= '1';
wadr_sel(I) <= '0';
write_done(I) <= '1';
write_grant_d0(I) <= write_grant(I);
write_req(I) <= write_i_split(I) and (not write_grant(I)) and (not write_grant_d0(I));
mll_state(I) <= WRITE;
when others =>
mll_state(I) <= WRITE;
end case;
end if;
end if;
end process;
end generate;
---------------------------------------
-- Scheduling free requests from the --
-- freeing module. --
---------------------------------------
gen_free_pck_request_vec : for i in 0 to g_num_ports - 1 generate
free_pck_request_vec(i) <= free_pck_read(i) and (not (free_pck_grant_vec_d0(i) or free_pck_grant_vec_d1(i)));
end generate;
-- reading
f_rr_arbitrate(req => free_pck_request_vec,
pre_grant=> free_pck_grant_vec_d0,
grant => free_pck_grant_vec);
free_pck_grant_index <= f_one_hot_to_binary(free_pck_grant_vec_d0) ;
free_pck_request_noempty <= '1' when (free_pck_request_vec /= zeros) else '0';
-- ======= writing =======
-- mux input data for the port to which access is granted
ll_write_data <= write_data_i((write_grant_index + 1) * g_data_width - 1 downto write_grant_index * g_data_width);
ll_write_addr <= write_addr_i((write_grant_index + 1) * g_addr_width - 1 downto write_grant_index * g_addr_width);
ll_write_data_valid <= write_data_i((write_grant_index + 1) * g_data_width - 1); -- MSB bit
ll_write_end_of_list<= write_data_i((write_grant_index + 1) * g_data_width - 2); -- MSB -1 bit
--ll_write_next_addr <= ll_write_data(g_addr_width - 1 downto 0);
ll_write_next_addr <= write_next_addr_i((write_grant_index + 1) * g_addr_width - 1 downto write_grant_index * g_addr_width);
-- create data and address to be written to memory (both DPRAMs)
-- ll_wr_data <= (others => '0') when (ll_write_next_ena = '1' ) else ll_write_data;
--reversing the order (16/03/2012) of writing current/cleaning next page
ll_wr_data <= ll_write_data when (ll_write_next_ena = '1' and write_next_addr_valid_i(write_grant_index) = '1') else
(others => '0') when (ll_write_ena = '1' and write_next_addr_valid_i(write_grant_index) = '1') else
ll_write_data;-- when (ll_write_ena = '1' and write_next_addr_valid_i(write_grant_index) = '0') else
--(others => '0'); -- this should not happen
free_pck_grant_index <= to_integer(unsigned(f_onehot_decode(free_pck_grant_vec_d0, g_num_ports)));
free_pck_request_noempty <= '1' when (or_reduce(free_pck_request_vec) /= '0') else '0';
-- ll_wr_addr <= ll_write_next_addr when (ll_write_next_ena = '1' ) else ll_write_addr;
--reversing the order (16/03/2012) of writing current/cleaning next page
ll_wr_addr <= ll_write_addr when (ll_write_next_ena = '1' and write_next_addr_valid_i(write_grant_index) = '1') else
ll_write_next_addr when (ll_write_ena = '1' and write_next_addr_valid_i(write_grant_index) = '1') else
ll_write_addr;-- when (ll_write_ena = '1' and write_next_addr_valid_i(write_grant_index) = '0') else
--(others => '1'); -- this should not happen
ll_write_ena <= (write_grant_vec (write_grant_index) and write_grant_vec_d0(write_grant_index) and write_next_addr_valid_i(write_grant_index)) or
(write_grant_vec_d0(write_grant_index) and not write_next_addr_valid_i(write_grant_index));
ll_write_next_ena <= write_grant_vec_d0(write_grant_index) and write_grant_vec_d1(write_grant_index);
-- ======= reading (read pump) =======
-- address
ll_free_pck_addr <= free_pck_addr_i((free_pck_grant_index + 1) * g_addr_width - 1 downto free_pck_grant_index * g_addr_width);
process(clk_i, rst_n_i)
begin
if rising_edge(clk_i) then
if(rst_n_i = '0') then
free_pck_grant_vec_d0 <= (others => '0' );
free_pck_grant_vec_d1 <= (others => '0' );
free_pck_grant_valid <= '0';
free_pck_grant_valid_d0 <= '0';
free_pck_grant_index_d0 <= 0;
write_grant_vec_d0 <= (others => '0' );
write_grant_vec_d1 <= (others => '0' );
write_grant_index_d0 <= 0;
else
free_pck_grant_vec_d0 <= free_pck_grant_vec;
free_pck_grant_vec_d1 <= free_pck_grant_vec_d0;
free_pck_grant_index_d0 <= free_pck_grant_index;
free_pck_grant_valid <= free_pck_request_noempty; -- we always get grant in 1-cycle
free_pck_grant_valid_d0 <= free_pck_grant_valid;
write_grant_vec_d0 <= write_grant_vec;
write_grant_vec_d1 <= write_grant_vec_d0;
write_grant_index_d0 <= write_grant_index;
end if;
end if;
end process;
......@@ -365,64 +390,34 @@ begin -- syn
read_data_valid: swc_ll_read_data_validation
generic map(
g_addr_width => g_addr_width,
g_data_width => g_data_width
g_data_width => g_data_width,
g_wports => c_MPRAM_WPORTS
)
port map(
clk_i => clk_i,
rst_n_i => rst_n_i,
read_req_i => free_pck_rd_req_i(i),
read_req_i => free_pck_i(i).rd_req,
read_req_o => free_pck_read(i),
read_addr_i => free_pck_addr_i((i+1)*g_addr_width - 1 downto i*g_addr_width ),
read_data_i => free_pck_data(i),--(g_data_width - 2 downto 0),
read_addr_i => free_pck_i(i).adr,
read_data_i => free_pck_data(i),
read_data_valid_i => free_pck_data(i)(g_data_width - 1),
read_data_ready_i => free_pck_grant_vec_d1(i),
write_addr_i => ll_wr_addr,
write_data_i => ll_wr_data,--(g_data_width - 2 downto 0),
write_data_valid_i => ll_wr_data(g_data_width - 1),
write_data_ready_i => ll_write_ena,
read_data_o => free_pck_data_o((i+1)*g_data_width - 1 downto i*g_data_width), --free_pck_data_out(i),--(g_data_width - 2 downto 0),
read_data_valid_o => free_pck_read_done_o(i) --free_pck_read_done(i)
-- eavesdropping
write_addr_i => x_mpram_wadr_d0,
write_data_i => x_mpram_wdat_d0,
write_data_ready_i => mpram_write,
-- end of eavesdropping
read_data_o => free_pck_o(i).data,
read_data_valid_o => free_pck_o(i).rd_done
);
-- free_pck_data_o ((i+1)*g_data_width - 1 downto i*g_data_width) <= free_pck_data_out(i)(g_data_width - 1 downto 0);
-- free_pck_data_o ((i+1)*g_data_width - 1) <= free_pck_read_done(i);
-- free_pck_read_done_o(i) <= free_pck_read_done(i);
end generate;
ll_free_pck_ena <= free_pck_grant_valid_d0;
ll_wr_ena <= ll_write_ena or ll_write_next_ena;
wr_ram: process(clk_i, rst_n_i)
begin
if rising_edge(clk_i) then
if(rst_n_i = '0') then
ll_wr_addr_reg <= (others =>'0');
ll_wr_data_reg <= (others =>'0');
ll_wr_ena_reg <= '0';
else
ll_wr_addr_reg <= ll_wr_addr;
ll_wr_data_reg <= ll_wr_data;
ll_wr_ena_reg <= ll_wr_ena;
end if;
end if;
end process wr_ram;
-- wr_done: for i in 0 to g_num_ports -1 generate
-- write_done_o(i) <= '1' when ((write_grant_vec_d0(i) = '1' and tmp_write_end_of_list(i) = '1') or -- end-of-list, one one write, so write_done faster
-- (write_grant_vec_d0(i) = '1' and write_grant_vec_d1(i) = '1' and tmp_write_end_of_list(i) = '0')) else -- normal write, we write two words, it takes longer
-- '0';
-- end generate;
wr_done: for i in 0 to g_num_ports -1 generate
write_done_o(i) <= '1' when ((write_grant_vec_d0(i) = '1' and write_next_addr_valid_i(i) = '0') or -- end-of-list, one one write, so write_done faster
(write_grant_vec_d0(i) = '1' and write_grant_vec_d1(i) = '1' and write_next_addr_valid_i(i) = '1')) else -- normal write, we write two words, it takes longer
'0';
end generate;
end syn;
......@@ -69,11 +69,8 @@ entity swc_multiport_pck_pg_free_module is
ob_free_done_o : out std_logic_vector(g_num_ports-1 downto 0);
ob_free_pgaddr_i : in std_logic_vector(g_num_ports * g_page_addr_width - 1 downto 0);
ll_read_addr_o : out std_logic_vector(g_num_ports * g_page_addr_width -1 downto 0);
ll_read_data_i : in std_logic_vector(g_num_ports * g_data_width - 1 downto 0);
--ll_read_data_i : in std_logic_vector(g_page_addr_width - 1 downto 0);
ll_read_req_o : out std_logic_vector(g_num_ports-1 downto 0);
ll_read_valid_data_i : in std_logic_vector(g_num_ports-1 downto 0);
ll_i : in t_ll2fp_array(g_num_ports-1 downto 0);
ll_o : out t_fp2ll_array(g_num_ports-1 downto 0);
mmu_resource_i : in std_logic_vector(g_num_ports * g_resource_num_width -1 downto 0);
......@@ -123,10 +120,10 @@ begin -- syn
ob_free_done_o => ob_free_done_o(i),
ob_free_pgaddr_i => ob_free_pgaddr_i((i+1)*g_page_addr_width - 1 downto i * g_page_addr_width),
ll_read_addr_o => ll_read_addr_o((i+1)*g_page_addr_width - 1 downto i * g_page_addr_width),
ll_read_data_i => ll_read_data_i((i+1)*g_data_width - 1 downto i * g_data_width),
ll_read_req_o => ll_read_req_o(i),
ll_read_valid_data_i => ll_read_valid_data_i(i),
ll_read_addr_o => ll_o(i).adr,
ll_read_data_i => ll_i(i).data,
ll_read_req_o => ll_o(i).rd_req,
ll_read_valid_data_i => ll_i(i).rd_done,
mmu_resource_i => mmu_resource_i((i+1)*g_resource_num_width -1 downto i *g_resource_num_width),
......
......@@ -49,10 +49,16 @@ library work;
use work.wr_fabric_pkg.all;
use work.wrsw_shared_types_pkg.all;
use work.genram_pkg.all;
use work.swc_wbgen2_pkg.all;
package swc_swcore_pkg is
-- Constants that configure the SwCore
constant c_ll_addr_width : integer := 10; -- calculated for mem size 64kB and page size 64 words (128B)
constant c_ll_data_width : integer := 15; -- calculated for addr_width=10; oobsize=2, +3
----------------------------------------
type t_swcore_gen_parameters is record
num_ports: integer;
mem_pages: integer;
......@@ -64,6 +70,55 @@ package swc_swcore_pkg is
type t_classes_array is array(integer range <>) of std_logic_vector(7 downto 0);
type t_ports_masks is array(integer range <>) of std_logic_vector(c_RTU_MAX_PORTS+1-1 downto 0);
type t_lladr_array is array(integer range <>) of std_logic_vector(c_ll_addr_width-1 downto 0);
type t_lldat_array is array(integer range <>) of std_logic_vector(c_ll_data_width-1 downto 0);
-- free_pck to Linked List interface
--------------------------------------
-- Free_pck to Linked List i/f --
--------------------------------------
type t_fp2ll is record
-- request reading
rd_req : std_logic;
-- requested address, needs to be valid till write_done_o=HIGH
adr : std_logic_vector(c_ll_addr_width-1 downto 0);
end record;
type t_fp2ll_array is array (natural range <>) of t_fp2ll;
type t_ll2fp is record
-- requested data
data : std_logic_vector(c_ll_data_width-1 downto 0);
-- data available on data_o
rd_done : std_logic;
end record;
type t_ll2fp_array is array (natural range <>) of t_ll2fp;
--------------------------------------
-- IB to Linked List i/f --
--------------------------------------
type t_ib2ll is record
-- write request
write : std_logic;
-- write address, needs to be valid till write_done_o=HIGH
adr : std_logic_vector(c_ll_addr_width-1 downto 0);
-- next page [ctrls,address or (size + sel)]
data : std_logic_vector(c_ll_data_width-1 downto 0);
-- if we already know the address (of the next page to be used), we provide it here, it
-- is invalidated.
adr_next : std_logic_vector(c_ll_addr_width-1 downto 0);
-- indicates that the next_addr is provided
next_valid : std_logic;
end record;
type t_ib2ll_array is array (natural range <>) of t_ib2ll;
type t_ll2ib is record
-- indicates that the data was written
done : std_logic;
end record;
type t_ll2ib_array is array (natural range <>) of t_ll2ib;
component swc_prio_encoder
generic (
g_num_inputs : integer range 2 to 80;
......@@ -102,8 +157,7 @@ package swc_swcore_pkg is
g_max_pck_size : integer := 759;
g_special_res_num_pages : integer := 256;
g_resource_num : integer := 3;
g_resource_num_width : integer := 2;
g_num_dbg_vector_width : integer
g_resource_num_width : integer := 2
);
port (
clk_i : in std_logic;
......@@ -126,8 +180,7 @@ package swc_swcore_pkg is
rescnt_page_num_i : in std_logic_vector(g_page_addr_width -1 downto 0);
set_usecnt_succeeded_o : out std_logic;
res_full_o : out std_logic_vector(g_resource_num -1 downto 0);
res_almost_full_o : out std_logic_vector(g_resource_num -1 downto 0);
dbg_o : out std_logic_vector(g_num_dbg_vector_width - 1 downto 0)
res_almost_full_o : out std_logic_vector(g_resource_num -1 downto 0)
);
end component;
......@@ -180,17 +233,11 @@ package swc_swcore_pkg is
rst_n_i : in std_logic;
clk_i : in std_logic;
write_i : in std_logic_vector(g_num_ports - 1 downto 0);
write_done_o : out std_logic_vector(g_num_ports - 1 downto 0);
write_addr_i : in std_logic_vector(g_num_ports * g_addr_width - 1 downto 0);
write_data_i : in std_logic_vector(g_num_ports * g_data_width - 1 downto 0);
write_next_addr_i : in std_logic_vector(g_num_ports * g_addr_width - 1 downto 0);
write_next_addr_valid_i: in std_logic_vector(g_num_ports - 1 downto 0);
free_pck_rd_req_i : in std_logic_vector(g_num_ports - 1 downto 0);
free_pck_addr_i : in std_logic_vector(g_num_ports * g_addr_width - 1 downto 0);
free_pck_read_done_o : out std_logic_vector(g_num_ports - 1 downto 0);
free_pck_data_o : out std_logic_vector(g_num_ports * g_data_width - 1 downto 0);
ib_i : in t_ib2ll_array(g_num_ports-1 downto 0);
ib_o : out t_ll2ib_array(g_num_ports-1 downto 0);
free_pck_i : in t_fp2ll_array(g_num_ports-1 downto 0);
free_pck_o : out t_ll2fp_array(g_num_ports-1 downto 0);
mpm_rpath_addr_i : in std_logic_vector(g_addr_width - 1 downto 0);
mpm_rpath_data_o : out std_logic_vector(g_data_width - 1 downto 0)
......@@ -298,7 +345,6 @@ package swc_swcore_pkg is
g_special_res_num_pages : integer ;
g_resource_num : integer ; -- this include 1 for unknown
g_resource_num_width : integer ;
g_num_dbg_vector_width : integer ;
g_with_RESOURCE_MGR : boolean := false
);
port (
......@@ -331,7 +377,8 @@ package swc_swcore_pkg is
set_usecnt_succeeded_o : out std_logic_vector(g_num_ports -1 downto 0);
res_full_o : out std_logic_vector(g_num_ports * g_resource_num -1 downto 0);
res_almost_full_o : out std_logic_vector(g_num_ports * g_resource_num -1 downto 0);
dbg_o : out std_logic_vector(g_num_dbg_vector_width - 1 downto 0)
free_pages_o : out std_logic_vector(g_page_addr_width downto 0);
afull_thr_i : in std_logic_vector(g_page_addr_width downto 0)
);
end component;
......@@ -555,11 +602,8 @@ component swc_multiport_pck_pg_free_module is
ob_free_done_o : out std_logic_vector(g_num_ports-1 downto 0);
ob_free_pgaddr_i : in std_logic_vector(g_num_ports * g_page_addr_width - 1 downto 0);
ll_read_addr_o : out std_logic_vector(g_num_ports * g_page_addr_width -1 downto 0);
ll_read_data_i : in std_logic_vector(g_num_ports * g_data_width - 1 downto 0);
--ll_read_data_i : in std_logic_vector(g_page_addr_width - 1 downto 0);
ll_read_req_o : out std_logic_vector(g_num_ports-1 downto 0);
ll_read_valid_data_i : in std_logic_vector(g_num_ports-1 downto 0);
ll_i : in t_ll2fp_array(g_num_ports-1 downto 0);
ll_o : out t_fp2ll_array(g_num_ports-1 downto 0);
mmu_resource_i : in std_logic_vector(g_num_ports * g_resource_num_width -1 downto 0);
......@@ -646,8 +690,7 @@ component swc_multiport_pck_pg_free_module is
g_mpm_fifo_size : integer ;
g_mpm_fetch_next_pg_in_advance : boolean ;
g_drop_outqueue_head_on_full : boolean ;
g_num_global_pause : integer ;
g_num_dbg_vector_width : integer
g_num_global_pause : integer
);
port (
clk_i : in std_logic;
......@@ -666,10 +709,7 @@ component swc_multiport_pck_pg_free_module is
rtu_rsp_i : in t_rtu_response_array(g_num_ports - 1 downto 0);
rtu_ack_o : out std_logic_vector(g_num_ports - 1 downto 0);
nomem_o : out std_logic;
dbg_o : out std_logic_vector(g_num_dbg_vector_width -1 downto 0);
shaper_drop_at_hp_ena_i : in std_logic
nomem_o : out std_logic
);
end component;
......@@ -694,8 +734,7 @@ component swc_multiport_pck_pg_free_module is
g_mpm_fifo_size : integer ;
g_mpm_fetch_next_pg_in_advance : boolean ;
g_drop_outqueue_head_on_full : boolean ;
g_num_global_pause : integer ;
g_num_dbg_vector_width : integer
g_num_global_pause : integer
);
port (
clk_i : in std_logic;
......@@ -736,17 +775,15 @@ component swc_multiport_pck_pg_free_module is
pp_req_i : in std_logic_vector(g_num_ports - 1 downto 0);
pp_quanta_i : in std_logic_vector(g_num_ports*16 - 1 downto 0);
pp_classes_i : in std_logic_vector(g_num_ports*8 - 1 downto 0);
dbg_o : out std_logic_vector(g_num_dbg_vector_width -1 downto 0);
shaper_drop_at_hp_ena_i : in std_logic
);
pp_classes_i : in std_logic_vector(g_num_ports*8 - 1 downto 0)
);
end component;
component swc_ll_read_data_validation is
generic(
g_addr_width : integer ;--:= c_swc_page_addr_width;
g_data_width : integer --:= c_swc_page_addr_width
g_addr_width : integer;--:= c_swc_page_addr_width;
g_data_width : integer;--:= c_swc_page_addr_width
g_wports : integer
);
port(
clk_i : in std_logic;
......@@ -759,10 +796,9 @@ component swc_multiport_pck_pg_free_module is
read_data_valid_i : in std_logic;
read_data_ready_i : in std_logic;
write_addr_i : in std_logic_vector(g_addr_width - 1 downto 0);
write_data_i : in std_logic_vector(g_data_width - 1 downto 0);
write_data_valid_i : in std_logic;
write_data_ready_i : in std_logic;
write_addr_i : in t_lladr_array(g_wports-1 downto 0);
write_data_i : in t_lldat_array(g_wports-1 downto 0);
write_data_ready_i : in std_logic_vector(g_wports-1 downto 0);
read_data_o : out std_logic_vector(g_data_width - 1 downto 0);
read_data_valid_o : out std_logic
......@@ -779,7 +815,7 @@ component swc_multiport_pck_pg_free_module is
g_special_res_num_pages : integer := 248;
g_resource_num : integer := 3; -- this include 1 for unknown
g_resource_num_width : integer := 2;
g_num_dbg_vector_width : integer
g_num_dbg_vector_width : integer := 30
);
port (
clk_i : in std_logic; -- clock & reset
......@@ -830,6 +866,22 @@ component swc_multiport_pck_pg_free_module is
);
end component;
component swc_wishbone_slave is
port (
rst_n_i : in std_logic;
clk_sys_i : in std_logic;
wb_adr_i : in std_logic_vector(2 downto 0);
wb_dat_i : in std_logic_vector(31 downto 0);
wb_dat_o : out std_logic_vector(31 downto 0);
wb_cyc_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic;
wb_stall_o : out std_logic;
regs_i : in t_swc_in_registers;
regs_o : out t_swc_out_registers);
end component;
component swc_core_vectorized_top is
generic(
......
---------------------------------------------------------------------------------------
-- Title : Wishbone slave core for WR Switching core
---------------------------------------------------------------------------------------
-- File : swc_wbgen2_pkg.vhd
-- Author : auto-generated by wbgen2 from wrsw_swcore.wb
-- Created : Tue Sep 13 14:08:37 2016
-- Standard : VHDL'87
---------------------------------------------------------------------------------------
-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE wrsw_swcore.wb
-- DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
---------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package swc_wbgen2_pkg is
-- Input registers (user design -> WB slave)
type t_swc_in_registers is record
csr_mpm_afull_i : std_logic;
csr_mpm_full_i : std_logic;
stat_min_fpg_i : std_logic_vector(15 downto 0);
stat_max_fpg_i : std_logic_vector(15 downto 0);
cur_fpg_i : std_logic_vector(31 downto 0);
afull_thr_i : std_logic_vector(31 downto 0);
end record;
constant c_swc_in_registers_init_value: t_swc_in_registers := (
csr_mpm_afull_i => '0',
csr_mpm_full_i => '0',
stat_min_fpg_i => (others => '0'),
stat_max_fpg_i => (others => '0'),
cur_fpg_i => (others => '0'),
afull_thr_i => (others => '0')
);
-- Output registers (WB slave -> user design)
type t_swc_out_registers is record
csr_new_stat_o : std_logic;
afull_thr_o : std_logic_vector(31 downto 0);
afull_thr_load_o : std_logic;
hp_ob_drop_mask_o : std_logic_vector(18 downto 0);
end record;
constant c_swc_out_registers_init_value: t_swc_out_registers := (
csr_new_stat_o => '0',
afull_thr_o => (others => '0'),
afull_thr_load_o => '0',
hp_ob_drop_mask_o => (others => '0')
);
function "or" (left, right: t_swc_in_registers) return t_swc_in_registers;
function f_x_to_zero (x:std_logic) return std_logic;
function f_x_to_zero (x:std_logic_vector) return std_logic_vector;
end package;
package body swc_wbgen2_pkg is
function f_x_to_zero (x:std_logic) return std_logic is
begin
if x = '1' then
return '1';
else
return '0';
end if;
end function;
function f_x_to_zero (x:std_logic_vector) return std_logic_vector is
variable tmp: std_logic_vector(x'length-1 downto 0);
begin
for i in 0 to x'length-1 loop
if x(i) = '1' then
tmp(i):= '1';
else
tmp(i):= '0';
end if;
end loop;
return tmp;
end function;
function "or" (left, right: t_swc_in_registers) return t_swc_in_registers is
variable tmp: t_swc_in_registers;
begin
tmp.csr_mpm_afull_i := f_x_to_zero(left.csr_mpm_afull_i) or f_x_to_zero(right.csr_mpm_afull_i);
tmp.csr_mpm_full_i := f_x_to_zero(left.csr_mpm_full_i) or f_x_to_zero(right.csr_mpm_full_i);
tmp.stat_min_fpg_i := f_x_to_zero(left.stat_min_fpg_i) or f_x_to_zero(right.stat_min_fpg_i);
tmp.stat_max_fpg_i := f_x_to_zero(left.stat_max_fpg_i) or f_x_to_zero(right.stat_max_fpg_i);
tmp.cur_fpg_i := f_x_to_zero(left.cur_fpg_i) or f_x_to_zero(right.cur_fpg_i);
tmp.afull_thr_i := f_x_to_zero(left.afull_thr_i) or f_x_to_zero(right.afull_thr_i);
return tmp;
end function;
end package body;
---------------------------------------------------------------------------------------
-- Title : Wishbone slave core for WR Switching core
---------------------------------------------------------------------------------------
-- File : swc_wishbone_slave.vhd
-- Author : auto-generated by wbgen2 from wrsw_swcore.wb
-- Created : Tue Sep 13 14:08:37 2016
-- Standard : VHDL'87
---------------------------------------------------------------------------------------
-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE wrsw_swcore.wb
-- DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
---------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.swc_wbgen2_pkg.all;
entity swc_wishbone_slave is
port (
rst_n_i : in std_logic;
clk_sys_i : in std_logic;
wb_adr_i : in std_logic_vector(2 downto 0);
wb_dat_i : in std_logic_vector(31 downto 0);
wb_dat_o : out std_logic_vector(31 downto 0);
wb_cyc_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic;
wb_stall_o : out std_logic;
regs_i : in t_swc_in_registers;
regs_o : out t_swc_out_registers
);
end swc_wishbone_slave;
architecture syn of swc_wishbone_slave is
signal swc_csr_new_stat_dly0 : std_logic ;
signal swc_csr_new_stat_int : std_logic ;
signal swc_hp_ob_drop_mask_int : std_logic_vector(18 downto 0);
signal ack_sreg : std_logic_vector(9 downto 0);
signal rddata_reg : std_logic_vector(31 downto 0);
signal wrdata_reg : std_logic_vector(31 downto 0);
signal bwsel_reg : std_logic_vector(3 downto 0);
signal rwaddr_reg : std_logic_vector(2 downto 0);
signal ack_in_progress : std_logic ;
signal wr_int : std_logic ;
signal rd_int : std_logic ;
signal allones : std_logic_vector(31 downto 0);
signal allzeros : std_logic_vector(31 downto 0);
begin
-- Some internal signals assignments. For (foreseen) compatibility with other bus standards.
wrdata_reg <= wb_dat_i;
bwsel_reg <= wb_sel_i;
rd_int <= wb_cyc_i and (wb_stb_i and (not wb_we_i));
wr_int <= wb_cyc_i and (wb_stb_i and wb_we_i);
allones <= (others => '1');
allzeros <= (others => '0');
--
-- Main register bank access process.
process (clk_sys_i, rst_n_i)
begin
if (rst_n_i = '0') then
ack_sreg <= "0000000000";
ack_in_progress <= '0';
rddata_reg <= "00000000000000000000000000000000";
swc_csr_new_stat_int <= '0';
regs_o.afull_thr_load_o <= '0';
swc_hp_ob_drop_mask_int <= "0000000000000000000";
elsif rising_edge(clk_sys_i) then
-- advance the ACK generator shift register
ack_sreg(8 downto 0) <= ack_sreg(9 downto 1);
ack_sreg(9) <= '0';
if (ack_in_progress = '1') then
if (ack_sreg(0) = '1') then
swc_csr_new_stat_int <= '0';
regs_o.afull_thr_load_o <= '0';
ack_in_progress <= '0';
else
regs_o.afull_thr_load_o <= '0';
end if;
else
if ((wb_cyc_i = '1') and (wb_stb_i = '1')) then
case rwaddr_reg(2 downto 0) is
when "000" =>
if (wb_we_i = '1') then
swc_csr_new_stat_int <= wrdata_reg(0);
end if;
rddata_reg(0) <= '0';
rddata_reg(30) <= regs_i.csr_mpm_afull_i;
rddata_reg(31) <= regs_i.csr_mpm_full_i;
rddata_reg(1) <= 'X';
rddata_reg(2) <= 'X';
rddata_reg(3) <= 'X';
rddata_reg(4) <= 'X';
rddata_reg(5) <= 'X';
rddata_reg(6) <= 'X';
rddata_reg(7) <= 'X';
rddata_reg(8) <= 'X';
rddata_reg(9) <= 'X';
rddata_reg(10) <= 'X';
rddata_reg(11) <= 'X';
rddata_reg(12) <= 'X';
rddata_reg(13) <= 'X';
rddata_reg(14) <= 'X';
rddata_reg(15) <= 'X';
rddata_reg(16) <= 'X';
rddata_reg(17) <= 'X';
rddata_reg(18) <= 'X';
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
ack_sreg(2) <= '1';
ack_in_progress <= '1';
when "001" =>
if (wb_we_i = '1') then
end if;
rddata_reg(15 downto 0) <= regs_i.stat_min_fpg_i;
rddata_reg(31 downto 16) <= regs_i.stat_max_fpg_i;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "010" =>
if (wb_we_i = '1') then
end if;
rddata_reg(31 downto 0) <= regs_i.cur_fpg_i;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "011" =>
if (wb_we_i = '1') then
regs_o.afull_thr_load_o <= '1';
end if;
rddata_reg(31 downto 0) <= regs_i.afull_thr_i;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "100" =>
if (wb_we_i = '1') then
swc_hp_ob_drop_mask_int <= wrdata_reg(18 downto 0);
end if;
rddata_reg(18 downto 0) <= swc_hp_ob_drop_mask_int;
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
rddata_reg(31) <= 'X';
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when others =>
-- prevent the slave from hanging the bus on invalid address
ack_in_progress <= '1';
ack_sreg(0) <= '1';
end case;
end if;
end if;
end if;
end process;
-- Drive the data output bus
wb_dat_o <= rddata_reg;
-- Lock MMU free pages stats
process (clk_sys_i, rst_n_i)
begin
if (rst_n_i = '0') then
swc_csr_new_stat_dly0 <= '0';
regs_o.csr_new_stat_o <= '0';
elsif rising_edge(clk_sys_i) then
swc_csr_new_stat_dly0 <= swc_csr_new_stat_int;
regs_o.csr_new_stat_o <= swc_csr_new_stat_int and (not swc_csr_new_stat_dly0);
end if;
end process;
-- MPM almost full
-- MPM Full
-- min pages
-- max pages
-- pages
-- pages
regs_o.afull_thr_o <= wrdata_reg(31 downto 0);
-- Port mask
regs_o.hp_ob_drop_mask_o <= swc_hp_ob_drop_mask_int;
rwaddr_reg <= wb_adr_i;
wb_stall_o <= (not ack_sreg(0)) and (wb_stb_i and wb_cyc_i);
-- ACK signal generation. Just pass the LSB of ACK counter.
wb_ack_o <= ack_sreg(0);
end syn;
-- -*- Mode: LUA; tab-width: 2 -*-
-- White-Rabbit Watchdog Module
-- author: Grzegorz Daniluk <grzegorz.daniluk@cern.ch>
--
-- Use wbgen2 to generate code, documentation and more.
-- wbgen2 is available at:
-- http://www.ohwr.org/projects/wishbone-gen
--
peripheral {
name = "WR Switching core";
description = "The module is responsible for Ethernet switching with special treatment for High Priority traffic";
hdl_entity = "swc_wishbone_slave";
prefix = "swc";
reg {
name = "SWcore control & status register";
description = "Various control and status bits of the Swcore";
prefix = "CSR";
field {
name = "Lock MMU free pages stats";
description = "write 1: lock new values of MPM_AFULL, MPM_FULL and STAT register \
write 0: no effect";
prefix = "NEW_STAT";
size = 1;
type = MONOSTABLE;
access_dev = READ_ONLY;
access_bus = WRITE_ONLY;
};
field {
name = "MPM almost full";
description = "Bit is 1 if since the last request of stats (NEW_STAT bit) the MMU has reported that MPM is almost full. \
This means we lost some best efford traffic, but not yet the HP traffic.";
prefix = "MPM_AFULL";
size = 1;
align = 30;
type = BIT;
access_dev = WRITE_ONLY;
access_bus = READ_ONLY;
};
field {
name = "MPM Full";
description = "Bit is 1 if since the last request of stats (NEW_STAT bit) the MMU had no free pages to allocate - MPM was full. \
This usually means we have lost some frames (also HP frames).";
prefix = "MPM_FULL";
size = 1;
align = 31;
type = BIT;
access_dev = WRITE_ONLY;
access_bus = READ_ONLY;
};
};
reg {
name = "Free pages in MPM stats";
description = "Values refreshed each time new stats are requested with a NEW_STAT bit";
prefix = "STAT";
field {
name = "min pages";
prefix = "MIN_FPG";
size = 16;
type = SLV;
access_dev = WRITE_ONLY;
access_bus = READ_ONLY;
};
field {
name = "max pages";
prefix = "MAX_FPG";
size = 16;
type = SLV;
access_dev = WRITE_ONLY;
access_bus = READ_ONLY;
};
};
reg {
name = "Current free pages in MPM";
description = "Exports the current number of free pages in the MPM";
prefix = "CUR_FPG";
field {
name = "pages";
size = 32;
type = SLV;
access_dev = WRITE_ONLY;
access_bus = READ_ONLY;
load = LOAD_EXT;
};
};
reg {
name = "MPM almost full threshold";
description = "Number of free pages in MPM when Almost Full flag is set.";
prefix = "AFULL_THR";
field {
name = "pages";
size = 32;
type = SLV;
access_dev = READ_WRITE;
access_bus = READ_WRITE;
load = LOAD_EXT;
};
};
reg {
name = "HP OB register";
description = "Enables dropping regular traffic at the output of swcore ports when HP traffic is queued.";
prefix = "HP_OB";
field {
name = "Port mask";
prefix = "DROP_MASK";
size = 19;
type = SLV;
access_dev = READ_ONLY;
access_bus = READ_WRITE;
};
};
};
......@@ -43,6 +43,7 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_misc.all;
use ieee.numeric_std.all;
use ieee.math_real.CEIL;
use ieee.math_real.log2;
......@@ -52,9 +53,13 @@ use work.swc_swcore_pkg.all;
use work.wr_fabric_pkg.all;
use work.wrsw_shared_types_pkg.all;
use work.mpm_pkg.all;
use work.wishbone_pkg.all;
use work.swc_wbgen2_pkg.all;
entity xswc_core is
generic(
g_interface_mode : t_wishbone_interface_mode := PIPELINED;
g_address_granularity : t_wishbone_address_granularity := BYTE;
g_prio_num : integer ;--:= c_swc_output_prio_num; [works only for value of 8, output_block-causes problem]
g_output_queue_num : integer ;
......@@ -104,8 +109,6 @@ entity xswc_core is
global_pause_i : in t_global_pause_request_array(g_num_global_pause-1 downto 0);
shaper_drop_at_hp_ena_i : in std_logic := '0';
-------------------------------------------------------------------------------
-- I/F with Tx PAUSE triggers (i.e. Endpoints)
-------------------------------------------------------------------------------
......@@ -130,7 +133,13 @@ entity xswc_core is
-- Watchdog outputs
-------------------------------------------------------------------------------
wdog_o : out t_swc_fsms_array(g_num_ports-1 downto 0);
nomem_o : out std_logic);
nomem_o : out std_logic;
-------------------------------------------------------------------------------
-- Wishbone interface
-------------------------------------------------------------------------------
wb_i : in t_wishbone_slave_in;
wb_o : out t_wishbone_slave_out);
end xswc_core;
architecture rtl of xswc_core is
......@@ -146,8 +155,8 @@ architecture rtl of xswc_core is
constant c_mpm_partial_sel_width : integer := integer(g_wb_sel_width-1);
constant c_mpm_page_size_width : integer := integer(CEIL(LOG2(real(g_mpm_page_size-1))));
constant c_ll_addr_width : integer := c_mpm_page_addr_width;
constant c_ll_data_width : integer := c_mpm_page_addr_width + c_max_oob_size_width + 3;
--constant c_ll_addr_width : integer := c_mpm_page_addr_width;
--constant c_ll_data_width : integer := c_mpm_page_addr_width + c_max_oob_size_width + 3;
-- resource management -----------------------
constant c_res_mmu_max_pck_size : integer := 759; -- in 16 bit words (1518 [octets])/(2 [octets])
......@@ -155,7 +164,8 @@ architecture rtl of xswc_core is
constant c_res_mmu_resource_num : integer := 3; -- (1) unknown; (2) special; (3) normal
constant c_res_mmu_resource_num_width : integer := 2;
----------------------------------------------
constant c_hwdu_mmu_width : integer := 10*3;
constant c_ALMOST_FULL_THR : integer := 256;
----------------------------------------------------------------------------------------------------
-- signals connecting >>Input Block<< with >>Memory Management Unit<<
......@@ -247,14 +257,8 @@ architecture rtl of xswc_core is
----------------------------------------------------------------------------------------------------
-- signals connecting >>Input Block<< with >>Linked List<< (new)
----------------------------------------------------------------------------------------------------
signal ib2ll_addr : std_logic_vector(g_num_ports*c_ll_addr_width - 1 downto 0);
signal ib2ll_data : std_logic_vector(g_num_ports*c_ll_data_width - 1 downto 0);
signal ib2ll_next_addr : std_logic_vector(g_num_ports*c_ll_addr_width - 1 downto 0);
signal ib2ll_next_addr_valid : std_logic_vector(g_num_ports - 1 downto 0);
signal ib2ll_wr_req : std_logic_vector(g_num_ports - 1 downto 0);
signal ll2ib_wr_done : std_logic_vector(g_num_ports - 1 downto 0);
signal ib2ll : t_ib2ll_array(g_num_ports-1 downto 0);
signal ll2ib : t_ll2ib_array(g_num_ports-1 downto 0);
----------------------------------------------------------------------------------------------------
-- signals connecting >>Input Block<< with >>Pck's pages freeeing module<<
......@@ -288,10 +292,8 @@ architecture rtl of xswc_core is
signal ll_read_valid_data : std_logic_vector(g_num_ports-1 downto 0);
-- new Free Pck (FP) module <-> Linked List (LL)
signal fp2ll_rd_req : std_logic_vector(g_num_ports - 1 downto 0);
signal fp2ll_addr : std_logic_vector(g_num_ports * c_ll_addr_width - 1 downto 0);
signal ll2fp_read_done : std_logic_vector(g_num_ports - 1 downto 0);
signal ll2fp_data : std_logic_vector(g_num_ports * c_ll_data_width - 1 downto 0);
signal fp2ll : t_fp2ll_array(g_num_ports-1 downto 0);
signal ll2fp : t_ll2fp_array(g_num_ports-1 downto 0);
----------------------------------------------------------------------------------------------------
-- signals connecting >>Pck's pages freeing module (PPFM)<< with >>Page allocator (MMU)<<
......@@ -357,10 +359,22 @@ architecture rtl of xswc_core is
signal wdog_ib : t_swc_fsms_array(g_num_ports-1 downto 0);
signal wdog_ob : t_swc_fsms_array(g_num_ports-1 downto 0);
signal wdog_free : t_swc_fsms_array(g_num_ports-1 downto 0);
signal hwdu_mmu : std_logic_vector(c_hwdu_mmu_width -1 downto 0);
signal dbg_pckstart_pageaddr : std_logic_vector(g_num_ports*c_mpm_page_addr_width - 1 downto 0);
signal dbg_pckinter_pageaddr : std_logic_vector(g_num_ports*c_mpm_page_addr_width - 1 downto 0);
-------------------------------------------------------------------------------
-- Wishbone interface
-------------------------------------------------------------------------------
signal wb_in : t_wishbone_master_out;
signal wb_out : t_wishbone_master_in;
signal regs_fromwb : t_swc_out_registers;
signal regs_towb : t_swc_in_registers;
signal mmu_free_pages : std_logic_vector(c_mpm_page_addr_width downto 0);
signal mmu_afull_thr : std_logic_vector(c_mpm_page_addr_width downto 0);
signal mmu_pmin, mmu_pmin_prev : unsigned(c_mpm_page_addr_width downto 0);
signal mmu_pmax, mmu_pmax_prev : unsigned(c_mpm_page_addr_width downto 0);
signal mmu_was_full, mmu_was_afull : std_logic;
begin --rtl
......@@ -377,6 +391,114 @@ architecture rtl of xswc_core is
-- TRIG2 => tap(95 downto 64),
-- TRIG3 => tap(127 downto 96));
-------------------------------------------------------------------------------
-- Wishbone interface
-------------------------------------------------------------------------------
U_Adapter : wb_slave_adapter
generic map (
g_master_use_struct => true,
g_master_mode => CLASSIC,
g_master_granularity => WORD,
g_slave_use_struct => true,
g_slave_mode => g_interface_mode,
g_slave_granularity => g_address_granularity)
port map (
clk_sys_i => clk_i,
rst_n_i => rst_n_i,
slave_i => wb_i,
slave_o => wb_o,
master_i => wb_out,
master_o => wb_in);
wb_out.err <= '0';
wb_out.rty <= '0';
wb_out.int <= '0';
U_WB_SLAVE : swc_wishbone_slave
port map (
rst_n_i => rst_n_i,
clk_sys_i => clk_i,
wb_adr_i => wb_in.adr(2 downto 0),
wb_dat_i => wb_in.dat,
wb_dat_o => wb_out.dat,
wb_cyc_i => wb_in.cyc,
wb_sel_i => wb_in.sel,
wb_stb_i => wb_in.stb,
wb_we_i => wb_in.we,
wb_ack_o => wb_out.ack,
wb_stall_o=> wb_out.stall,
regs_o => regs_fromwb,
regs_i => regs_towb);
regs_towb.cur_fpg_i(c_mpm_page_addr_width downto 0) <= mmu_free_pages;
regs_towb.cur_fpg_i(31 downto c_mpm_page_addr_width+1) <= (others=>'0');
process(clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
mmu_afull_thr <= std_logic_vector(to_unsigned(c_ALMOST_FULL_THR, c_mpm_page_addr_width+1));
elsif regs_fromwb.afull_thr_load_o = '1' then
mmu_afull_thr <= regs_fromwb.afull_thr_o(c_mpm_page_addr_width downto 0);
end if;
end if;
end process;
regs_towb.afull_thr_i(c_mpm_page_addr_width downto 0) <= mmu_afull_thr;
regs_towb.afull_thr_i(31 downto c_mpm_page_addr_width+1) <= (others=>'0');
process(clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
mmu_pmin <= to_unsigned(c_mpm_page_num, c_mpm_page_addr_width+1);
mmu_pmin_prev <= to_unsigned(c_mpm_page_num, c_mpm_page_addr_width+1);
mmu_pmax <= (others=>'0');
mmu_pmax_prev <= to_unsigned(c_mpm_page_num, c_mpm_page_addr_width+1);
elsif regs_fromwb.csr_new_stat_o = '1' then
mmu_pmin_prev <= mmu_pmin;
mmu_pmax_prev <= mmu_pmax;
mmu_pmin <= to_unsigned(c_mpm_page_num, c_mpm_page_addr_width+1);
mmu_pmax <= (others=>'0');
-- we look for minimal and maximal values
elsif unsigned(mmu_free_pages) > mmu_pmax then
mmu_pmax <= unsigned(mmu_free_pages);
elsif unsigned(mmu_free_pages) < mmu_pmin then
mmu_pmin <= unsigned(mmu_free_pages);
end if;
end if;
end process;
regs_towb.stat_min_fpg_i(c_mpm_page_addr_width downto 0) <= std_logic_vector(mmu_pmin_prev);
regs_towb.stat_min_fpg_i(15 downto c_mpm_page_addr_width+1) <= (others=>'0');
regs_towb.stat_max_fpg_i(c_mpm_page_addr_width downto 0) <= std_logic_vector(mmu_pmax_prev);
regs_towb.stat_max_fpg_i(15 downto c_mpm_page_addr_width+1) <= (others=>'0');
process(clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
regs_towb.csr_mpm_afull_i <= '0';
regs_towb.csr_mpm_full_i <= '0';
mmu_was_full <= '0';
mmu_was_afull <= '0';
elsif regs_fromwb.csr_new_stat_o = '1' then
regs_towb.csr_mpm_afull_i <= mmu_was_afull;
regs_towb.csr_mpm_full_i <= mmu_was_full;
mmu_was_full <= '0';
mmu_was_afull <= '0';
else
if or_reduce(mmu2ib_res_almost_full) = '1' then
mmu_was_afull <= '1';
end if;
if or_reduce(mmu2ib_res_full) = '1' then
mmu_was_full <= '1';
end if;
end if;
end if;
end process;
-------------------------------------------------------------------------------
nomem_o <= mmu_nomem;
tap <= tap_alloc & tap_ob(2);
......@@ -467,14 +589,12 @@ architecture rtl of xswc_core is
-- I/F with Linked List
-------------------------------------------------------------------------------
ll_addr_o => ib2ll_addr((i+1)* c_ll_addr_width - 1 downto i* c_ll_addr_width),
ll_data_o => ib2ll_data((i+1)* c_ll_data_width - 1 downto i *c_ll_data_width),
ll_next_addr_o => ib2ll_next_addr((i+1)* c_ll_addr_width - 1 downto i* c_ll_addr_width),
ll_next_addr_valid_o => ib2ll_next_addr_valid(i),
ll_wr_req_o => ib2ll_wr_req(i),
ll_wr_done_i => ll2ib_wr_done(i),
ll_addr_o => ib2ll(i).adr,
ll_data_o => ib2ll(i).data,
ll_next_addr_o => ib2ll(i).adr_next,
ll_next_addr_valid_o => ib2ll(i).next_valid,
ll_wr_req_o => ib2ll(i).write,
ll_wr_done_i => ll2ib(i).done,
-------------------------------------------------------------------------------
-- I/F with Page Transfer Arbiter (PTA)
......@@ -556,7 +676,7 @@ architecture rtl of xswc_core is
--: output traffic shaper (PAUSE + time-aware-shaper)
-------------------------------------------------------------------------------
ots_output_mask_i => ots2ob_output_masks(i),
ots_output_drop_at_rx_hp_i=> shaper_drop_at_hp_ena_i,
ots_output_drop_at_rx_hp_i=> regs_fromwb.hp_ob_drop_mask_o(i),
-------------------------------------------------------------------------------
-- pWB : output (goes to the Endpoint)
......@@ -604,10 +724,8 @@ architecture rtl of xswc_core is
ob_free_done_o => ppfm_free_done_to_ob,
ob_free_pgaddr_i => ob_free_pgaddr,
ll_read_addr_o => fp2ll_addr, --ppfm_read_addr,
ll_read_data_i => ll2fp_data, --ll_data,
ll_read_req_o => fp2ll_rd_req, --ppfm_read_req,
ll_read_valid_data_i => ll2fp_read_done, --ll_read_valid_data,
ll_i => ll2fp,
ll_o => fp2ll,
mmu_resource_i => mmu2ppfm_resource,
......@@ -639,31 +757,20 @@ architecture rtl of xswc_core is
g_data_width => c_ll_data_width
)
port map(
rst_n_i => rst_n_i,
clk_i => clk_i,
write_i => ib2ll_wr_req,
write_done_o => ll2ib_wr_done,
write_next_addr_i => ib2ll_next_addr,
write_next_addr_valid_i => ib2ll_next_addr_valid,
rst_n_i => rst_n_i,
clk_i => clk_i,
write_addr_i => ib2ll_addr,
write_data_i => ib2ll_data,
ib_i => ib2ll,
ib_o => ll2ib,
mpm_rpath_addr_i => mpm2ll_addr,
mpm_rpath_data_o => ll2mpm_data,
mpm_rpath_addr_i => mpm2ll_addr,
mpm_rpath_data_o => ll2mpm_data,
free_pck_i => fp2ll,
free_pck_o => ll2fp
free_pck_rd_req_i => fp2ll_rd_req,
free_pck_addr_i => fp2ll_addr,
free_pck_read_done_o => ll2fp_read_done,
free_pck_data_o => ll2fp_data
);
-- tmp
--fp2ll_rd_req <= (others => '0');
--fp2ll_addr <= (others => '0');
----------------------------------------------------------------------
-- Memory Mangement Unit (MMU)
----------------------------------------------------------------------
......@@ -679,8 +786,7 @@ architecture rtl of xswc_core is
g_page_size => g_mpm_page_size,
g_special_res_num_pages => c_res_mmu_special_res_num_pages,
g_resource_num => c_res_mmu_resource_num,
g_resource_num_width => c_res_mmu_resource_num_width,
g_num_dbg_vector_width => c_hwdu_mmu_width
g_resource_num_width => c_res_mmu_resource_num_width
)
port map (
rst_n_i => rst_n_i,
......@@ -723,7 +829,9 @@ architecture rtl of xswc_core is
res_full_o => mmu2ib_res_full,
res_almost_full_o => mmu2ib_res_almost_full,
dbg_o => hwdu_mmu
free_pages_o => mmu_free_pages,
afull_thr_i => mmu_afull_thr
-- tap_out_o => tap_alloc
);
......@@ -802,8 +910,6 @@ architecture rtl of xswc_core is
ib_hp_i => ib_hp
);
dbg_o(31 downto 0) <= "00" & hwdu_mmu;
WDOG_GEN: for I in 0 to g_num_ports-1 generate
wdog_o(I)(c_ALLOC_FSM_IDX) <= wdog_ib(I)(c_ALLOC_FSM_IDX);
wdog_o(I)(c_TRANS_FSM_IDX) <= wdog_ib(I)(c_TRANS_FSM_IDX);
......
......@@ -284,6 +284,7 @@ architecture behavoural of xswc_output_block_new is
signal cycle_frozen_cnt : unsigned(9 downto 0);
signal current_tx_prio : std_logic_vector(g_queue_num - 1 downto 0);
signal new_tx_prio : std_logic_vector(g_queue_num - 1 downto 0);
signal hp_prio_mask : std_logic_vector(g_queue_num - 1 downto 0);
signal zero_prio_mask : std_logic_vector(g_queue_num - 1 downto 0);
......@@ -570,19 +571,23 @@ begin -- behavoural
begin
if rising_edge(clk_i) then
if(rst_n_i = '0') then
current_tx_prio <= (others => '0');
new_tx_prio <= (others => '0');
else
if(rd_valid = '1') then
current_tx_prio <= read_array;
new_tx_prio <= rd_array;
elsif((s_send_pck = S_EOF) and (s_prep_to_send = S_IDLE)) then
current_tx_prio <= (others => '0');
new_tx_prio <= (others => '0');
end if;
end if;
end if;
end process p_track_tx_prio;
-- deciding whether to drop currently tx-ed frame
hp_in_queuing <= '1' when ((read_array and hp_prio_mask) /= zero_prio_mask) else '0';
hp_in_queuing <= '1' when ((read_array and hp_prio_mask) /= zero_prio_mask) else
'1' when ((new_tx_prio and hp_prio_mask) /= zero_prio_mask) else
--'1' when ((new_tx_prio and hp_prio_mask) /= zero_prio_mask and (new_tx_prio /= current_tx_prio)) else
'0';
--non_hp_txing <= '1' when ((new_tx_prio and (not hp_prio_mask)) /= zero_prio_mask) else '0';
non_hp_txing <= '1' when ((current_tx_prio and (not hp_prio_mask)) /= zero_prio_mask) else '0';
abord_tx_at_hp <= non_hp_txing and -- we are currently sending frame which is not HP
......@@ -661,7 +666,7 @@ begin -- behavoural
--===========================================================================================
when S_NEWPCK_PAGE_SET_IN_ADVANCE =>
--===========================================================================================
if(request_retry = '1') then
if(request_retry = '1' or (abord_tx_at_hp = '1' and mpm_pg_req_i = '0')) then
mpm_abort <= '1';
s_prep_to_send <= S_RETRY_PREPARE;
mpm_pg_addr_memorized_valid <= '1';
......@@ -701,7 +706,13 @@ begin -- behavoural
when S_RETRY_PREPARE =>
--===========================================================================================
if(mpm_pg_req_i = '1') then
mpm_pg_addr <= pck_start_pgaddr;
--mpm_pg_addr <= pck_start_pgaddr;
if(mpm_pg_addr_memorized_valid = '1') then
mpm_pg_addr <= mpm_pg_addr_memorized;
mpm_pg_addr_memorized_valid <= '0';
else
mpm_pg_addr <= pck_start_pgaddr;
end if;
mpm_pg_valid <= '1';
s_prep_to_send <= S_RETRY_READY;
end if;
......@@ -760,6 +771,7 @@ begin -- behavoural
tmp_dat <= (others => '0');
tmp_sel <= (others => '0');
page_set_in_advance <= '0';
current_tx_prio <= (others => '0');
--========================================
else
-- default values
......@@ -773,10 +785,12 @@ begin -- behavoural
when S_IDLE =>
--===========================================================================================
if(s_prep_to_send = S_NEWPCK_PAGE_READY and src_i.err = '0' and src_i.stall = '0' and ifg_count = x"0") then
if((s_prep_to_send = S_NEWPCK_PAGE_READY or s_prep_to_send = S_RETRY_READY)
and src_i.err = '0' and src_i.stall = '0' and ifg_count = x"0") then
src_out_int.cyc <= '1';
s_send_pck <= S_DATA;
pck_start_pgaddr <= mpm_pg_addr;
current_tx_prio <= new_tx_prio;
end if;
--===========================================================================================
......@@ -866,7 +880,9 @@ begin -- behavoural
src_out_int.cyc <= '1';
s_send_pck <= S_DATA;
pck_start_pgaddr <= mpm_pg_addr;
current_tx_prio <= new_tx_prio;
else
current_tx_prio <= (others=>'0');
s_send_pck <= S_IDLE;
end if;
else
......@@ -891,7 +907,9 @@ begin -- behavoural
src_out_int.cyc <= '1';
s_send_pck <= S_DATA;
pck_start_pgaddr <= mpm_pg_addr;
current_tx_prio <= new_tx_prio;
else
current_tx_prio <= (others=>'0');
s_send_pck <= S_IDLE;
end if;
end if;
......
......@@ -188,7 +188,7 @@ end scb_top_bare;
architecture rtl of scb_top_bare is
constant c_GW_VERSION : std_logic_vector(31 downto 0) := x"20_02_14_00"; --DD_MM_YY_VV
constant c_NUM_WB_SLAVES : integer := 14;
constant c_NUM_WB_SLAVES : integer := 15;
constant c_NUM_PORTS : integer := g_num_ports;
constant c_MAX_PORTS : integer := 18;
constant c_NUM_GL_PAUSE : integer := 2; -- number of output global PAUSE sources for SWcore
......@@ -220,6 +220,7 @@ architecture rtl of scb_top_bare is
constant c_SLAVE_PSTATS : integer := 11;
constant c_SLAVE_HWIU : integer := 12;
constant c_SLAVE_WDOG : integer := 13;
constant c_SLAVE_SWC : integer := 14;
--constant c_SLAVE_DUMMY : integer := 13;
......@@ -799,6 +800,8 @@ begin
U_Swcore : xswc_core
generic map (
g_interface_mode => PIPELINED,
g_address_granularity => BYTE,
g_prio_num => 8,
g_output_queue_num => 8,
g_max_pck_size => 10 * 1024,
......@@ -817,8 +820,7 @@ begin
g_mpm_fifo_size => 8,
g_mpm_fetch_next_pg_in_advance => false,
g_drop_outqueue_head_on_full => true,
g_num_global_pause => c_NUM_GL_PAUSE,
g_num_dbg_vector_width => c_DBG_V_SWCORE)
g_num_global_pause => c_NUM_GL_PAUSE)
port map (
clk_i => clk_sys,
clk_mpm_core_i => clk_aux_i,
......@@ -829,19 +831,16 @@ begin
snk_i => swc_snk_in,
snk_o => swc_snk_out,
shaper_drop_at_hp_ena_i => shaper_drop_at_hp_ena,
-- pause stuff
global_pause_i => global_pause,
perport_pause_i => fc_rx_pause,
dbg_o => dbg_n_regs(32+c_DBG_V_SWCORE-1 downto 32),
rtu_rsp_i => rtu_rsp,
rtu_ack_o => swc_rtu_ack,
rtu_abort_o =>rtu_rsp_abort,-- open --rtu_rsp_abort
wdog_o => swc_wdog_out
);
wdog_o => swc_wdog_out,
wb_i => cnx_master_out(c_SLAVE_SWC),
wb_o => cnx_master_in(c_SLAVE_SWC));
-- SWcore global pause nr=0 assigned to TRU
global_pause(0) <= swc2tru_req;
......
......@@ -220,6 +220,22 @@ package wrs_sdb_pkg is
date => x"20150630",
name => "WRSW WATCHDOG ")));
constant c_xswc_swcore_sdb: t_sdb_device := (
abi_class => x"0000",
abi_ver_major => x"01",
abi_ver_minor => x"01",
wbd_endian => c_sdb_endian_big,
wbd_width => x"7",
sdb_component => (
addr_first => x"0000000000000000",
addr_last => x"00000000000000ff",
product => (
vendor_id => x"000000000000CE42", -- CERN
device_id => x"5783046b", -- echo -n "xswc_core" | md5sum - | cut -c1-8
version => x"00000001",
date => x"20160810",
name => "WRSW SWCORE ")));
-- RT subsystem crossbar
constant c_rtbar_layout : t_sdb_record_array(7 downto 0) :=
(0 => f_sdb_embed_device(f_xwb_dpram(16384), x"00000000"),
......@@ -259,7 +275,7 @@ package wrs_sdb_pkg is
f_xwb_bridge_layout_sdb(true, c_epbar_layout, c_epbar_sdb_address);
-- WRS main crossbar
constant c_layout : t_sdb_record_array(13+4 downto 0) :=
constant c_layout : t_sdb_record_array(14+4 downto 0) :=
(0 => f_sdb_embed_bridge(c_rtbar_bridge_sdb, x"00000000"), --RT subsystem
1 => f_sdb_embed_device(c_xwrsw_nic_sdb, x"00020000"), --NIC
2 => f_sdb_embed_bridge(c_epbar_bridge_sdb, x"00030000"), --Endpoints
......@@ -274,10 +290,11 @@ package wrs_sdb_pkg is
11 => f_sdb_embed_device(c_xwrsw_pstats_sdb, x"00058000"), --PSTATS
12 => f_sdb_embed_device(c_xwrsw_hwiu_sdb, x"00059000"), --HWIU
13 => f_sdb_embed_device(c_xwrsw_watchdog_sdb, x"0005a000"), --Watchdog
14 => f_sdb_embed_repo_url(c_sdb_repo_url),
15 => f_sdb_embed_synthesis(c_sdb_top_syn_info),
16 => f_sdb_embed_synthesis(c_sdb_general_cores_syn_info),
17 => f_sdb_embed_synthesis(c_sdb_wr_cores_syn_info));
14 => f_sdb_embed_device(c_xswc_swcore_sdb, x"0005b000"), --SWcore
15 => f_sdb_embed_repo_url(c_sdb_repo_url),
16 => f_sdb_embed_synthesis(c_sdb_top_syn_info),
17 => f_sdb_embed_synthesis(c_sdb_general_cores_syn_info),
18 => f_sdb_embed_synthesis(c_sdb_wr_cores_syn_info));
constant c_sdb_address : t_wishbone_address := x"00070000";
end wrs_sdb_pkg;
......@@ -264,6 +264,8 @@ package wrsw_components_pkg is
component xswc_core is
generic(
g_interface_mode : t_wishbone_interface_mode := PIPELINED;
g_address_granularity : t_wishbone_address_granularity := BYTE;
g_prio_num : integer ;
g_output_queue_num : integer ;
g_max_pck_size : integer ;
......@@ -284,8 +286,7 @@ package wrsw_components_pkg is
g_mpm_fifo_size : integer ;
g_mpm_fetch_next_pg_in_advance : boolean ;
g_drop_outqueue_head_on_full : boolean ;
g_num_global_pause : integer ;
g_num_dbg_vector_width : integer := 32
g_num_global_pause : integer
);
port (
clk_i : in std_logic;
......@@ -300,14 +301,13 @@ package wrsw_components_pkg is
global_pause_i : in t_global_pause_request_array(g_num_global_pause-1 downto 0);
perport_pause_i : in t_pause_request_array(g_num_ports-1 downto 0);
shaper_drop_at_hp_ena_i : in std_logic := '0';
dbg_o : out std_logic_vector(g_num_dbg_vector_width - 1 downto 0);
rtu_rsp_i : in t_rtu_response_array(g_num_ports - 1 downto 0);
rtu_ack_o : out std_logic_vector(g_num_ports - 1 downto 0);
rtu_abort_o : out std_logic_vector(g_num_ports - 1 downto 0);
wdog_o : out t_swc_fsms_array(g_num_ports-1 downto 0);
nomem_o : out std_logc
);
nomem_o : out std_logc;
wb_i : in t_wishbone_slave_in;
wb_o : out t_wishbone_slave_out);
end component;
component xwrsw_rtu
generic (
......
......@@ -324,6 +324,8 @@ package wrsw_top_pkg is
end component;
component xswc_core is
generic(
g_interface_mode : t_wishbone_interface_mode := PIPELINED;
g_address_granularity : t_wishbone_address_granularity := BYTE;
g_prio_num : integer ;--:= c_swc_output_prio_num; [works only for value of 8, output_block-causes problem]
g_output_queue_num : integer ;
g_max_pck_size : integer ;-- in 16bits words --:= c_swc_max_pck_size
......@@ -358,14 +360,14 @@ package wrsw_top_pkg is
global_pause_i : in t_global_pause_request_array(g_num_global_pause-1 downto 0);
perport_pause_i : in t_pause_request_array(g_num_ports-1 downto 0);
shaper_drop_at_hp_ena_i : in std_logic := '0';
dbg_o : out std_logic_vector(g_num_dbg_vector_width - 1 downto 0);
rtu_rsp_i : in t_rtu_response_array(g_num_ports - 1 downto 0);
rtu_ack_o : out std_logic_vector(g_num_ports - 1 downto 0);
rtu_abort_o : out std_logic_vector(g_num_ports - 1 downto 0);
wdog_o : out t_swc_fsms_array(g_num_ports-1 downto 0);
nomem_o : out std_logic
);
nomem_o : out std_logic;
wb_i : in t_wishbone_slave_in;
wb_o : out t_wishbone_slave_out);
end component;
component xwrsw_rtu
......
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