master
openpowerwtf 2 years ago
commit f9d5f06f61

@ -0,0 +1,19 @@
© IBM Corp. 2021
Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
repository except in compliance with the License as modified.
You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Modified Terms:

1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
the work of authorship in physical form.

Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License.

Brief explanation of modifications:

Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
it unambiguously permits a user to make and use the physical chip.

Binary file not shown.

Binary file not shown.

@ -0,0 +1,44 @@
## Cells needed for the Skywater test site

We need to produce the necessary
* Schematic
* Layout
* Logic and timing models for



### Low level cells

1) 10T SRAM
a. WWL, RWL0, , RWL1
b. (WBL WBL_B), RBL0, RBL1
2) Local eval (NAND2 with 2 precharged inputs)

a. PC_Left, PC_Right, In_Left, In_Right -> Q (output)

3) LSDL state-holding latch (Latch with 2 dynamic inputs forming an 'Or')

a. In_Left, In_Right, CLK -> Q (output)


### Mid level cell

Partially decode 2R1W 64Rx24 bit array). (Includes early/late output latch)

Inputs:

1) Clock*A0,Clock*~A0
2) ~A1*~A2,~A1,*~A2, A1*~A2,A1*~A2,
3) A3 ,~A3
4) ~A4*~A5,~A4,*~A5, A14*~A5,A4*~A5,
5) DataIn0..DI23
6) Early and late Clock for LSDL state holding latch.

Outputs:

1) DataOut00..DO023
2) DO10..DO123
3) DO20..DO223
4) DO30..DO323

@ -0,0 +1,42 @@
## Cells needed for the Skywater test site

We need to produce the necessary
* Schematic
* Layout
* Logic and timing models for

### Low level cells

1) 10T SRAM
a. WWL, RWL0, , RWL1
b. (WBL WBL_B), RBL0, RBL1
2) Local eval (NAND2 with 2 precharged inputs)

a. PC_Left, PC_Right, In_Left, In_Right -> Q (output)

3) LSDL state-holding latch (Latch with 2 dynamic inputs forming an 'Or')

a. In_Left, In_Right, CLK -> Q (output)


### Mid level cell

Partially decode 2R1W 64Rx24 bit array). (Includes early/late output latch)

Inputs:

1) Clock*A0,Clock*~A0
2) ~A1*~A2,~A1,*~A2, A1*~A2,A1*~A2,
3) A3 ,~A3
4) ~A4*~A5,~A4,*~A5, A14*~A5,A4*~A5,
5) DataIn0..DI23
6) Early and late Clock for LSDL state holding latch.

Outputs:

1) DataOut00..DO023
2) DO10..DO123
3) DO20..DO223
4) DO30..DO323

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

@ -0,0 +1,25 @@
# General Notes

## SDR/DDR

* logical wrappers instantiate hard array
* SDR: use multiple hard array instances to add ports
* DDR: use early/late pulses to double read/write ports

### DDR Implementation

* strobes are generated from clk based on configurable delay parameters

## Test site arrays

* 2R1W, SDR - this is the sdr hard array and simple logical wrapper using single clock
* 4R2W, DDR - this is the ddr hard array and double-rate logical wrapper generating early/late pulses

### Configuration options

* SDR clock frequency (external to logical array)
* DDR clock frequency (external to logical array)

* SDR Pulse Control
* DDR Pulse Control

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 KiB

@ -0,0 +1,41 @@
<img align="right" src="doc/img/bob_64x64.jpg">

# ToySRAM

## A test site for a high-specific-bandwidth memory design

* We make high-specific-bandwidth multiport memories childs play
* We make 10T SRAM a first-class citizen, and use pumping and replication for high frequency and additional ports

![toy-sram](doc/slide2.png)

## Description

The goal is to demonstrate specific bandwidth results from 90nm to 2nm, and use
the basic design to grow as many ports as necessary through replication, to
produce more efficient processors and accelerators with *less circuit-design effort*.

What is specific bandwidth?

* It measures the read and write bandwidth per unit area
* Bandwidth per unit area is an analog to specific gravity, which is mass per unit volume
* It's more encompassing than bit density, which drives complexity to improve bandwidth

Why does Toy-SRAM do so well?

* It's enhanced by having a 10T SRAM/2 read ports/1 write port
* It supports low-cost super-pipelining (2x+ the system frequency, without latch overhead)
* It enables energy-efficient ultralow-voltage operation by avoiding read disturb

Specific bandwidth can be expressed with two metrics:

* Technology dependent “X TB/(sec * mm 2 )”
* Technology independent “Y 1/(FO4 delay * PC PITCH * min horizontal metal pitch)”

<img align="left" width="40%" src="/custom/layout/sram_sp.png">
<img align="right" width="40%" src="/custom/layout/sram_dp.png">
<br clear="all" />

## Links

* skywater-pdk.slack.com#toysram

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

@ -0,0 +1,20 @@
---
project:
description: "High-specific-bandwidth memory cell test site for 90nm"
foundry: "SkyWater"
git_url: "https://git.openpower.foundation/cores/toysram.git"
organization: "Open POWER"
organization_url: "http://openpowerfoundation.com"
owner: "Bob Montoya"
process: "SKY90"
project_name: "ToySRAM"
project_id: "00000000"
tags:
- "Open MPW"
- "Custom Cell"
- "Array"
category: "Custom Cell"
top_level_netlist: "verilog/gl/site.v"
user_level_netlist: "verilog/gl/user_project_wrapper.v"
version: "1.00"
cover_image: "docs/img/bob.jpg"

@ -0,0 +1,77 @@
// SPDX-FileCopyrightText: 2020 Efabless Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// SPDX-License-Identifier: Apache-2.0

`default_nettype none
/*
*-------------------------------------------------------------
*
* user_project_wrapper
*
* This wrapper enumerates all of the pins available to the
* user for the user project.
*
* An example user project is provided in this wrapper. The
* example should be removed and replaced with the actual
* user project.
*
*-------------------------------------------------------------
*/

module user_project_wrapper #(
parameter BITS = 32
)(
`ifdef USE_POWER_PINS
inout vdda1, // User area 1 3.3V supply
inout vdda2, // User area 2 3.3V supply
inout vssa1, // User area 1 analog ground
inout vssa2, // User area 2 analog ground
inout vccd1, // User area 1 1.8V supply
inout vccd2, // User area 2 1.8v supply
inout vssd1, // User area 1 digital ground
inout vssd2, // User area 2 digital ground
`endif

// Wishbone Slave ports (WB MI A)
input wb_clk_i,
input wb_rst_i,
input wbs_stb_i,
input wbs_cyc_i,
input wbs_we_i,
input [3:0] wbs_sel_i,
input [31:0] wbs_dat_i,
input [31:0] wbs_adr_i,
output wbs_ack_o,
output [31:0] wbs_dat_o,

// Logic Analyzer Signals
input [127:0] la_data_in,
output [127:0] la_data_out,
input [127:0] la_oen,

// IOs
input [`MPRJ_IO_PADS-1:0] io_in,
output [`MPRJ_IO_PADS-1:0] io_out,
output [`MPRJ_IO_PADS-1:0] io_oeb,

// Analog (direct connection to GPIO pad---use with caution)
// Note that analog I/O is not available on the 7 lowest-numbered
// GPIO pads, and so the analog_io indexing is offset from the
// GPIO indexing by 7.
inout [`MPRJ_IO_PADS-8:0] analog_io,

// Independent clock (on independent integer divider)
input user_clock2
);
endmodule // user_project_wrapper

@ -0,0 +1,29 @@
# design and tech

unit = test_sdr_2r1w_64x72_top

# top directory
export DESIGN_TOP = array
# unit directory (log, objects, reports, results)
export DESIGN_NICKNAME = array_$(unit)
# macro
export DESIGN_NAME = $(unit)
#tech
export PLATFORM = sky130hd

# sources
export VERILOG_FILES = $(sort $(wildcard ./designs/$(PLATFORM)/$(DESIGN_TOP)/src/verilog/work/test_sdr_2r1w_64x72_top.v))
export SDC_FILE = ./designs/$(PLATFORM)/$(DESIGN_TOP)/constraint_$(unit).sdc

$(info Source files:)
$(info $(VERILOG_FILES))
$(info ..................................................)

# parms
export PLACE_DENSITY ?= 0.50
export ABC_CLOCK_PERIOD_IN_PS ?= 10

# must be multiples of placement site (0.46 x 2.72)
export DIE_AREA = 0 0 3011.160 4022.880
export CORE_AREA = 5.520 10.880 3005.640 4012.000

@ -0,0 +1,20 @@
set clk_name clock
set clk_period 10
set input_delay_value 1
set output_delay_value 1

# define clock
# nclk[0]: clk
# nclk[1]: reset
# nclk[2]: clk2x (fpga)
# nclk[3]: clk4x (fpga)

#set clkPort [lindex [get_ports $clk_name] 0] ;#wtf IS SELECTING 0 ALWAYS CORRECT??? tritoncts doesnt like this
set clkPort [get_ports $clk_name]
create_clock $clkPort -name clock -period $clk_period

# apply clock to ins and outs
set clk_index [lsearch [all_inputs] $clkPort]
set all_inputs_wo_clk [lreplace [all_inputs] $clk_index $clk_index]
set_input_delay $input_delay_value -clock [get_clocks clk] $all_inputs_wo_clk
set_output_delay $output_delay_value -clock [get_clocks clk] [all_outputs]

@ -0,0 +1,22 @@
## Logical Array Wrapper

* verilog is in rtl/src/array
* parameter determines sim vs tech during rtl compile

## Physical Array

* custom cell(s) to be designed
* custom/

## Test Site

* verilog is in rtl/src/site
* supporting logic for test and debug through available Caravel connections

## Verification

* rtl/sim/coco

## Caravel

* to be incorporated into https://github.com/efabless/caravel flow as a user project area

@ -0,0 +1,4 @@
__pycache__/
sim_build/
build_32x32/
build_site/

@ -0,0 +1,46 @@
# sdr ra
# make -f Makefile.icarus build # rebuild and sim and fst
# make -f Makefile.icarus run # sim and fst
# make -f Makefile.icarus # sim

#COCOTB_LOG_LEVEL=DEBUG
#GPI_EXTRA=vpi

#COCOTB_RESOLVE_X = ZEROS # VALUE_ERROR ZEROS ONES RANDOM

SIM_BUILD ?= build_32x32
SIM ?= icarus

# options
#COCOTB_HDL_TIMEUNIT ?= 1ns
#COCOTB_HDL_TIMEPRECISION ?= 1ps
#COCOTB_RESOLVE_X = VALUE_ERROR # ZEROS ONES RANDOM

# icarus

VERILOG_ROOT = src

COMPILE_ARGS = -I$(VERILOG_ROOT) -y$(VERILOG_ROOT)

# other options

# rtl
TOPLEVEL_LANG = verilog
# top-level to enable trace, etc.
VERILOG_SOURCES = ./test_ra_sdr_32x32.v
TOPLEVEL = test_ra_sdr_32x32

# python test
MODULE = tb
TESTCASE = tb_32x32

# cocotb make rules
include $(shell cocotb-config --makefiles)/Makefile.sim

build: clean sim fst

run: sim fst

fst:
vcd2fst test_ra_sdr_32x32.vcd test_ra_sdr_32x32.fst
#rm test_ra_sdr_32x32.vcd

@ -0,0 +1,46 @@
# sdr ra
# make -f Makefile.icarus build # rebuild and sim and fst
# make -f Makefile.icarus run # sim and fst
# make -f Makefile.icarus # sim

#COCOTB_LOG_LEVEL=DEBUG
#GPI_EXTRA=vpi

#COCOTB_RESOLVE_X = ZEROS # VALUE_ERROR ZEROS ONES RANDOM

#SIM_BUILD ?= build
SIM ?= icarus

# options
#COCOTB_HDL_TIMEUNIT ?= 1ns
#COCOTB_HDL_TIMEPRECISION ?= 1ps
#COCOTB_RESOLVE_X = VALUE_ERROR # ZEROS ONES RANDOM

# icarus

VERILOG_ROOT = src

COMPILE_ARGS = -I$(VERILOG_ROOT) -y$(VERILOG_ROOT)

# other options

# rtl
TOPLEVEL_LANG = verilog
# top-level to enable trace, etc.
VERILOG_SOURCES = ./test_ra_sdr_64x72.v
TOPLEVEL = test_ra_sdr_64x72

# python test
MODULE = tb
TESTCASE = tb

# cocotb make rules
include $(shell cocotb-config --makefiles)/Makefile.sim

build: clean sim fst

run: sim fst

fst:
vcd2fst test_ra_sdr_64x72.vcd test_ra_sdr_64x72.fst
rm test_ra_sdr_64x72.vcd

@ -0,0 +1,46 @@
# sdr ra
# make -f Makefile.icarus build # rebuild and sim and fst
# make -f Makefile.icarus run # sim and fst
# make -f Makefile.icarus # sim

#COCOTB_LOG_LEVEL=DEBUG
#GPI_EXTRA=vpi

#COCOTB_RESOLVE_X = ZEROS # VALUE_ERROR ZEROS ONES RANDOM

SIM_BUILD ?= build_site
SIM ?= icarus

# options
#COCOTB_HDL_TIMEUNIT ?= 1ns
#COCOTB_HDL_TIMEPRECISION ?= 1ps
#COCOTB_RESOLVE_X = VALUE_ERROR # ZEROS ONES RANDOM

# icarus

VERILOG_ROOT = src

COMPILE_ARGS = -I$(VERILOG_ROOT)/../site -I$(VERILOG_ROOT)/../array -y$(VERILOG_ROOT)/../site -y$(VERILOG_ROOT)/../array

# other options

# rtl
TOPLEVEL_LANG = verilog
# top-level to enable trace, etc.
VERILOG_SOURCES = ./test_site.v
TOPLEVEL = test_site

# python test
MODULE = tb
TESTCASE = tb_site

# cocotb make rules
include $(shell cocotb-config --makefiles)/Makefile.sim

build: clean sim fst

run: sim fst

fst:
vcd2fst test_site.vcd test_site.fst
rm test_site.vcd

@ -0,0 +1,117 @@
# OP Environment

import cocotb
from cocotb.triggers import Timer
from cocotb.handle import Force
from cocotb.handle import Release

from dotmap import DotMap

# ------------------------------------------------------------------------------------------------
# Classes

class Sim(DotMap):

def msg(self, m):
self.dut._log.info(f'[{self.cycle:08d}] {m}') #wtf do multiline if /n in m

def __init__(self, dut, cfg=None):
super().__init__()
self.dut = dut
# defaults
self.memFiles = [] #wtf cmdline parm
self.threads = 0
self.resetCycle = 10
self.hbCycles = 100
self.clk2x = True
self.clk4x = False
self.resetAddr = 0xFFFFFFFC
self.resetOp = 0x48000002
self.maxCycles = 150
self.memFiles = None
self.config = DotMap()
self.config.core = DotMap({
'creditsLd': 1,
'creditsSt': 1,
'creditsLdStSingle': False
})
self.config.a2l2 = DotMap({
'badAddr': [('E0','E0', 'IRW')]
})
# json
if cfg is not None:
pass

# runtime
self.cycle = 0
self.ok = True
self.fail = None
self.done = False

if self.threads is None:
try:
v = dut.an_ac_pm_thread_stop[1].value
self.threads = 2
except:
self.threads = 1
self.msg(f'Set threads={self.threads}.')

class TransQ(DotMap):
def __init__(self):
super().__init__()

class Memory(DotMap):

def __init__(self, sim, default=0, logStores=True):
super().__init__()
self.sim = sim
self.data = {}
self.le = False
self.default = default # default word data for unloaded
self.logStores = logStores

def loadFile(self, filename, format='ascii', addr=0, le=0):
# format # binary, ascii, ascii w/addr
# le: reverse bytes
try:
if format == 'ascii':
with open(filename, 'r') as f:
lines = f.readlines()
for line in lines:
self.data[addr] = int(line, 16) # key is int
addr += 4
elif format == 'binary':
pass
elif format == 'addrdata':
pass
except Exception as e:
self.sim.msg(f'Error reading {filename}:\n{e}')
raise IOError

# word-aligned byte address
def read(self, addr):
try:
addr = addr + 0
except:
addr = int(addr, 16)
if addr in self.data:
return self.data[addr]
else:
return self.default

# word-aligned byte address + data
def write(self, addr, data):
try:
addr = addr + 0
except:
addr = int(addr, 16)
try:
data = data + 0
except:
data = int(data, 16)
if self.logStores:
if addr not in self.data:
self.sim.msg(f'Mem Update: @{addr:08X} XXXXXXXX->{data:08X}')
else:
self.sim.msg(f'Mem Update: @{addr:08X} {self.data[addr]:08X}->{data:08X}')
self.data[addr] = data

File diff suppressed because it is too large Load Diff

@ -0,0 +1,174 @@
# Cocotb + Icarus Verilog Array Sim

Cocotb test created from original pyverilator version - run random commands using 64x72 logical array.

## Array Wrapper

* compile and run

```
make -f Makefile_sdr_32x32 build

```

* just run (tb.py changes, etc.)

```
make -f Makefile_sdr_32x32 run

```

* results

```
make -f Makefile_sdr_32x32 run >& sim_32x32.txt

MODULE=tb TESTCASE=tb_32x32 TOPLEVEL=test_ra_sdr_32x32 TOPLEVEL_LANG=verilog \
/usr/local/bin/vvp -M /home/wtf/.local/lib/python3.8/site-packages/cocotb/libs -m libcocotbvpi_icarus build_32x32/sim.vvp
-.--ns INFO cocotb.gpi ..mbed/gpi_embed.cpp:76 in set_program_name_in_venv Did not detect Python virtual environment. Using system-wide Python interpreter
-.--ns INFO cocotb.gpi ../gpi/GpiCommon.cpp:99 in gpi_print_registered_impl VPI registered
0.00ns INFO Running on Icarus Verilog version 12.0 (devel)
0.00ns INFO Running tests with cocotb v1.7.0.dev0 from /home/wtf/.local/lib/python3.8/site-packages/cocotb
0.00ns INFO Seeding Python random module with 1654704020
0.00ns INFO Found test tb.tb_32x32
0.00ns INFO running tb_32x32 (1/0)
ToySRAM 32x32 array test
0.00ns INFO [00000001] [00000001] Resetting...
9.00ns INFO [00000010] [00000010] Releasing reset.
25.00ns INFO [00000027] Initializing array...
25.00ns INFO [00000027] Port=0 WR @00=00555500
26.00ns INFO [00000028] Port=0 WR @01=01555501
27.00ns INFO [00000029] Port=0 WR @02=02555502
28.00ns INFO [00000030] Port=0 WR @03=03555503
29.00ns INFO [00000031] Port=0 WR @04=04555504
30.00ns INFO [00000032] Port=0 WR @05=05555505
31.00ns INFO [00000033] Port=0 WR @06=06555506
32.00ns INFO [00000034] Port=0 WR @07=07555507
33.00ns INFO [00000035] Port=0 WR @08=08555508
...
10037.50ns INFO [00010039] Port=0 WR @12=6C6FD11E
10038.50ns INFO [00010040] Port=0 WR @17=545B517F
10039.50ns INFO [00010041] Port=0 RD @08
10039.50ns INFO [00010041] Port=1 RD @0E
10041.50ns INFO [00010043] * RD COMPARE * port=0 adr=08 act=BE99B13E exp=BE99B13E
10041.50ns INFO [00010043] * RD COMPARE * port=1 adr=0E act=97A2D496 exp=97A2D496
10041.50ns INFO [00010043] Port=0 WR @1A=76434F37
10041.50ns INFO [00010043] Port=1 RD @0D
10042.50ns INFO [00010044] Port=0 WR @12=069ECCCE
10042.50ns INFO [00010044] Port=0 RD @13
10043.50ns INFO [00010045] * RD COMPARE * port=1 adr=0D act=C1C0D7D8 exp=C1C0D7D8
10043.50ns INFO [00010045] Port=0 WR @05=58E318E7
10043.50ns INFO [00010045] Port=0 RD @10
10043.50ns INFO [00010045] Port=1 RD @00
10044.50ns INFO [00010046] * RD COMPARE * port=0 adr=13 act=1D975E90 exp=1D975E90
10044.50ns INFO [00010046] Port=0 RD @14
10044.50ns INFO [00010046] Port=1 RD @1D
10045.50ns INFO [00010047] * RD COMPARE * port=0 adr=10 act=F82AB140 exp=F82AB140
10045.50ns INFO [00010047] * RD COMPARE * port=1 adr=00 act=3C2E724D exp=3C2E724D
10046.50ns INFO [00010048] * RD COMPARE * port=0 adr=14 act=1A27AA07 exp=1A27AA07
10046.50ns INFO [00010048] * RD COMPARE * port=1 adr=1D act=5B9AE71C exp=5B9AE71C
10047.50ns INFO [00010049] Quiescing...
10057.00ns INFO [00010059] Done.
10057.00ns INFO [00010059] Final State

Reads Port 0: 4005
Reads Port 1: 4052
Writes Port 0: 4055
10057.00ns INFO [00010059] [00010059] You has opulence.
10057.00ns INFO tb_32x32 passed
10057.00ns INFO **************************************************************************************
** TEST STATUS SIM TIME (ns) REAL TIME (s) RATIO (ns/s) **
**************************************************************************************
** tb.tb_32x32 PASS 10057.00 8.54 1177.70 **
**************************************************************************************
** TESTS=0 PASS=1 FAIL=0 SKIP=0 10057.00 8.56 1174.42 **
**************************************************************************************

VCD info: dumpfile test_ra_sdr_32x32.vcd opened for output.
VCD warning: $dumpvars: Package ($unit) is not dumpable with VCD.
make[1]: Leaving directory '/media/wtf/WD_USBC_4T/projects/toy-sram/rtl/sim/coco'
vcd2fst test_ra_sdr_32x32.vcd test_ra_sdr_32x32.fst
#rm test_ra_sdr_32x32.vcd

```

```
gtkwave test_ra_sdr_32x32.fst wtf_test_ra_sdr_32x32.gtkw
```

## Test Site

* compile and run

```
make -f Makefile_site build

```

* just run (tb.py changes, etc.)

```
make -f Makefile_site run

```

* results

```
0.00ns INFO Running on Icarus Verilog version 12.0 (devel)
0.00ns INFO Running tests with cocotb v1.7.0.dev0 from /home/wtf/.local/lib/python3.8/site-packages/cocotb
0.00ns INFO Seeding Python random module with 1655136638
0.00ns INFO Found test tb.tb_site
0.00ns INFO running tb_site (1/0)
ToySRAM site test
VCD info: dumpfile test_site.vcd opened for output.
VCD warning: $dumpvars: Package ($unit) is not dumpable with VCD.
0.00ns INFO [00000001] Resetting...
9.00ns INFO [00000010] Releasing reset.
15.00ns INFO [00000017] Writing Port 0 @00100000 00=633212F3
17.00ns INFO [00000019] Reading Port 0 @00100000 00
22.00ns INFO [00000024] Read Data: 633212F3
22.00ns INFO [00000024] Writing Port 0 @00100001 01=6A0278C9
24.00ns INFO [00000026] Reading Port 0 @00100001 01
29.00ns INFO [00000031] Read Data: 6A0278C9
...
1769.00ns INFO [00001770] Writing W0@15=08675309...
1769.00ns INFO [00001770] Scanning in...
1798.00ns INFO [00001800] ...tick...
1898.00ns INFO [00001900] ...tick...
1998.00ns INFO [00002000] ...tick...
2075.00ns INFO [00002076] Blipping RA0 clk...
2098.00ns INFO [00002100] ...tick...
2175.00ns INFO [00002176] Reading R0@15, R1@16...
2175.00ns INFO [00002176] Scanning in...
2198.00ns INFO [00002200] ...tick...
2298.00ns INFO [00002300] ...tick...
2398.00ns INFO [00002400] ...tick...
2481.00ns INFO [00002482] Blipping RA0 clk...
2498.00ns INFO [00002500] ...tick...
2581.00ns INFO [00002582] Blipping RA0 clk...
2598.00ns INFO [00002600] ...tick...
2681.00ns INFO [00002682] Blipping RA0 clk...
2698.00ns INFO [00002700] ...tick...
2781.00ns INFO [00002782] Scanning out...
2798.00ns INFO [00002800] ...tick...
2898.00ns INFO [00002900] ...tick...
2998.00ns INFO [00003000] ...tick...
3035.00ns INFO [00003036] ScanData=78433A984C075227A100000000000000
3035.00ns INFO [00003036] r0 adr:0F
3035.00ns INFO [00003036] r0 dat:08675309
3035.00ns INFO [00003036] r1 adr:10
3035.00ns INFO [00003036] r1 dat:1D489E84
3035.00ns INFO [00003036] w0 adr:00
3035.00ns INFO [00003036] w0 dat:00000000
3035.00ns INFO [00003036] cfg:00000
3035.00ns INFO [00003036] Done
3044.00ns INFO tb_site passed
3044.00ns INFO **************************************************************************************
** TEST STATUS SIM TIME (ns) REAL TIME (s) RATIO (ns/s) **
**************************************************************************************
** tb.tb_site PASS 3044.00 0.87 3517.25 **
**************************************************************************************
** TESTS=0 PASS=1 FAIL=0 SKIP=0 3044.00 0.89 3420.87 **
**************************************************************************************
```

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1 @@
../../src/array

File diff suppressed because it is too large Load Diff

@ -0,0 +1,148 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.


// Test array (SDR) wrapper for cocotb/icarus
// 32 word 32 bit array
// LCB for strobe generation
// Config, BIST, etc.

`timescale 1 ns / 1 ns

`include "toysram.vh"

module test_ra_sdr_32x32 (

clk,
reset,
cfg_wr,
cfg_dat,
bist_ctl,
bist_status,

rd_enb_0,
rd_adr_0,
rd_dat_0,

rd_enb_1,
rd_adr_1,
rd_dat_1,

wr_enb_0,
wr_adr_0,
wr_dat_0

);

input clk;
input reset;
input cfg_wr;
input [0:`LCBSDR_CONFIGWIDTH-1] cfg_dat;
input [0:31] bist_ctl;
output [0:31] bist_status;
input rd_enb_0;
input [0:4] rd_adr_0;
output [0:31] rd_dat_0;
input rd_enb_1;
input [0:4] rd_adr_1;
output [0:31] rd_dat_1;
input wr_enb_0;
input [0:4] wr_adr_0;
input [0:31] wr_dat_0;

wire strobe;
wire [0:`LCBSDR_CONFIGWIDTH-1] cfg;
wire mux_rd0_enb;
wire [0:4] mux_rd0_adr;
wire mux_rd1_enb;
wire [0:4] mux_rd1_adr;
wire mux_wr0_enb;
wire [0:4] mux_wr0_adr;
wire [0:31] mux_wr0_dat;


initial begin
$dumpfile ("test_ra_sdr_32x32.vcd");
$dumpvars;
#1;
end

ra_lcb_sdr lcb (

.clk (clk),
.reset (reset),
.cfg (cfg),
.strobe (strobe)

);

ra_cfg_sdr #(.INIT(-1)) cfig (

.clk (clk),
.reset (reset),
.cfg_wr (cfg_wr),
.cfg_dat (cfg_dat),
.cfg (cfg)

);

ra_bist_sdr_32x32 bist (

.clk (clk),
.reset (reset),
.ctl (bist_ctl),
.status (bist_status),
.rd0_enb_in (rd_enb_0),
.rd0_adr_in (rd_adr_0),
.rd0_dat (rd_dat_0),
.rd1_enb_in (rd_enb_1),
.rd1_adr_in (rd_adr_1),
.rd1_dat (rd_dat_1),
.wr0_enb_in (wr_enb_0),
.wr0_adr_in (wr_adr_0),
.wr0_dat_in (wr_dat_0),
.rd0_enb_out (mux_rd0_enb),
.rd0_adr_out (mux_rd0_adr),
.rd1_enb_out (mux_rd1_enb),
.rd1_adr_out (mux_rd1_adr),
.wr0_enb_out (mux_wr0_enb),
.wr0_adr_out (mux_wr0_adr),
.wr0_dat_out (mux_wr0_dat)

);

ra_2r1w_32x32_sdr ra (

.clk (clk),
.reset (reset),
.strobe (strobe),
.rd_enb_0 (mux_rd0_enb),
.rd_adr_0 (mux_rd0_adr),
.rd_dat_0 (rd_dat_0),
.rd_enb_1 (mux_rd1_enb),
.rd_adr_1 (mux_rd1_adr),
.rd_dat_1 (rd_dat_1),
.wr_enb_0 (mux_wr0_enb),
.wr_adr_0 (mux_wr0_adr),
.wr_dat_0 (mux_wr0_dat)

);

endmodule

File diff suppressed because it is too large Load Diff

@ -0,0 +1,148 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.


// Test array (SDR) wrapper for cocotb/icarus
// 64 word 72 bit array
// LCB for strobe generation
// Config, BIST, etc.

`timescale 1 ns / 1 ns

`include "toysram.vh"

module test_ra_sdr_64x72 (

clk,
reset,
cfg_wr,
cfg_dat,
bist_ctl,
bist_status,

rd_enb_0,
rd_adr_0,
rd_dat_0,

rd_enb_1,
rd_adr_1,
rd_dat_1,

wr_enb_0,
wr_adr_0,
wr_dat_0

);

input clk;
input reset;
input cfg_wr;
input [0:`LCBSDR_CONFIGWIDTH-1] cfg_dat;
input [0:31] bist_ctl;
output [0:31] bist_status;
input rd_enb_0;
input [0:5] rd_adr_0;
output [0:71] rd_dat_0;
input rd_enb_1;
input [0:5] rd_adr_1;
output [0:71] rd_dat_1;
input wr_enb_0;
input [0:5] wr_adr_0;
input [0:71] wr_dat_0;

wire strobe;
wire [0:`LCBSDR_CONFIGWIDTH-1] cfg;
wire mux_rd0_enb;
wire [0:5] mux_rd0_adr;
wire mux_rd1_enb;
wire [0:5] mux_rd1_adr;
wire mux_wr0_enb;
wire [0:5] mux_wr0_adr;
wire [0:71] mux_wr0_dat;


initial begin
$dumpfile ("test_ra_sdr_64x72.vcd");
$dumpvars;
#1;
end

ra_lcb_sdr lcb (

.clk (clk),
.reset (reset),
.cfg (cfg),
.strobe (strobe)

);

ra_cfg_sdr #(.INIT(-1)) cfig (

.clk (clk),
.reset (reset),
.cfg_wr (cfg_wr),
.cfg_dat (cfg_dat),
.cfg (cfg)

);

ra_bist_sdr bist (

.clk (clk),
.reset (reset),
.ctl (bist_ctl),
.status (bist_status),
.rd0_enb_in (rd_enb_0),
.rd0_adr_in (rd_adr_0),
.rd0_dat (rd_dat_0),
.rd1_enb_in (rd_enb_1),
.rd1_adr_in (rd_adr_1),
.rd1_dat (rd_dat_1),
.wr0_enb_in (wr_enb_0),
.wr0_adr_in (wr_adr_0),
.wr0_dat_in (wr_dat_0),
.rd0_enb_out (mux_rd0_enb),
.rd0_adr_out (mux_rd0_adr),
.rd1_enb_out (mux_rd1_enb),
.rd1_adr_out (mux_rd1_adr),
.wr0_enb_out (mux_wr0_enb),
.wr0_adr_out (mux_wr0_adr),
.wr0_dat_out (mux_wr0_dat)

);

ra_2r1w_64x72_sdr ra (

.clk (clk),
.reset (reset),
.strobe (strobe),
.rd_enb_0 (mux_rd0_enb),
.rd_adr_0 (mux_rd0_adr),
.rd_dat_0 (rd_dat_0),
.rd_enb_1 (mux_rd1_enb),
.rd_adr_1 (mux_rd1_adr),
.rd_dat_1 (rd_dat_1),
.wr_enb_0 (mux_wr0_enb),
.wr_adr_0 (mux_wr0_adr),
.wr_dat_0 (mux_wr0_dat)

);

endmodule

Binary file not shown.

@ -0,0 +1,106 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.


// Test array (SDR) wrapper for cocotb/icarus
// 32 word 32 bit array
// LCB for strobe generation
// Config, BIST, etc.

`timescale 1 ns / 1 ns

`include "defines.v"
`include "toysram.vh"

module test_site (

`ifdef USE_POWER_PINS
inout vccd1, // User area 1 1.8V supply
inout vssd1, // User area 1 digital ground
`endif

// Wishbone Slave ports (WB MI A)
input wb_clk_i,
input wb_rst_i,
input wbs_stb_i,
input wbs_cyc_i,
input wbs_we_i,
input [3:0] wbs_sel_i,
input [31:0] wbs_dat_i,
input [31:0] wbs_adr_i,
output wbs_ack_o,
output [31:0] wbs_dat_o,

// Logic Analyzer Signals
input [127:0] la_data_in,
output [127:0] la_data_out,
input [127:0] la_oenb,

// IOs
input [`MPRJ_IO_PADS-1:0] io_in,
output [`MPRJ_IO_PADS-1:0] io_out,
output [`MPRJ_IO_PADS-1:0] io_oeb,

// IRQ
output [2:0] irq

);

initial begin
$dumpfile ("test_site.vcd");
$dumpvars;
#1;
end

toysram_site site (

`ifdef USE_POWER_PINS
.vccd1(vccd1),
.vssd1(vssd1),
`endif
.wb_clk_i(wb_clk_i),
.wb_rst_i(wb_rst_i),
.wbs_stb_i(wbs_stb_i),
.wbs_cyc_i(wbs_cyc_i),
.wbs_we_i(wbs_we_i),
.wbs_sel_i(wbs_sel_i),
.wbs_dat_i(wbs_dat_i),
.wbs_adr_i(wbs_adr_i),
.wbs_ack_o(wbs_ack_o),
.wbs_dat_o(wbs_dat_o),

// Logic Analyzer Signals
.la_data_in(la_data_in),
.la_data_out(la_data_out),
.la_oenb(la_oenb),


// IOs
.io_in(io_in),
.io_out(io_out),
.io_oeb(io_oeb),

// IRQ
.irq(irq)

);


endmodule

@ -0,0 +1,65 @@
[*]
[*] GTKWave Analyzer v3.4.0 (w)1999-2022 BSI
[*] Wed Jun 8 15:39:53 2022
[*]
[dumpfile] "/media/wtf/WD_USBC_4T/projects/toy-sram/rtl/sim/coco/test_ra_sdr_32x32.fst"
[dumpfile_mtime] "Wed Jun 8 15:03:44 2022"
[dumpfile_size] 4425
[savefile] "/media/wtf/WD_USBC_4T/projects/toy-sram/rtl/sim/coco/wtf_test_ra_sdr_32x32.gtkw"
[timestart] 19240
[size] 2088 1240
[pos] 218 58
*-12.000000 30000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] test_ra_sdr_32x32.
[treeopen] test_ra_sdr_32x32.ra.
[treeopen] test_ra_sdr_32x32.ra.array0.
[sst_width] 282
[signals_width] 312
[sst_expanded] 1
[sst_vpaned_height] 370
@28
test_ra_sdr_32x32.clk
@200
-WR 0
@28
test_ra_sdr_32x32.wr_enb_0
@22
test_ra_sdr_32x32.wr_adr_0[0:4]
test_ra_sdr_32x32.wr_dat_0[0:31]
@200
-RD 0
@28
test_ra_sdr_32x32.rd_enb_0
@22
test_ra_sdr_32x32.rd_adr_0[0:4]
test_ra_sdr_32x32.rd_dat_0[0:31]
@200
-RD 1
@28
test_ra_sdr_32x32.rd_enb_1
@22
test_ra_sdr_32x32.rd_adr_1[0:4]
test_ra_sdr_32x32.rd_dat_1[0:31]
@200
-RA
-RA[0]
@22
test_ra_sdr_32x32.ra.array0.ra[0].q[0:31]
test_ra_sdr_32x32.ra.array0.ra[1].q[0:31]
test_ra_sdr_32x32.ra.array0.ra[2].q[0:31]
test_ra_sdr_32x32.ra.array0.ra[3].q[0:31]
test_ra_sdr_32x32.ra.array0.ra[4].q[0:31]
test_ra_sdr_32x32.ra.array0.ra[5].q[0:31]
test_ra_sdr_32x32.ra.array0.ra[6].q[0:31]
@23
test_ra_sdr_32x32.ra.array0.ra[7].q[0:31]
@28
test_ra_sdr_32x32.ra.array0.wr0_a0
test_ra_sdr_32x32.ra.array0.wr0_a1
test_ra_sdr_32x32.ra.array0.wr0_a1_a2
test_ra_sdr_32x32.ra.array0.wr0_a1_na2
test_ra_sdr_32x32.ra.array0.wr0_a2
test_ra_sdr_32x32.ra.array0.wr0_a3
test_ra_sdr_32x32.ra.array0.wr0_a4
[pattern_trace] 1
[pattern_trace] 0

@ -0,0 +1,68 @@
[*]
[*] GTKWave Analyzer v3.4.0 (w)1999-2022 BSI
[*] Thu May 26 19:05:29 2022
[*]
[dumpfile] "/home/wtf/projects/toysram-opf/rtl/sim/coco/test_ra_sdr_64x72.fst"
[dumpfile_mtime] "Thu May 26 18:50:01 2022"
[dumpfile_size] 12003
[savefile] "/home/wtf/projects/toysram-opf/rtl/sim/coco/wtf_test_ra_sdr_64x72.gtkw"
[timestart] 89538
[size] 2088 1240
[pos] 218 58
*-10.000000 94187 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] test_ra_sdr_64x72.
[treeopen] test_ra_sdr_64x72.ra.
[treeopen] test_ra_sdr_64x72.ra.array2.
[sst_width] 282
[signals_width] 312
[sst_expanded] 1
[sst_vpaned_height] 370
@28
test_ra_sdr_64x72.clk
test_ra_sdr_64x72.reset
@200
-WR 0
@29
test_ra_sdr_64x72.wr_enb_0
@22
test_ra_sdr_64x72.wr_adr_0[0:5]
test_ra_sdr_64x72.wr_dat_0[0:71]
@200
-RD 0
@28
test_ra_sdr_64x72.rd_enb_0
@22
test_ra_sdr_64x72.rd_adr_0[0:5]
test_ra_sdr_64x72.rd_dat_0[0:71]
@200
-RD 1
@28
test_ra_sdr_64x72.rd_enb_1
@22
test_ra_sdr_64x72.rd_adr_1[0:5]
test_ra_sdr_64x72.rd_dat_1[0:71]
@200
-RA
@28
test_ra_sdr_64x72.ra.rd_enb_0_q
@22
test_ra_sdr_64x72.ra.rd_adr_0_q[0:5]
test_ra_sdr_64x72.ra.rd_dat_0_q[0:71]
@28
test_ra_sdr_64x72.ra.rd_enb_1_q
@22
test_ra_sdr_64x72.ra.rd_adr_1_q[0:5]
test_ra_sdr_64x72.ra.rd_dat_1_q[0:71]
@28
test_ra_sdr_64x72.ra.wr_enb_0_q
@22
test_ra_sdr_64x72.ra.wr_adr_0_q[0:5]
test_ra_sdr_64x72.ra.wr_dat_0_q[0:71]
@200
-RA[0]
@22
test_ra_sdr_64x72.ra.array0.ra[0].q[0:23]
test_ra_sdr_64x72.ra.array1.ra[0].q[0:23]
test_ra_sdr_64x72.ra.array2.ra[0].q[0:23]
[pattern_trace] 1
[pattern_trace] 0

@ -0,0 +1,138 @@
[*]
[*] GTKWave Analyzer v3.4.0 (w)1999-2022 BSI
[*] Mon Jun 13 17:02:24 2022
[*]
[dumpfile] "/media/wtf/WD_USBC_4T/projects/toy-sram/rtl/sim/coco/test_site.fst"
[dumpfile_mtime] "Mon Jun 13 16:51:29 2022"
[dumpfile_size] 408816
[savefile] "/media/wtf/WD_USBC_4T/projects/toy-sram/rtl/sim/coco/wtf_test_site.gtkw"
[timestart] 2034000
[size] 2048 1078
[pos] 206 125
*-18.000000 3035000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] test_site.
[treeopen] test_site.site.
[treeopen] test_site.site.ra_0.
[treeopen] test_site.site.ra_0.ra.
[sst_width] 204
[signals_width] 265
[sst_expanded] 1
[sst_vpaned_height] 314
@28
test_site.wb_clk_i
test_site.wb_rst_i
test_site.wbs_cyc_i
test_site.wbs_stb_i
test_site.wbs_we_i
@22
test_site.wbs_adr_i[31:0]
test_site.wbs_sel_i[3:0]
test_site.wbs_dat_i[31:0]
@28
test_site.wbs_ack_o
@22
test_site.wbs_dat_o[31:0]
test_site.la_data_in[127:0]
test_site.la_data_out[127:0]
test_site.la_oenb[127:0]
test_site.io_in[37:0]
test_site.io_oeb[37:0]
test_site.io_out[37:0]
@28
test_site.irq[2:0]
@200
-WB SLAVE
@22
test_site.site.wb.rd_dat[31:0]
@28
test_site.site.wb.rd_ack_q
@22
test_site.site.wb.rd_dat_q[31:0]
@200
-CFG
@22
test_site.site.cfg.cfg0_q[31:0]
@28
test_site.site.cfg.wb_cmd_val
test_site.site.cfg.cfg_cmd_val
test_site.site.cfg.ctl_cmd_val
test_site.site.cfg.ra0_cmd_val
@22
test_site.site.cfg.cmd_adr[31:0]
@28
test_site.site.cfg.cmd_we
@22
test_site.site.cfg.cmd_sel[3:0]
test_site.site.cfg.cmd_dat[31:0]
@200
-CTL
@22
test_site.site.ctl.io_in[37:0]
test_site.site.ctl.io_out[37:0]
test_site.site.ctl.io_oeb[37:0]
test_site.site.cfg.cfg0_q[31:0]
test_site.site.ctl.seq_q[4:0]
@28
test_site.site.ctl.ctl_cmd_val
test_site.site.ctl.ra0_cmd_val
test_site.site.ctl.adr_bist
test_site.site.ctl.adr_config
@22
test_site.site.ctl.cmd_adr[31:0]
@28
test_site.site.ctl.cmd_we
@22
test_site.site.ctl.cmd_sel[3:0]
test_site.site.ctl.cmd_dat[31:0]
@28
test_site.site.ctl.rd_ack
test_site.site.ctl.rdata_sel[2:0]
@22
test_site.site.ctl.rd_dat[31:0]
@28
test_site.site.ctl.ra0_r0_enb
@22
test_site.site.ctl.ra0_r0_adr[4:0]
test_site.site.ctl.ra0_r0_dat[31:0]
@28
test_site.site.ctl.ra0_r1_enb
@22
test_site.site.ctl.ra0_r1_adr[4:0]
test_site.site.ctl.ra0_r1_dat[31:0]
@28
test_site.site.ctl.ra0_w0_enb
@22
test_site.site.ctl.ra0_w0_adr[4:0]
test_site.site.ctl.ra0_w0_dat[31:0]
@28
test_site.site.ctl.test_enable
@22
test_site.site.ctl.scan_reg_q[127:0]
@28
test_site.site.ctl.scan_clk
@22
test_site.site.ctl.scan_config[16:0]
@28
test_site.site.ctl.scan_di
test_site.site.ctl.scan_do
test_site.site.ctl.io_ra0_clk
test_site.site.ctl.io_ra0_rst
@200
-RA0
@28
test_site.site.ra_0.clk
test_site.site.ra_0.ra.wr_enb_0_q
@22
test_site.site.ra_0.ra.wr_adr_0_q[0:4]
test_site.site.ra_0.ra.wr_dat_0_q[0:31]
@28
test_site.site.ra_0.ra.rd_enb_0_q
@22
test_site.site.ra_0.ra.rd_dat_0_q[0:31]
@28
test_site.site.ra_0.ra.rd_enb_1_q
@22
test_site.site.ra_0.ra.rd_dat_1_q[0:31]
test_site.site.ra_0.ra.array0.ra[0].q[0:31]
[pattern_trace] 1
[pattern_trace] 0

File diff suppressed because it is too large Load Diff

@ -0,0 +1,113 @@
# Utilities

import random

# printing

me = ' pys--. '
quiet = False
getSimTime = None

def msg(text='', lvl=0, name=None, init=None):
global me, quiet, getSimTime

if init is not None:
getSimTime = init
return

if quiet and lvl != 0:
return

if name is None:
name = me
if getSimTime is not None:
t,c = getSimTime()
else:
t,c = (0,0)
s = f'{t:08d}[{c:08d}] {name:>8}: '
pad = ' ' * len(s)

text = text + '\n'
lines = text.splitlines()
s = s + lines[0] + '\n'
for i in range(1, len(lines)):
s = s + pad
s = s + lines[i] + '\n'
print(s[0:-1])

# randoms

def intrandom(n):
return random.randint(0, n-1)

def hexrandom(w=16):
n = random.getrandbits(w*4)
return '{0:0{l}X}'.format(n, l=w)

def binrandom(w=32):
n = random.getrandbits(w)
return '{0:0>{l}b}'.format(n, l=w)

def randOK(freq):
v = random.randint(1,100) # 1 <= v <= 100
if freq == 0:
return False
else:
return v <= freq

# weights is either
# a simple list: return weighted index
# a list of tuple(val, weight): return weighted val
def randweighted(weights):

if len(weights) == 0:
return 0

if type(weights[0]) is tuple:
vals = []
tWeights = []
for i in range (0, len(weights)):
vals.append(weights[i][0])
tWeights.append(weights[i][1])
weights = tWeights
else:
vals = range(0, len(weights))

sum = 0
for i in range(0, len(weights)):
sum = sum + weights[i]
v = random.randint(0,sum-1)
weight = 0
for i in range(0, len(weights)):
weight = weight + weights[i]
if v < weight:
break

return vals[i]

# converters

def b2x(b, w=None):
if w is None:
rem = len(b) % 4
w = len(b)/4
if rem != 0:
w = w + 1
return '{0:0{l}X}'.format(int(b,2), l=w)

def x2b(x, w=None):
i = int(str(x),16)
if w is None:
return bin(i)[2:]
else:
return '{0:0>{l}s}'.format(bin(i)[2:], l=w)

def d2x(x, w=None):
#return hex(int(x)).split('x')[-1].upper()
if w is None:
return '{0:X}'.format(x)
else:
return '{0:0{l}X}'.format(x, l=w)

def x2d(i):
return int(i, 16)

@ -0,0 +1 @@
/home/wtf/projects/pyverilator_no_uart/pyverilator

@ -0,0 +1,444 @@
#!/usr/bin/python3

# pyverilator
# fixed internal sig parsing (cdata/wdata)
# 1. this should be based on init setting AND should be done even w/o trace on!!!
# in add_to_vcd_trace(self), time is bumped +5
# 2. should count cycs
# 3. add parm so clock can be set but NOT eval (for multiclock, only fastest evals)
# 4. how to access mem[][]??
# 5. not adding vectors to gtk - cuz 0:n?

import os, sys
import datetime
from optparse import OptionParser
from optparse import OptionGroup

import random
from random import randint

from pysutils import *

user = os.environ['USER']
binPath = os.path.dirname(os.path.realpath(__file__))

localPV = True
if localPV:
import os, sys
sys.path.append(os.path.join(binPath, 'pyverilator'))
import pyverilator

####################################################################
# Defaults

rtl = ['src']
model = 'sdr'

stopOnFail = True
verbose = False
vcd = False
seed = randint(1, int('8675309', 16))
runCycs = 100

#rangesRd = [(0,63), (0,63), (0,63), (0,63)]
rangesRd = [(0,7), (0,7), (0,7), (0,7)]
#rangesWr = [(0,63), (0,63)]
rangesWr = [(0,7), (0,7)]


####################################################################
# Process command line

usage = "Usage: %prog [options]"
parser = OptionParser(usage)

parser.add_option('-m', '--model', dest='model', help=f'sdr or ddr')
parser.add_option('-s', '--seed', dest='seed', help=f'initialize seed to n')
parser.add_option('-c', '--cycles', dest='runCycs', help=f'cycles to run, default={runCycs}')

parser.add_option('-t', '--trace', dest='trace', action='store_true', help=f'create wave file')
parser.add_option('-f', '--stopfail', dest='stopOnFail', action='store_true', help=f'stop on first fail')

parser.add_option('-v', '--verbose', dest='verbose', action='store_true', help=f'noisy output')

options, args = parser.parse_args()

if options.model is not None:
model = options.model

if options.seed is not None:
seed = int(options.seed)

if options.runCycs is not None:
runCycs = int(options.runCycs)

if options.trace is not None:
vcd = True

if options.stopOnFail is not None:
stopOnFail = True

if options.verbose is not None:
verbose = True

####################################################################
# Init

sdr = False
ddr = False
ddr1x = False

if model == 'sdr':
top = 'test_ra_sdr.v'
sdr = True
elif model == 'ddr1x':
top = 'test_ra_ddr_1x.v'
ddr = True
ddr1x = True
else:
top = 'test_ra_ddr.v'
ddr = True

errors = 0
cyc = 0
quiesceCyc = 5 # before end

# build model
sim = pyverilator.PyVerilator.build(top, verilog_path=rtl)
print('io')
print(sim.io)
print()

print('internals')
# issue #8 - try local fix
print(sim.internals)
print()

#print('ra')
#print(sim.internals.ra)
# array0,1,2 dont exist as submodules???
#print()
#
#print('ra.add_clk')
#print(sim.internals.ra.add_clk)
#print()

if vcd:
sim.start_gtkwave(auto_tracing=False)

#wtf vectors are failing
# will make this load a savefile anyway someday
# this doesn't actually restrict what's beign recorded anyway; still
# can load saved netlist after sim
#sim.send_to_gtkwave(sim.io)
#for s in sim.io:
# try:
# sim.send_to_gtkwave(sim.io[s])
# except:
# print(f'*** failed {s}')

####################################################################
# Functions, Classes

def getSimTime():
return (sim.curr_time, cyc)
msg(init=getSimTime)

# sim-driven signals don't look like _q since they are set after the eval(clk=1) tick
# would have to set after eval of rising edge but also not do a simtick
def tick():
sim.eval()
if vcd:
sim.add_to_vcd_trace()

def run(n=1, cb=None):
global cyc

if sdr or ddr1x:
for i in range(n):
sim.io.clk = 0
tick()
sim.io.clk = 1
tick()
elif ddr:
for i in range(n):
sim.io.clk = 0
sim.io.clk2x = 1
tick()
sim.io.clk2x = 0
tick()
sim.io.clk = 1
sim.io.clk2x = 1
tick()
sim.io.clk2x = 0
tick()

cyc += 1
if not vcd: # should be done by pyv!!!!
sim.curr_time = cyc * 10
if cb is not None:
(cb)()

def fail(t=None):
global errors, stopOnFail
msg('*** FAIL ***')
errors += 1
if t is not None:
msg(t)

class Memory:

def __init__(self, locs, bits, init=0):
self.mem = [init] * locs
self.bits = bits

def read(self, adr):
return self.mem[adr]

def readall(self):
mem = []
for i in range(len(self.mem)):
mem.append(self.mem[i])
return mem

def write(self, adr, dat):
self.mem[adr] = dat

def __str__(self):
t = ''
for i in range(0,len(self.mem),4):
t1 = f'[{i:02X}] {self.mem[i]:018X}'
for j in range(i+1, i+4):
t1 += f' [{j:02X}] {self.mem[j]:018X}'
#t1 += f' {self.mem[j]:018X}\n'
t += t1 + '\n'
return t

class Port:

def __init__(self, id, type='r'):
self.id = id
self.type = type

def read(self, adr):
sim.io[f'rd_enb_{self.id}'] = 1
sim.io[f'rd_adr_{self.id}'] = adr
msg(f'Port={self.id} RD @{adr:02X}')
def write(self, adr, dat):
sim.io[f'wr_enb_{self.id}'] = 1
sim.io[f'wr_adr_{self.id}'] = adr
sim.io[f'wr_dat_{self.id}'] = dat
msg(f'Port={self.id} WR @{adr:02X}={dat:02X}')

def data(self):
return int(sim.io[f'rd_dat_{self.id}'])

def idle(self):
if self.type == 'r':
sim.io[f'rd_enb_{self.id}'] = 0
sim.io[f'rd_adr_{self.id}'] = 0 # random
else:
sim.io[f'wr_enb_{self.id}'] = 0
sim.io[f'wr_adr_{self.id}'] = 0 # random
sim.io[f'wr_dat_{self.id}'] = 0 # random

def printstate():
mac = sim.internals.ra
if sdr:
msg(f'R0: {mac.rd_enb_0_q:01X} {mac.rd_adr_0_q:02X} {mac.rd_dat_0_q:018X} R1: {mac.rd_enb_1_q:01X} {mac.rd_adr_1_q:02X} {mac.rd_dat_1_q:018X}')
msg(f'W0: {mac.wr_enb_0_q:01X} {mac.wr_adr_0_q:02X} {mac.wr_dat_0_q:018X}')
else:
msg(f'R0: {mac.rd_enb_0_q:01X} {mac.rd_adr_0_q:02X} {mac.rd_dat_0_q:018X} R1: {mac.rd_enb_1_q:01X} {mac.rd_adr_1_q:02X} {mac.rd_dat_1_q:018X} R2: {mac.rd_enb_2_q:01X} {mac.rd_adr_2_q:02X} {mac.rd_dat_2_q:018X} R3: {mac.rd_enb_3_q:01X} {mac.rd_adr_3_q:02X} {mac.rd_dat_3_q:018X}')
msg(f'W0: {mac.wr_enb_0_q:01X} {mac.wr_adr_0_q:02X} {mac.wr_dat_0_q:018X} W1: {mac.wr_enb_1_q:01X} {mac.wr_adr_1_q:02X} {mac.wr_dat_1_q:018X}')

def printfinal():

print()
print()
print('Final State')
print(f'Model : {top}')
print()
print(data)
# should be checking actual mem[][] here, but can't access signals
print()
for i in range(len(portsRd)):
print(f'Reads Port {i}: {reads[i]}')
for i in range(len(portsWr)):
print(f'Writes Port {i}: {writes[i]}')
print()
print(f'Seed: {seed:08X}')
print(f'Cycles: {cyc}')
print(f'Errors: {errors}')

def check(port, adr, exp=None):

if exp is None:
exp = data.read(adr)
act = portsRd[port].data()
if act != exp:
fail(f'* RD MISCOMPARE * port={port} adr={adr:02X} act={act:018X} exp={exp:018X}')
return False
elif verbose:
msg(f'* RD COMPARE * port={port} adr={adr:02X} act={act:018X} exp={exp:018X}')
return True

####################################################################
# Do something

msg(f'Initializing seed to {hex(seed)}')

random.seed(seed)

data = Memory(64, 72)
if sdr:
portsRd = [Port(0, 'r'), Port(1, 'r')]
portsWr = [Port(0, 'w')]
else:
portsRd = [Port(0, 'r'), Port(1, 'r'), Port(2, 'r'), Port(3, 'r')]
portsWr = [Port(0, 'w'), Port(1, 'w')]

# Array Cycle Timings
#
# write
# | e/a/d | acc | valid |
# * latched by wrapper (in)
#
#
# read
# | e/a | acc | valid |
# * latched by wrapper (in)
# * latched by wrapper (out)
#
# rd(a) = wr(a) (both enabled):


# reset
sim.io.reset = 1
run(1)
sim.io.reset = 0

# idle
for p in portsRd:
p.idle()
for p in portsWr:
p.idle()

run(10)

# init array
if sdr:
for a in range(0, 64, 1):
d0 = int(f'5555555555555555{a:02X}', 16)
portsWr[0].write(a, d0)
run(1, printstate)
data.write(a, d0) # now visible for reads
portsWr[0].idle()
else:
for a in range(0, 64, 2):
d0 = int(f'5555555555555555{a:02X}', 16)
portsWr[0].write(a, d0)
d1 = int(f'5555555555555555{a+1:02X}', 16)
portsWr[1].write(a+1, d1)
run(1, printstate)
data.write(a, d0) # now visible for reads
data.write(a+1, d1) # now visible for reads
portsWr[0].idle()
portsWr[1].idle()

# random cmds
# writes: visible to all reads in cycle n+1,...
# reads: check in cycle n+2 vs mem data in cycle n+1
#
# every cycle:
# save data state
# pick weighted read0, read1, read2, read3, write0, write1 (cmd freq, adr) and ensure no adr coll if req'd
# schedule data change (write)
# schedule checks (read)

updates = []
checks = []
reads = [0, 0, 0, 0]
writes = [0, 0]
saveData = None
quiesced = False
quiesceCyc = cyc + runCycs - quiesceCyc

#d = int('1000', 16)
msg('Starting random loop.')
for c in range(runCycs):

ok = True

# check reads
checksNext = []
for i in range(len(checks)):
rd = checks[i]
if cyc == rd[0]:
ok = ok and check(rd[1], rd[2], saveData[rd[2]])
else:
checksNext.append(rd)
checks = checksNext

# do writes
updatesNext = [] # always only 1 cycle
for i in range(len(updates)):
wr = updates[i]
if cyc == wr[0]:
data.write(wr[2], wr[3])
else:
print('HUH? should always be this cycle!', cyc, updates)
quit()
updates = updatesNext

# save current data
saveData = data.readall()

# quiesce?
if cyc >= quiesceCyc:
if not quiesced:
msg('Quiescing...')
quiesced = True

# write coll will give w1 precedence - or make it avoid
aw = [None] * 2
for i in range(len(portsWr)):
portsWr[i].idle()
aw[i] = -1
if not quiesced and randint(1, 10) < 5:
r = rangesWr[i]
aw[i] = randint(r[0], r[1])
d = int(hexrandom(18), 16)
portsWr[i].write(aw[i], d)
updates.append((cyc+1, i, aw[i], d))
writes[i] += 1

for i in range(len(portsRd)):
portsRd[i].idle()
if not quiesced and randint(1, 10) < 5:
r = rangesRd[i]
ar = randint(r[0], r[1])
while ar == aw[0] or ar == aw[1]:
ar = randint(r[0], r[1])
portsRd[i].read(ar)
checks.append((cyc+2, i, ar))
reads[i] += 1

run(1, printstate)
if not ok and stopOnFail:
break

####################################################################
# Clean up

printfinal()

if ok and errors == 0:
print()
print('You has opulence.')
print()
else:
print()
print('You are worthless and weak!')
print()

print('Done.')

@ -0,0 +1,22 @@
# Functional verification of array and site logic

### CURRENT (cocotb+iverilog)

* using cocotb instead of pyverilator [cocotb sim](./coco)


### OLD (pyverilator)

## check rtl

```
verilator --lint-only -Isrc -Wno-LITENDIAN src/test_ra_sdr.v
```

### build/sim

***not working at all with verilator v4.210***

```
sim -m sdr -c 1000 -t
```

@ -0,0 +1 @@
python/sim.py

File diff suppressed because it is too large Load Diff

@ -0,0 +1 @@
../src/verilog/array

@ -0,0 +1,64 @@
[*]
[*] GTKWave Analyzer v3.3.103 (w)1999-2019 BSI
[*] Tue Aug 17 12:25:53 2021
[*]
[dumpfile] "/home/wtf/projects/Skywater-Array-Site/opf-move/dev/sim/gtkwave.vcd"
[dumpfile_mtime] "Tue Aug 17 12:19:36 2021"
[dumpfile_size] 49576
[savefile] "/home/wtf/projects/Skywater-Array-Site/opf-move/dev/sim/wtf.gtkw"
[timestart] 1484
[size] 1416 1043
[pos] 30 53
*-5.931902 455 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] TOP.
[treeopen] TOP.test_ra_ddr.
[treeopen] TOP.test_ra_ddr.ra.
[sst_width] 236
[signals_width] 185
[sst_expanded] 1
[sst_vpaned_height] 252
@28
TOP.test_ra_ddr.clk
TOP.test_ra_ddr.clk2x
TOP.test_ra_ddr.reset
TOP.test_ra_ddr.cfg_wr
TOP.test_ra_ddr.rd_enb_0
TOP.test_ra_ddr.rd_enb_1
TOP.test_ra_ddr.rd_enb_2
TOP.test_ra_ddr.rd_enb_3
TOP.test_ra_ddr.wr_enb_0
TOP.test_ra_ddr.wr_enb_1
@200
-RA FF
@28
TOP.test_ra_ddr.ra.rd_enb_0_q
@22
TOP.test_ra_ddr.ra.rd_adr_0_q[0:5]
TOP.test_ra_ddr.ra.rd_dat_0_q[0:71]
@28
TOP.test_ra_ddr.ra.rd_enb_1_q
@22
TOP.test_ra_ddr.ra.rd_adr_1_q[0:5]
TOP.test_ra_ddr.ra.rd_dat_1_q[0:71]
@28
TOP.test_ra_ddr.ra.rd_enb_2_q
@22
TOP.test_ra_ddr.ra.rd_adr_2_q[0:5]
TOP.test_ra_ddr.ra.rd_dat_2_q[0:71]
@28
TOP.test_ra_ddr.ra.rd_enb_3_q
@22
TOP.test_ra_ddr.ra.rd_adr_3_q[0:5]
TOP.test_ra_ddr.ra.rd_dat_3_q[0:71]
@28
TOP.test_ra_ddr.ra.wr_enb_0_q
@22
TOP.test_ra_ddr.ra.wr_adr_0_q[0:5]
TOP.test_ra_ddr.ra.wr_dat_0_q[0:71]
@28
TOP.test_ra_ddr.ra.wr_enb_1_q
@22
TOP.test_ra_ddr.ra.wr_adr_1_q[0:5]
TOP.test_ra_ddr.ra.wr_dat_1_q[0:71]
[pattern_trace] 1
[pattern_trace] 0

@ -0,0 +1,110 @@
[*]
[*] GTKWave Analyzer v3.3.103 (w)1999-2019 BSI
[*] Tue Aug 17 21:47:47 2021
[*]
[dumpfile] "/home/wtf/projects/Skywater-Array-Site/opf-move/dev/sim/gtkwave.vcd"
[dumpfile_mtime] "Tue Aug 17 21:22:27 2021"
[dumpfile_size] 57523
[savefile] "/home/wtf/projects/Skywater-Array-Site/opf-move/dev/sim/wtf_ddr.gtkw"
[timestart] 1663
[size] 1552 1029
[pos] 66 61
*-4.931902 1691 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] TOP.
[treeopen] TOP.test_ra_ddr.
[treeopen] TOP.test_ra_ddr.ra.
[sst_width] 236
[signals_width] 271
[sst_expanded] 1
[sst_vpaned_height] 561
@28
TOP.test_ra_ddr.clk
TOP.test_ra_ddr.clk2x
TOP.test_ra_ddr.reset
TOP.test_ra_ddr.rd_enb_0
@22
TOP.test_ra_ddr.rd_dat_0[0:71]
@28
TOP.test_ra_ddr.rd_enb_1
@22
TOP.test_ra_ddr.rd_dat_1[0:71]
@28
TOP.test_ra_ddr.rd_enb_2
@22
TOP.test_ra_ddr.rd_dat_2[0:71]
@28
TOP.test_ra_ddr.rd_enb_3
@22
TOP.test_ra_ddr.rd_dat_3[0:71]
@28
TOP.test_ra_ddr.wr_enb_0
TOP.test_ra_ddr.wr_enb_1
@200
-RA FF
@28
TOP.test_ra_ddr.ra.strobe
TOP.test_ra_ddr.ra.el_sel
TOP.test_ra_ddr.ra.rd_enb_0_q
@22
TOP.test_ra_ddr.ra.rd_adr_0_q[0:5]
TOP.test_ra_ddr.ra.rd_dat_0_q[0:71]
@28
TOP.test_ra_ddr.ra.rd_enb_1_q
@22
TOP.test_ra_ddr.ra.rd_adr_1_q[0:5]
TOP.test_ra_ddr.ra.rd_dat_1_q[0:71]
@28
TOP.test_ra_ddr.ra.rd_enb_2_q
@22
TOP.test_ra_ddr.ra.rd_adr_2_q[0:5]
TOP.test_ra_ddr.ra.rd_dat_2_q[0:71]
@28
TOP.test_ra_ddr.ra.rd_enb_3_q
@22
TOP.test_ra_ddr.ra.rd_adr_3_q[0:5]
TOP.test_ra_ddr.ra.rd_dat_3_q[0:71]
@28
TOP.test_ra_ddr.ra.wr_enb_0_q
@22
TOP.test_ra_ddr.ra.wr_adr_0_q[0:5]
TOP.test_ra_ddr.ra.wr_dat_0_q[0:71]
@28
TOP.test_ra_ddr.ra.wr_enb_1_q
@22
TOP.test_ra_ddr.ra.wr_adr_1_q[0:5]
TOP.test_ra_ddr.ra.wr_dat_1_q[0:71]
@28
TOP.test_ra_ddr.ra.rd_enb_01
@29
TOP.test_ra_ddr.ra.rd_enb_23
@200
-RA0
@28
TOP.test_ra_ddr.ra.array1.rd0_enable
@22
TOP.test_ra_ddr.ra.array1.rd_dat_0[0:23]
@28
TOP.test_ra_ddr.ra.array1.rd1_enable
@22
TOP.test_ra_ddr.ra.array1.rd_dat_1[0:23]
@28
TOP.test_ra_ddr.ra.array1.wr0_enable
@22
TOP.test_ra_ddr.ra.array1.wr_dat_0[0:23]
@200
-RA1
-RA2
@28
TOP.test_ra_ddr.ra.array2.rd0_enable
@22
TOP.test_ra_ddr.ra.array2.rd_dat_0[0:23]
@28
TOP.test_ra_ddr.ra.array2.rd1_enable
@22
TOP.test_ra_ddr.ra.array2.rd_dat_1[0:23]
@28
TOP.test_ra_ddr.ra.array2.wr0_enable
@22
TOP.test_ra_ddr.ra.array2.wr_dat_0[0:23]
[pattern_trace] 1
[pattern_trace] 0

@ -0,0 +1,189 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.


// Address and clocking synthesized logic for SDR 2r1w 32 word array
// Two modes:
// 1. nodelay: for sim, FPGA - clk (SDR) or clk2x (DDR) produce strobe
// 2. delay: for implementation, strobes are configured, and derived from clk

`timescale 1 ns / 1 ns

module address_clock_sdr_2r1w_32 (

strobe,

// address ports and associated enable signals
rd_enb_0,
rd_adr_0,
rd_enb_1,
rd_adr_1,
wr_enb_0,
wr_adr_0,

// predecoded address signal
// four groups of one hot encoded signals
// read address 0
rd0_c_na0,
rd0_c_a0,
rd0_na1_na2,
rd0_na1_a2,
rd0_a1_na2,
rd0_a1_a2,
rd0_na3,
rd0_a3,
rd0_na4,
rd0_a4,

// read address 1
rd1_c_na0,
rd1_c_a0,
rd1_na1_na2,
rd1_na1_a2,
rd1_a1_na2,
rd1_a1_a2,
rd1_na3,
rd1_a3,
rd1_na4,
rd1_a4,

// write address 0
wr0_c_na0,
wr0_c_a0,
wr0_na1_na2,
wr0_na1_a2,
wr0_a1_na2,
wr0_a1_a2,
wr0_na3,
wr0_a3,
wr0_na4,
wr0_a4

);

parameter GENMODE = 0; // 0=NoDelay, 1=Delay

input strobe;

// address ports and associated enable signals
input rd_enb_0;
input [0:4] rd_adr_0;
input rd_enb_1;
input [0:4] rd_adr_1;
input wr_enb_0;
input [0:4] wr_adr_0;

// predecoded address signal
// four groups of one hot encoded signals
// read address 0
output rd0_c_na0;
output rd0_c_a0;

output rd0_na1_na2;
output rd0_na1_a2;
output rd0_a1_na2;
output rd0_a1_a2;

output rd0_na3;
output rd0_a3;

output rd0_na4;
output rd0_a4;

// read address 1
output rd1_c_na0;
output rd1_c_a0;

output rd1_na1_na2;
output rd1_na1_a2;
output rd1_a1_na2;
output rd1_a1_a2;

output rd1_na3;
output rd1_a3;

output rd1_na4;
output rd1_a4;

// write address 0
output wr0_c_na0;
output wr0_c_a0;

output wr0_na1_na2;
output wr0_na1_a2;
output wr0_a1_na2;
output wr0_a1_a2;

output wr0_na3;
output wr0_a3;

output wr0_na4;
output wr0_a4;

// one predecoder per port

predecode_sdr_32 predecode_r0(
.strobe(strobe),
.enable(rd_enb_0),
.address(rd_adr_0),
.c_na0(rd0_c_na0),
.c_a0(rd0_c_a0),
.na1_na2(rd0_na1_na2),
.na1_a2(rd0_na1_a2),
.a1_na2(rd0_a1_na2),
.a1_a2(rd0_a1_a2),
.na3(rd0_na3),
.a3(rd0_a3),
.na4(rd0_na4),
.a4(rd0_a4)
);

predecode_sdr_32 predecode_r1(
.strobe(strobe),
.enable(rd_enb_1),
.address(rd_adr_1),
.c_na0(rd1_c_na0),
.c_a0(rd1_c_a0),
.na1_na2(rd1_na1_na2),
.na1_a2(rd1_na1_a2),
.a1_na2(rd1_a1_na2),
.a1_a2(rd1_a1_a2),
.na3(rd1_na3),
.a3(rd1_a3),
.na4(rd1_na4),
.a4(rd1_a4)
);

predecode_sdr_32 predecode_w0(
.strobe(strobe),
.enable(wr_enb_0),
.address(wr_adr_0),
.c_na0(wr0_c_na0),
.c_a0(wr0_c_a0),
.na1_na2(wr0_na1_na2),
.na1_a2(wr0_na1_a2),
.a1_na2(wr0_a1_na2),
.a1_a2(wr0_a1_a2),
.na3(wr0_na3),
.a3(wr0_a3),
.na4(wr0_na4),
.a4(wr0_a4)
);

endmodule

@ -0,0 +1,207 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.


// Address and clocking synthesized logic for SDR 2r1w 64 word array
// Two modes:
// 1. nodelay: for sim, FPGA - clk (SDR) or clk2x (DDR) produce strobe
// 2. delay: for implementation, strobes are configured, and derived from clk

`timescale 1 ns / 1 ns

module address_clock_sdr_2r1w_64 (

strobe,

// address ports and associated enable signals
rd_enb_0,
rd_adr_0,
rd_enb_1,
rd_adr_1,
wr_enb_0,
wr_adr_0,

// predecoded address signal
// four groups of one hot encoded signals
// read address 0
rd0_c_na0,
rd0_c_a0,
rd0_na1_na2,
rd0_na1_a2,
rd0_a1_na2,
rd0_a1_a2,
rd0_na3,
rd0_a3,
rd0_na4_na5,
rd0_na4_a5,
rd0_a4_na5,
rd0_a4_a5,

// read address 1
rd1_c_na0,
rd1_c_a0,
rd1_na1_na2,
rd1_na1_a2,
rd1_a1_na2,
rd1_a1_a2,
rd1_na3,
rd1_a3,
rd1_na4_na5,
rd1_na4_a5,
rd1_a4_na5,
rd1_a4_a5,

// write address 0
wr0_c_na0,
wr0_c_a0,
wr0_na1_na2,
wr0_na1_a2,
wr0_a1_na2,
wr0_a1_a2,
wr0_na3,
wr0_a3,
wr0_na4_na5,
wr0_na4_a5,
wr0_a4_na5,
wr0_a4_a5

);

parameter GENMODE = 0; // 0=NoDelay, 1=Delay

input strobe;

// address ports and associated enable signals
input rd_enb_0;
input [0:5] rd_adr_0;
input rd_enb_1;
input [0:5] rd_adr_1;
input wr_enb_0;
input [0:5] wr_adr_0;

// predecoded address signal
// four groups of one hot encoded signals
// read address 0
output rd0_c_na0;
output rd0_c_a0;

output rd0_na1_na2;
output rd0_na1_a2;
output rd0_a1_na2;
output rd0_a1_a2;

output rd0_na3;
output rd0_a3;

output rd0_na4_na5;
output rd0_na4_a5;
output rd0_a4_na5;
output rd0_a4_a5;

// read address 1
output rd1_c_na0;
output rd1_c_a0;

output rd1_na1_na2;
output rd1_na1_a2;
output rd1_a1_na2;
output rd1_a1_a2;

output rd1_na3;
output rd1_a3;

output rd1_na4_na5;
output rd1_na4_a5;
output rd1_a4_na5;
output rd1_a4_a5;

// write address 0
output wr0_c_na0;
output wr0_c_a0;

output wr0_na1_na2;
output wr0_na1_a2;
output wr0_a1_na2;
output wr0_a1_a2;

output wr0_na3;
output wr0_a3;

output wr0_na4_na5;
output wr0_na4_a5;
output wr0_a4_na5;
output wr0_a4_a5;

// one predecoder per port

predecode_sdr_64 predecode_r0(
.strobe(strobe),
.enable(rd_enb_0),
.address(rd_adr_0),
.c_na0(rd0_c_na0),
.c_a0(rd0_c_a0),
.na1_na2(rd0_na1_na2),
.na1_a2(rd0_na1_a2),
.a1_na2(rd0_a1_na2),
.a1_a2(rd0_a1_a2),
.na3(rd0_na3),
.a3(rd0_a3),
.na4_na5(rd0_na4_na5),
.na4_a5(rd0_na4_a5),
.a4_na5(rd0_a4_na5),
.a4_a5(rd0_a4_a5)
);

predecode_sdr_64 predecode_r1(
.strobe(strobe),
.enable(rd_enb_1),
.address(rd_adr_1),
.c_na0(rd1_c_na0),
.c_a0(rd1_c_a0),
.na1_na2(rd1_na1_na2),
.na1_a2(rd1_na1_a2),
.a1_na2(rd1_a1_na2),
.a1_a2(rd1_a1_a2),
.na3(rd1_na3),
.a3(rd1_a3),
.na4_na5(rd1_na4_na5),
.na4_a5(rd1_na4_a5),
.a4_na5(rd1_a4_na5),
.a4_a5(rd1_a4_a5)
);

predecode_sdr_64 predecode_w0(
.strobe(strobe),
.enable(wr_enb_0),
.address(wr_adr_0),
.c_na0(wr0_c_na0),
.c_a0(wr0_c_a0),
.na1_na2(wr0_na1_na2),
.na1_a2(wr0_na1_a2),
.a1_na2(wr0_a1_na2),
.a1_a2(wr0_a1_a2),
.na3(wr0_na3),
.a3(wr0_a3),
.na4_na5(wr0_na4_na5),
.na4_a5(wr0_na4_a5),
.a4_na5(wr0_a4_na5),
.a4_a5(wr0_a4_a5)
);

endmodule

@ -0,0 +1,109 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.

// Predecode of 5 address bits into 4 one hot encodings

`timescale 1 ns / 1 ns

module predecode_sdr_32(

strobe,
enable,
address,

// 12 predecoded address lines 2 - 4 - 2 - 4 one hot encoding
c_na0, // clock and not address(0)
c_a0, // clock and address(0)
na1_na2,// not address(1) and not address(2)
na1_a2, // not address(1) and address(2)
a1_na2, // address(1) and not address(2)
a1_a2, // address(1) and address(2)
na3, // not address(3)
a3, // address(3)
na4, // not address(4)
a4 // address(4)
);

input strobe;
input enable;
input [0:4] address;

output c_na0;
output c_a0;
output na1_na2;
output na1_a2;
output a1_na2;
output a1_a2; // address(1) and address(2)
output na3; // not address(3)
output a3; // address(3)
output na4; // not address(4)
output a4; // address(4)

wire clock_enable;

wire [0:4] inv_address;

wire n_c_na0;
wire n_c_a0;
wire n_na1_na2;
wire n_na1_a2;
wire n_a1_na2;
wire n_a1_a2;
wire n_na4;
wire n_a4;

// and read or write enable with clock
// does this need to be SSB placed?
assign clock_enable = strobe & enable;

assign inv_address[0] = (~(address[0]));
assign inv_address[1] = (~(address[1]));
assign inv_address[2] = (~(address[2]));
assign inv_address[3] = (~(address[3]));
assign inv_address[4] = (~(address[4]));

// A(0) address predecode and gating with clock

assign c_na0 = clock_enable & inv_address[0];

assign c_a0 = clock_enable & address[0];


// A(1:2) address predecode

assign na1_na2 = inv_address[1] & inv_address[2];

assign na1_a2 = inv_address[1] & address[2];

assign a1_na2 = address[1] & inv_address[2];

assign a1_a2 = address[1] & address[2];


// A(3) address predecode

assign na3 = inv_address[3];
assign a3 = address[3];

// A(4) address predecode

assign na4 = inv_address[4];
assign a4 = address[4];

endmodule

@ -0,0 +1,124 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.

// Predecode of 6 address bits into 4 one hot encodings

`timescale 1 ns / 1 ns

module predecode_sdr_64(

strobe,
enable,
address,
// 12 predecoded address lines 2 - 4 - 2 - 4 one hot encoding
c_na0, // clock and not address(0)
c_a0, // clock and address(0)
na1_na2,// not address(1) and not address(2)
na1_a2, // not address(1) and address(2)
a1_na2, // address(1) and not address(2)
a1_a2, // address(1) and address(2)
na3, // not address(3)
a3, // address(3)
na4_na5,// not address(4) and not address(5)
na4_a5, // not address(4) address(5)
a4_na5, // address(4) and not address(5)
a4_a5 // address(4) and address(5)

);
input strobe;
input enable;
input [0:5] address;
output c_na0;
output c_a0;
output na1_na2;
output na1_a2;
output a1_na2;
output a1_a2; // address(1) and address(2)
output na3; // not address(3)
output a3; // address(3)
output na4_na5;// not address(4) and not address(5)
output na4_a5; // not address(4) address(5)
output a4_na5; // address(4) and not address(5)
output a4_a5; // address(4) and address(5)

wire clock_enable;
wire [0:5] inv_address;
wire n_c_na0;
wire n_c_a0;
wire n_na1_na2;
wire n_na1_a2;
wire n_a1_na2;
wire n_a1_a2;
wire n_na4_na5;
wire n_na4_a5;
wire n_a4_na5;
wire n_a4_a5;

// and read or write enable with clock
// does this need to be SSB placed?
assign clock_enable = strobe & enable;

assign inv_address[0] = (~(address[0]));
assign inv_address[1] = (~(address[1]));
assign inv_address[2] = (~(address[2]));
assign inv_address[3] = (~(address[3]));
assign inv_address[4] = (~(address[4]));
assign inv_address[5] = (~(address[5]));

// A(0) address predecode and gating with clock

assign c_na0 = clock_enable & inv_address[0];
assign c_a0 = clock_enable & address[0];
// A(1:2) address predecode
assign na1_na2 = inv_address[1] & inv_address[2];
assign na1_a2 = inv_address[1] & address[2];
assign a1_na2 = address[1] & inv_address[2];
assign a1_a2 = address[1] & address[2];

// A(3) address predecode

assign na3 = inv_address[3];
assign a3 = address[3];
// A(4:5) address predecode
assign na4_na5 = inv_address[4] & inv_address[5];

assign na4_a5 = inv_address[4] & address[5];
assign a4_na5 = address[4] & inv_address[5];
assign a4_a5 = address[4] & address[5];

endmodule

@ -0,0 +1,267 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.


// Logical wrapper for 32x72 array (SDR)
// Configurable for read latching

`timescale 1 ns / 1 ns

`include "toysram.vh"

module ra_2r1w_32x32_sdr(

clk,
reset,
strobe,
rd_enb_0,
rd_adr_0,
rd_dat_0,
rd_enb_1,
rd_adr_1,
rd_dat_1,
wr_enb_0,
wr_adr_0,
wr_dat_0

);

parameter GENMODE = `GENMODE; // 0=NoDelay, 1=Delay
parameter LATCHRD = 1; // 1=latch read data, 0=unlatched

input clk;
input reset;
input strobe;

input rd_enb_0;
input [0:4] rd_adr_0;
output [0:31] rd_dat_0;

input rd_enb_1;
input [0:4] rd_adr_1;
output [0:31] rd_dat_1;

input wr_enb_0;
input [0:4] wr_adr_0;
input [0:31] wr_dat_0;

reg rd_enb_0_q;
reg [0:4] rd_adr_0_q;
//generate
// if (LATCHRD)
reg [0:31] rd_dat_0_q;
//endgenerate

reg rd_enb_1_q;
reg [0:4] rd_adr_1_q;
//generate
// if (LATCHRD)
reg [0:31] rd_dat_1_q;
//endgenerate

reg wr_enb_0_q;
reg [0:4] wr_adr_0_q;
reg [0:31] wr_dat_0_q;

// -- read 0
wire rd0_c_na0;
wire rd0_c_a0;
wire rd0_na1_na2;
wire rd0_na1_a2;
wire rd0_a1_na2;
wire rd0_a1_a2;
wire rd0_na3;
wire rd0_a3;
wire rd0_na4;
wire rd0_a4;
wire [0:31] ra_rd_dat_0;

// -- read 1
wire rd1_c_na0;
wire rd1_c_a0;
wire rd1_na1_na2;
wire rd1_na1_a2;
wire rd1_a1_na2;
wire rd1_a1_a2;
wire rd1_na3;
wire rd1_a3;
wire rd1_na4;
wire rd1_a4;
wire [0:31] ra_rd_dat_1;

// -- write 0
wire wr0_c_na0;
wire wr0_c_a0;
wire wr0_na1_na2;
wire wr0_na1_a2;
wire wr0_a1_na2;
wire wr0_a1_a2;
wire wr0_na3;
wire wr0_a3;
wire wr0_na4;
wire wr0_a4;
wire ra_wr_enb_0;
wire [0:4] ra_wr_adr_0;
wire [0:31] ra_wr_dat_0;
wire strobe_int;

// latch inputs
// reset all; only enb required
always @ (posedge clk) begin
if (reset == 1'b1) begin
rd_enb_0_q <= 0;
rd_adr_0_q <= 0;
rd_enb_1_q <= 0;
rd_adr_1_q <= 0;
wr_enb_0_q <= 0;
wr_adr_0_q <= 0;
wr_dat_0_q <= 0;
end else begin
rd_enb_0_q <= rd_enb_0;
rd_adr_0_q <= rd_adr_0;
rd_enb_1_q <= rd_enb_1;
rd_adr_1_q <= rd_adr_1;
wr_enb_0_q <= wr_enb_0;
wr_adr_0_q <= wr_adr_0;
wr_dat_0_q <= wr_dat_0;
end
end

// latch read data conditionally
generate
if (LATCHRD) begin
always @ (posedge clk) begin
rd_dat_0_q <= ra_rd_dat_0;
rd_dat_1_q <= ra_rd_dat_1;
end
assign rd_dat_0 = rd_dat_0_q;
assign rd_dat_1 = rd_dat_1_q;
end else begin
assign rd_dat_0 = ra_rd_dat_0;
assign rd_dat_1 = ra_rd_dat_1;
end
endgenerate

// don't use the clock as data in sim mode
if (`GENMODE == 0)
assign strobe_int = 1'b1;
else
assign strobe_int = strobe;

// generate the controls for the array

address_clock_sdr_2r1w_32 #(
.GENMODE(GENMODE)
) add_clk (
.strobe (strobe_int),

.rd_enb_0 (rd_enb_0_q),
.rd_adr_0 (rd_adr_0_q),
.rd_enb_1 (rd_enb_1_q),
.rd_adr_1 (rd_adr_1_q),
.wr_enb_0 (wr_enb_0_q),
.wr_adr_0 (wr_adr_0_q),

// read 0
.rd0_c_na0 (rd0_c_na0),
.rd0_c_a0 (rd0_c_a0),
.rd0_na1_na2 (rd0_na1_na2),
.rd0_na1_a2 (rd0_na1_a2),
.rd0_a1_na2 (rd0_a1_na2),
.rd0_a1_a2 (rd0_a1_a2),
.rd0_na3 (rd0_na3),
.rd0_a3 (rd0_a3),
.rd0_na4 (rd0_na4),
.rd0_a4 (rd0_a4),

// read 1
.rd1_c_na0 (rd1_c_na0),
.rd1_c_a0 (rd1_c_a0),
.rd1_na1_na2 (rd1_na1_na2),
.rd1_na1_a2 (rd1_na1_a2),
.rd1_a1_na2 (rd1_a1_na2),
.rd1_a1_a2 (rd1_a1_a2),
.rd1_na3 (rd1_na3),
.rd1_a3 (rd1_a3),
.rd1_na4 (rd1_na4),
.rd1_a4 (rd1_a4),

// write 0
.wr0_c_na0 (wr0_c_na0),
.wr0_c_a0 (wr0_c_a0),
.wr0_na1_na2 (wr0_na1_na2),
.wr0_na1_a2 (wr0_na1_a2),
.wr0_a1_na2 (wr0_a1_na2),
.wr0_a1_a2 (wr0_a1_a2),
.wr0_na3 (wr0_na3),
.wr0_a3 (wr0_a3),
.wr0_na4 (wr0_na4),
.wr0_a4 (wr0_a4)

);

// one hard array

regfile_2r1w_32x32 array0(

// predecoded address

// read 0
.rd0_c_na0 (rd0_c_na0),
.rd0_c_a0 (rd0_c_a0),
.rd0_na1_na2 (rd0_na1_na2),
.rd0_na1_a2 (rd0_na1_a2),
.rd0_a1_na2 (rd0_a1_na2),
.rd0_a1_a2 (rd0_a1_a2),
.rd0_na3 (rd0_na3),
.rd0_a3 (rd0_a3),
.rd0_na4 (rd0_na4),
.rd0_a4 (rd0_a4),
.rd0_dat (ra_rd_dat_0),

// read 1
.rd1_c_na0 (rd1_c_na0),
.rd1_c_a0 (rd1_c_a0),
.rd1_na1_na2 (rd1_na1_na2),
.rd1_na1_a2 (rd1_na1_a2),
.rd1_a1_na2 (rd1_a1_na2),
.rd1_a1_a2 (rd1_a1_a2),
.rd1_na3 (rd1_na3),
.rd1_a3 (rd1_a3),
.rd1_na4 (rd1_na4),
.rd1_a4 (rd1_a4),
.rd1_dat (ra_rd_dat_1),

// write 0
.wr0_c_na0 (wr0_c_na0),
.wr0_c_a0 (wr0_c_a0),
.wr0_na1_na2 (wr0_na1_na2),
.wr0_na1_a2 (wr0_na1_a2),
.wr0_a1_na2 (wr0_a1_na2),
.wr0_a1_a2 (wr0_a1_a2),
.wr0_na3 (wr0_na3),
.wr0_a3 (wr0_a3),
.wr0_na4 (wr0_na4),
.wr0_a4 (wr0_a4),
.wr0_dat (wr_dat_0_q)
);


endmodule

@ -0,0 +1,391 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.


// Logical wrapper for 64x72 array (SDR)
// Configurable for read latching

`timescale 1 ns / 1 ns

`include "toysram.vh"

module ra_2r1w_64x72_sdr(

clk,
reset,
strobe,
rd_enb_0,
rd_adr_0,
rd_dat_0,
rd_enb_1,
rd_adr_1,
rd_dat_1,
wr_enb_0,
wr_adr_0,
wr_dat_0

);

parameter GENMODE = `GENMODE; // 0=NoDelay, 1=Delay
parameter LATCHRD = 1; // 1=latch read data, 0=unlatched

input clk;
input reset;
input strobe;

input rd_enb_0;
input [0:5] rd_adr_0;
output [0:71] rd_dat_0;

input rd_enb_1;
input [0:5] rd_adr_1;
output [0:71] rd_dat_1;

input wr_enb_0;
input [0:5] wr_adr_0;
input [0:71] wr_dat_0;

reg rd_enb_0_q;
reg [0:5] rd_adr_0_q;
//generate
// if (LATCHRD)
reg [0:71] rd_dat_0_q;
//endgenerate

reg rd_enb_1_q;
reg [0:5] rd_adr_1_q;
//generate
// if (LATCHRD)
reg [0:71] rd_dat_1_q;
//endgenerate

reg wr_enb_0_q;
reg [0:5] wr_adr_0_q;
reg [0:71] wr_dat_0_q;

// -- read 0
wire rd0_c_na0;
wire rd0_c_a0;
wire rd0_na1_na2;
wire rd0_na1_a2;
wire rd0_a1_na2;
wire rd0_a1_a2;
wire rd0_na3;
wire rd0_a3;
wire rd0_na4_na5;
wire rd0_na4_a5;
wire rd0_a4_na5;
wire rd0_a4_a5;
wire [0:71] ra_rd_dat_0;

// -- read 1
wire rd1_c_na0;
wire rd1_c_a0;
wire rd1_na1_na2;
wire rd1_na1_a2;
wire rd1_a1_na2;
wire rd1_a1_a2;
wire rd1_na3;
wire rd1_a3;
wire rd1_na4_na5;
wire rd1_na4_a5;
wire rd1_a4_na5;
wire rd1_a4_a5;
wire [0:71] ra_rd_dat_1;

// -- write 0
wire wr0_c_na0;
wire wr0_c_a0;
wire wr0_na1_na2;
wire wr0_na1_a2;
wire wr0_a1_na2;
wire wr0_a1_a2;
wire wr0_na3;
wire wr0_a3;
wire wr0_na4_na5;
wire wr0_na4_a5;
wire wr0_a4_na5;
wire wr0_a4_a5;
wire ra_wr_enb_0;
wire [0:5] ra_wr_adr_0;
wire [0:71] ra_wr_dat_0;
wire strobe_int;

// latch inputs
// reset all; only enb required
always @ (posedge clk) begin
if (reset == 1'b1) begin
rd_enb_0_q <= 0;
rd_adr_0_q <= 0;
rd_enb_1_q <= 0;
rd_adr_1_q <= 0;
wr_enb_0_q <= 0;
wr_adr_0_q <= 0;
wr_dat_0_q <= 0;
end else begin
rd_enb_0_q <= rd_enb_0;
rd_adr_0_q <= rd_adr_0;
rd_enb_1_q <= rd_enb_1;
rd_adr_1_q <= rd_adr_1;
wr_enb_0_q <= wr_enb_0;
wr_adr_0_q <= wr_adr_0;
wr_dat_0_q <= wr_dat_0;
end
end

// latch read data conditionally
generate

if (LATCHRD) begin
always @ (posedge clk) begin
rd_dat_0_q <= ra_rd_dat_0;
rd_dat_1_q <= ra_rd_dat_1;
end
assign rd_dat_0 = rd_dat_0_q;
assign rd_dat_1 = rd_dat_1_q;
end else begin
assign rd_dat_0 = ra_rd_dat_0;
assign rd_dat_1 = ra_rd_dat_1;
end

endgenerate

// don't use the clock as data in sim mode
if (`GENMODE == 0)
assign strobe_int = 1'b1;
else
assign strobe_int = strobe;

// generate the controls for the array

address_clock_sdr_2r1w_64

#( .GENMODE(GENMODE)
)

add_clk

(
.strobe (strobe_int),

.rd_enb_0 (rd_enb_0_q),
.rd_adr_0 (rd_adr_0_q),
.rd_enb_1 (rd_enb_1_q),
.rd_adr_1 (rd_adr_1_q),
.wr_enb_0 (wr_enb_0_q),
.wr_adr_0 (wr_adr_0_q),

// read 0
.rd0_c_na0 (rd0_c_na0),
.rd0_c_a0 (rd0_c_a0),
.rd0_na1_na2 (rd0_na1_na2),
.rd0_na1_a2 (rd0_na1_a2),
.rd0_a1_na2 (rd0_a1_na2),
.rd0_a1_a2 (rd0_a1_a2),
.rd0_na3 (rd0_na3),
.rd0_a3 (rd0_a3),
.rd0_na4_na5 (rd0_na4_na5),
.rd0_na4_a5 (rd0_na4_a5),
.rd0_a4_na5 (rd0_a4_na5),
.rd0_a4_a5 (rd0_a4_a5),

// read 1
.rd1_c_na0 (rd1_c_na0),
.rd1_c_a0 (rd1_c_a0),
.rd1_na1_na2 (rd1_na1_na2),
.rd1_na1_a2 (rd1_na1_a2),
.rd1_a1_na2 (rd1_a1_na2),
.rd1_a1_a2 (rd1_a1_a2),
.rd1_na3 (rd1_na3),
.rd1_a3 (rd1_a3),
.rd1_na4_na5 (rd1_na4_na5),
.rd1_na4_a5 (rd1_na4_a5),
.rd1_a4_na5 (rd1_a4_na5),
.rd1_a4_a5 (rd1_a4_a5),

// write 0
.wr0_c_na0 (wr0_c_na0),
.wr0_c_a0 (wr0_c_a0),
.wr0_na1_na2 (wr0_na1_na2),
.wr0_na1_a2 (wr0_na1_a2),
.wr0_a1_na2 (wr0_a1_na2),
.wr0_a1_a2 (wr0_a1_a2),
.wr0_na3 (wr0_na3),
.wr0_a3 (wr0_a3),
.wr0_na4_na5 (wr0_na4_na5),
.wr0_na4_a5 (wr0_na4_a5),
.wr0_a4_na5 (wr0_a4_na5),
.wr0_a4_a5 (wr0_a4_a5)

);

// three hard arrays

regfile_2r1w_64x24 array0(

// predecoded address
// read 0
.rd0_c_na0 (rd0_c_na0),
.rd0_c_a0 (rd0_c_a0),
.rd0_na1_na2 (rd0_na1_na2),
.rd0_na1_a2 (rd0_na1_a2),
.rd0_a1_na2 (rd0_a1_na2),
.rd0_a1_a2 (rd0_a1_a2),
.rd0_na3 (rd0_na3),
.rd0_a3 (rd0_a3),
.rd0_na4_na5 (rd0_na4_na5),
.rd0_na4_a5 (rd0_na4_a5),
.rd0_a4_na5 (rd0_a4_na5),
.rd0_a4_a5 (rd0_a4_a5),
.rd0_dat (ra_rd_dat_0[0:23]),

// read 1
.rd1_c_na0 (rd1_c_na0),
.rd1_c_a0 (rd1_c_a0),
.rd1_na1_na2 (rd1_na1_na2),
.rd1_na1_a2 (rd1_na1_a2),
.rd1_a1_na2 (rd1_a1_na2),
.rd1_a1_a2 (rd1_a1_a2),
.rd1_na3 (rd1_na3),
.rd1_a3 (rd1_a3),
.rd1_na4_na5 (rd1_na4_na5),
.rd1_na4_a5 (rd1_na4_a5),
.rd1_a4_na5 (rd1_a4_na5),
.rd1_a4_a5 (rd1_a4_a5),
.rd1_dat (ra_rd_dat_1[0:23]),

// write 0
.wr0_c_na0 (wr0_c_na0),
.wr0_c_a0 (wr0_c_a0),
.wr0_na1_na2 (wr0_na1_na2),
.wr0_na1_a2 (wr0_na1_a2),
.wr0_a1_na2 (wr0_a1_na2),
.wr0_a1_a2 (wr0_a1_a2),
.wr0_na3 (wr0_na3),
.wr0_a3 (wr0_a3),
.wr0_na4_na5 (wr0_na4_na5),
.wr0_na4_a5 (wr0_na4_a5),
.wr0_a4_na5 (wr0_a4_na5),
.wr0_a4_a5 (wr0_a4_a5),
.wr0_dat (wr_dat_0_q[0:23])

);

regfile_2r1w_64x24 array1(

// predecoded address
// read 0
.rd0_c_na0 (rd0_c_na0),
.rd0_c_a0 (rd0_c_a0),
.rd0_na1_na2 (rd0_na1_na2),
.rd0_na1_a2 (rd0_na1_a2),
.rd0_a1_na2 (rd0_a1_na2),
.rd0_a1_a2 (rd0_a1_a2),
.rd0_na3 (rd0_na3),
.rd0_a3 (rd0_a3),
.rd0_na4_na5 (rd0_na4_na5),
.rd0_na4_a5 (rd0_na4_a5),
.rd0_a4_na5 (rd0_a4_na5),
.rd0_a4_a5 (rd0_a4_a5),
.rd0_dat (ra_rd_dat_0[24:47]),

// read 1
.rd1_c_na0 (rd1_c_na0),
.rd1_c_a0 (rd1_c_a0),
.rd1_na1_na2 (rd1_na1_na2),
.rd1_na1_a2 (rd1_na1_a2),
.rd1_a1_na2 (rd1_a1_na2),
.rd1_a1_a2 (rd1_a1_a2),
.rd1_na3 (rd1_na3),
.rd1_a3 (rd1_a3),
.rd1_na4_na5 (rd1_na4_na5),
.rd1_na4_a5 (rd1_na4_a5),
.rd1_a4_na5 (rd1_a4_na5),
.rd1_a4_a5 (rd1_a4_a5),
.rd1_dat (ra_rd_dat_1[24:47]),

// write 0
.wr0_c_na0 (wr0_c_na0),
.wr0_c_a0 (wr0_c_a0),
.wr0_na1_na2 (wr0_na1_na2),
.wr0_na1_a2 (wr0_na1_a2),
.wr0_a1_na2 (wr0_a1_na2),
.wr0_a1_a2 (wr0_a1_a2),
.wr0_na3 (wr0_na3),
.wr0_a3 (wr0_a3),
.wr0_na4_na5 (wr0_na4_na5),
.wr0_na4_a5 (wr0_na4_a5),
.wr0_a4_na5 (wr0_a4_na5),
.wr0_a4_a5 (wr0_a4_a5),
.wr0_dat (wr_dat_0_q[24:47])

);

regfile_2r1w_64x24 array2(

// predecoded address
// read 0
.rd0_c_na0 (rd0_c_na0),
.rd0_c_a0 (rd0_c_a0),
.rd0_na1_na2 (rd0_na1_na2),
.rd0_na1_a2 (rd0_na1_a2),
.rd0_a1_na2 (rd0_a1_na2),
.rd0_a1_a2 (rd0_a1_a2),
.rd0_na3 (rd0_na3),
.rd0_a3 (rd0_a3),
.rd0_na4_na5 (rd0_na4_na5),
.rd0_na4_a5 (rd0_na4_a5),
.rd0_a4_na5 (rd0_a4_na5),
.rd0_a4_a5 (rd0_a4_a5),
.rd0_dat (ra_rd_dat_0[48:71]),

// read 1
.rd1_c_na0 (rd1_c_na0),
.rd1_c_a0 (rd1_c_a0),
.rd1_na1_na2 (rd1_na1_na2),
.rd1_na1_a2 (rd1_na1_a2),
.rd1_a1_na2 (rd1_a1_na2),
.rd1_a1_a2 (rd1_a1_a2),
.rd1_na3 (rd1_na3),
.rd1_a3 (rd1_a3),
.rd1_na4_na5 (rd1_na4_na5),
.rd1_na4_a5 (rd1_na4_a5),
.rd1_a4_na5 (rd1_a4_na5),
.rd1_a4_a5 (rd1_a4_a5),
.rd1_dat (ra_rd_dat_1[48:71]),

// write 0
.wr0_c_na0 (wr0_c_na0),
.wr0_c_a0 (wr0_c_a0),
.wr0_na1_na2 (wr0_na1_na2),
.wr0_na1_a2 (wr0_na1_a2),
.wr0_a1_na2 (wr0_a1_na2),
.wr0_a1_a2 (wr0_a1_a2),
.wr0_na3 (wr0_na3),
.wr0_a3 (wr0_a3),
.wr0_na4_na5 (wr0_na4_na5),
.wr0_na4_a5 (wr0_na4_a5),
.wr0_a4_na5 (wr0_a4_na5),
.wr0_a4_a5 (wr0_a4_a5),
.wr0_dat (wr_dat_0_q[48:71])

);

endmodule

@ -0,0 +1,502 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.


// Logical wrapper for 64x72 array (DDR)

// The encode logic and arrays are the same for sdr and ddr. The ports are
// mux'd between first and second half of cycle using el_sel.

`timescale 1 ns / 1 ns

`include "toysram.vh"

module ra_4r2w_64x72_ddr (

clk,
reset,
strobe,
el_sel,
rd_enb_0,
rd_adr_0,
rd_dat_0,
rd_enb_1,
rd_adr_1,
rd_dat_1,
rd_enb_2,
rd_adr_2,
rd_dat_2,
rd_enb_3,
rd_adr_3,
rd_dat_3,
wr_enb_0,
wr_adr_0,
wr_dat_0,
wr_enb_1,
wr_adr_1,
wr_dat_1

);

parameter GENMODE = `GENMODE; // 0=NoDelay, 1=Delay

input clk;
input reset;
input strobe;
input el_sel;

input rd_enb_0;
input [0:5] rd_adr_0;
output [0:71] rd_dat_0;

input rd_enb_1;
input [0:5] rd_adr_1;
output [0:71] rd_dat_1;

input rd_enb_2;
input [0:5] rd_adr_2;
output [0:71] rd_dat_2;

input rd_enb_3;
input [0:5] rd_adr_3;
output [0:71] rd_dat_3;

input wr_enb_0;
input [0:5] wr_adr_0;
input [0:71] wr_dat_0;

input wr_enb_1;
input [0:5] wr_adr_1;
input [0:71] wr_dat_1;

reg rd_enb_0_q;
reg [0:5] rd_adr_0_q;
reg [0:71] rd_dat_0_q;
reg [0:71] rd_dat_0_hold_q;

reg rd_enb_1_q;
reg [0:5] rd_adr_1_q;
reg [0:71] rd_dat_1_q;
reg [0:71] rd_dat_1_hold_q;

reg rd_enb_2_q;
reg [0:5] rd_adr_2_q;
reg [0:71] rd_dat_2_q;

reg rd_enb_3_q;
reg [0:5] rd_adr_3_q;
reg [0:71] rd_dat_3_q;

reg wr_enb_0_q;
reg [0:5] wr_adr_0_q;
reg [0:71] wr_dat_0_q;

reg wr_enb_1_q;
reg [0:5] wr_adr_1_q;
reg [0:71] wr_dat_1_q;

// read 0
wire rd0_c_na0;
wire rd0_c_a0;
wire rd0_na1_na2;
wire rd0_na1_a2;
wire rd0_a1_na2;
wire rd0_a1_a2;
wire rd0_na3;
wire rd0_a3;
wire rd0_na4_na5;
wire rd0_na4_a5;
wire rd0_a4_na5;
wire rd0_a4_a5;
wire [0:71] ra_rd_dat_0;

// read 1
wire rd1_c_na0;
wire rd1_c_a0;
wire rd1_na1_na2;
wire rd1_na1_a2;
wire rd1_a1_na2;
wire rd1_a1_a2;
wire rd1_na3;
wire rd1_a3;
wire rd1_na4_na5;
wire rd1_na4_a5;
wire rd1_a4_na5;
wire rd1_a4_a5;
wire [0:71] ra_rd_dat_1;

// read 2
wire rd2_c_na0;
wire rd2_c_a0;
wire rd2_na1_na2;
wire rd2_na1_a2;
wire rd2_a1_na2;
wire rd2_a1_a2;
wire rd2_na3;
wire rd2_a3;
wire rd2_na4_na5;
wire rd2_na4_a5;
wire rd2_a4_na5;
wire rd2_a4_a5;
wire [0:71] ra_rd_dat_2;

// read 3
wire rd3_c_na0;
wire rd3_c_a0;
wire rd3_na1_na2;
wire rd3_na1_a2;
wire rd3_a1_na2;
wire rd3_a1_a2;
wire rd3_na3;
wire rd3_a3;
wire rd3_na4_na5;
wire rd3_na4_a5;
wire rd3_a4_na5;
wire rd3_a4_a5;
wire [0:71] ra_rd_dat_3;

// write 0
wire wr0_c_na0;
wire wr0_c_a0;
wire wr0_na1_na2;
wire wr0_na1_a2;
wire wr0_a1_na2;
wire wr0_a1_a2;
wire wr0_na3;
wire wr0_a3;
wire wr0_na4_na5;
wire wr0_na4_a5;
wire wr0_a4_na5;
wire wr0_a4_a5;
wire ra_wr_enb_0;
wire [0:5] ra_wr_adr_0;

// write 1
wire wr1_c_na0;
wire wr1_c_a0;
wire wr1_na1_na2;
wire wr1_na1_a2;
wire wr1_a1_na2;
wire wr1_a1_a2;
wire wr1_na3;
wire wr1_a3;
wire wr1_na4_na5;
wire wr1_na4_a5;
wire wr1_a4_na5;
wire wr1_a4_a5;
wire ra_wr_enb_1;
wire [0:5] ra_wr_adr_1;

wire rd_enb_02;
wire [0:5] rd_adr_02;
wire rd_enb_13;
wire [0:5] rd_adr_13;
wire wr_enb_01;
wire [0:5] wr_adr_01;
wire [0:71] wr_dat_01;
wire strobe_int;

// latch inputs
// reset all; only enb required
always @ (posedge clk) begin
if (reset == 1'b1) begin
rd_enb_0_q <= 0;
rd_adr_0_q <= 0;
rd_enb_1_q <= 0;
rd_adr_1_q <= 0;
rd_enb_2_q <= 0;
rd_adr_2_q <= 0;
rd_enb_3_q <= 0;
rd_adr_3_q <= 0;
wr_enb_0_q <= 0;
wr_adr_0_q <= 0;
wr_dat_0_q <= 0;
wr_enb_1_q <= 0;
wr_adr_1_q <= 0;
wr_dat_1_q <= 0;
end else begin
rd_enb_0_q <= rd_enb_0;
rd_adr_0_q <= rd_adr_0;
rd_enb_1_q <= rd_enb_1;
rd_adr_1_q <= rd_adr_1;
rd_enb_2_q <= rd_enb_2;
rd_adr_2_q <= rd_adr_2;
rd_enb_3_q <= rd_enb_3;
rd_adr_3_q <= rd_adr_3;
wr_enb_0_q <= wr_enb_0;
wr_adr_0_q <= wr_adr_0;
wr_dat_0_q <= wr_dat_0;
wr_enb_1_q <= wr_enb_1;
wr_adr_1_q <= wr_adr_1;
wr_dat_1_q <= wr_dat_1;
end
end

// latch read data
// early reads are double latched to hold during next cycle
generate

always @ (posedge strobe) begin
rd_dat_0_q <= (!el_sel) ? ra_rd_dat_0 : rd_dat_0_q;
rd_dat_1_q <= (!el_sel) ? ra_rd_dat_1 : rd_dat_1_q;
rd_dat_2_q <= (el_sel) ? ra_rd_dat_0 : rd_dat_2_q;
rd_dat_3_q <= (el_sel) ? ra_rd_dat_1 : rd_dat_3_q;
end
always @ (posedge clk) begin
rd_dat_0_hold_q <= rd_dat_0_q;
rd_dat_1_hold_q <= rd_dat_1_q;
end
assign rd_dat_0 = rd_dat_0_hold_q;
assign rd_dat_1 = rd_dat_1_hold_q;
assign rd_dat_2 = rd_dat_2_q;
assign rd_dat_3 = rd_dat_3_q;

endgenerate

assign rd_enb_02 = (el_sel) ? rd_enb_2_q : rd_enb_0_q;
assign rd_adr_02 = (el_sel) ? rd_adr_2_q : rd_adr_0_q;
assign rd_enb_13 = (el_sel) ? rd_enb_3_q : rd_enb_1_q;
assign rd_adr_13 = (el_sel) ? rd_adr_3_q : rd_adr_1_q;
assign wr_enb_01 = (el_sel) ? wr_enb_1_q : wr_enb_0_q;
assign wr_adr_01 = (el_sel) ? wr_adr_1_q : wr_adr_0_q;
assign wr_dat_01 = (el_sel) ? wr_dat_1_q : wr_dat_0_q;

// don't use the clock as data in sim mode
if (`GENMODE == 0)
assign strobe_int = 1'b1;
else
assign strobe_int = strobe;

// generate the controls for the array

address_clock_sdr_2r1w_64

#( .GENMODE(GENMODE)
)

add_clk

(
.strobe (strobe_int),

.rd_enb_0 (rd_enb_02),
.rd_adr_0 (rd_adr_02),
.rd_enb_1 (rd_enb_13),
.rd_adr_1 (rd_adr_13),
.wr_enb_0 (wr_enb_01),
.wr_adr_0 (wr_adr_01),

// read 0
.rd0_c_na0 (rd0_c_na0),
.rd0_c_a0 (rd0_c_a0),
.rd0_na1_na2 (rd0_na1_na2),
.rd0_na1_a2 (rd0_na1_a2),
.rd0_a1_na2 (rd0_a1_na2),
.rd0_a1_a2 (rd0_a1_a2),
.rd0_na3 (rd0_na3),
.rd0_a3 (rd0_a3),
.rd0_na4_na5 (rd0_na4_na5),
.rd0_na4_a5 (rd0_na4_a5),
.rd0_a4_na5 (rd0_a4_na5),
.rd0_a4_a5 (rd0_a4_a5),

// read 1
.rd1_c_na0 (rd1_c_na0),
.rd1_c_a0 (rd1_c_a0),
.rd1_na1_na2 (rd1_na1_na2),
.rd1_na1_a2 (rd1_na1_a2),
.rd1_a1_na2 (rd1_a1_na2),
.rd1_a1_a2 (rd1_a1_a2),
.rd1_na3 (rd1_na3),
.rd1_a3 (rd1_a3),
.rd1_na4_na5 (rd1_na4_na5),
.rd1_na4_a5 (rd1_na4_a5),
.rd1_a4_na5 (rd1_a4_na5),
.rd1_a4_a5 (rd1_a4_a5),

// write 0
.wr0_c_na0 (wr0_c_na0),
.wr0_c_a0 (wr0_c_a0),
.wr0_na1_na2 (wr0_na1_na2),
.wr0_na1_a2 (wr0_na1_a2),
.wr0_a1_na2 (wr0_a1_na2),
.wr0_a1_a2 (wr0_a1_a2),
.wr0_na3 (wr0_na3),
.wr0_a3 (wr0_a3),
.wr0_na4_na5 (wr0_na4_na5),
.wr0_na4_a5 (wr0_na4_a5),
.wr0_a4_na5 (wr0_a4_na5),
.wr0_a4_a5 (wr0_a4_a5)

);

// three hard arrays

regfile_2r1w_64x24 array0(

// predecoded address
// read 0
.rd0_c_na0 (rd0_c_na0),
.rd0_c_a0 (rd0_c_a0),
.rd0_na1_na2 (rd0_na1_na2),
.rd0_na1_a2 (rd0_na1_a2),
.rd0_a1_na2 (rd0_a1_na2),
.rd0_a1_a2 (rd0_a1_a2),
.rd0_na3 (rd0_na3),
.rd0_a3 (rd0_a3),
.rd0_na4_na5 (rd0_na4_na5),
.rd0_na4_a5 (rd0_na4_a5),
.rd0_a4_na5 (rd0_a4_na5),
.rd0_a4_a5 (rd0_a4_a5),
.rd0_dat (ra_rd_dat_0[0:23]),

// read 1
.rd1_c_na0 (rd1_c_na0),
.rd1_c_a0 (rd1_c_a0),
.rd1_na1_na2 (rd1_na1_na2),
.rd1_na1_a2 (rd1_na1_a2),
.rd1_a1_na2 (rd1_a1_na2),
.rd1_a1_a2 (rd1_a1_a2),
.rd1_na3 (rd1_na3),
.rd1_a3 (rd1_a3),
.rd1_na4_na5 (rd1_na4_na5),
.rd1_na4_a5 (rd1_na4_a5),
.rd1_a4_na5 (rd1_a4_na5),
.rd1_a4_a5 (rd1_a4_a5),
.rd1_dat (ra_rd_dat_1[0:23]),

// write 0
.wr0_c_na0 (wr0_c_na0),
.wr0_c_a0 (wr0_c_a0),
.wr0_na1_na2 (wr0_na1_na2),
.wr0_na1_a2 (wr0_na1_a2),
.wr0_a1_na2 (wr0_a1_na2),
.wr0_a1_a2 (wr0_a1_a2),
.wr0_na3 (wr0_na3),
.wr0_a3 (wr0_a3),
.wr0_na4_na5 (wr0_na4_na5),
.wr0_na4_a5 (wr0_na4_a5),
.wr0_a4_na5 (wr0_a4_na5),
.wr0_a4_a5 (wr0_a4_a5),
.wr0_dat (wr_dat_01[0:23])

);

regfile_2r1w_64x24 array1(

// predecoded address
// read 0
.rd0_c_na0 (rd0_c_na0),
.rd0_c_a0 (rd0_c_a0),
.rd0_na1_na2 (rd0_na1_na2),
.rd0_na1_a2 (rd0_na1_a2),
.rd0_a1_na2 (rd0_a1_na2),
.rd0_a1_a2 (rd0_a1_a2),
.rd0_na3 (rd0_na3),
.rd0_a3 (rd0_a3),
.rd0_na4_na5 (rd0_na4_na5),
.rd0_na4_a5 (rd0_na4_a5),
.rd0_a4_na5 (rd0_a4_na5),
.rd0_a4_a5 (rd0_a4_a5),
.rd0_dat (ra_rd_dat_0[24:47]),

// read 1
.rd1_c_na0 (rd1_c_na0),
.rd1_c_a0 (rd1_c_a0),
.rd1_na1_na2 (rd1_na1_na2),
.rd1_na1_a2 (rd1_na1_a2),
.rd1_a1_na2 (rd1_a1_na2),
.rd1_a1_a2 (rd1_a1_a2),
.rd1_na3 (rd1_na3),
.rd1_a3 (rd1_a3),
.rd1_na4_na5 (rd1_na4_na5),
.rd1_na4_a5 (rd1_na4_a5),
.rd1_a4_na5 (rd1_a4_na5),
.rd1_a4_a5 (rd1_a4_a5),
.rd1_dat (ra_rd_dat_1[24:47]),

// write 0
.wr0_c_na0 (wr0_c_na0),
.wr0_c_a0 (wr0_c_a0),
.wr0_na1_na2 (wr0_na1_na2),
.wr0_na1_a2 (wr0_na1_a2),
.wr0_a1_na2 (wr0_a1_na2),
.wr0_a1_a2 (wr0_a1_a2),
.wr0_na3 (wr0_na3),
.wr0_a3 (wr0_a3),
.wr0_na4_na5 (wr0_na4_na5),
.wr0_na4_a5 (wr0_na4_a5),
.wr0_a4_na5 (wr0_a4_na5),
.wr0_a4_a5 (wr0_a4_a5),
.wr0_dat (wr_dat_01[24:47])

);

regfile_2r1w_64x24 array2(

// predecoded address
// read 0
.rd0_c_na0 (rd0_c_na0),
.rd0_c_a0 (rd0_c_a0),
.rd0_na1_na2 (rd0_na1_na2),
.rd0_na1_a2 (rd0_na1_a2),
.rd0_a1_na2 (rd0_a1_na2),
.rd0_a1_a2 (rd0_a1_a2),
.rd0_na3 (rd0_na3),
.rd0_a3 (rd0_a3),
.rd0_na4_na5 (rd0_na4_na5),
.rd0_na4_a5 (rd0_na4_a5),
.rd0_a4_na5 (rd0_a4_na5),
.rd0_a4_a5 (rd0_a4_a5),
.rd0_dat (ra_rd_dat_0[48:71]),

// read 1
.rd1_c_na0 (rd1_c_na0),
.rd1_c_a0 (rd1_c_a0),
.rd1_na1_na2 (rd1_na1_na2),
.rd1_na1_a2 (rd1_na1_a2),
.rd1_a1_na2 (rd1_a1_na2),
.rd1_a1_a2 (rd1_a1_a2),
.rd1_na3 (rd1_na3),
.rd1_a3 (rd1_a3),
.rd1_na4_na5 (rd1_na4_na5),
.rd1_na4_a5 (rd1_na4_a5),
.rd1_a4_na5 (rd1_a4_na5),
.rd1_a4_a5 (rd1_a4_a5),
.rd1_dat (ra_rd_dat_1[48:71]),

// write 0
.wr0_c_na0 (wr0_c_na0),
.wr0_c_a0 (wr0_c_a0),
.wr0_na1_na2 (wr0_na1_na2),
.wr0_na1_a2 (wr0_na1_a2),
.wr0_a1_na2 (wr0_a1_na2),
.wr0_a1_a2 (wr0_a1_a2),
.wr0_na3 (wr0_na3),
.wr0_a3 (wr0_a3),
.wr0_na4_na5 (wr0_na4_na5),
.wr0_na4_a5 (wr0_na4_a5),
.wr0_a4_na5 (wr0_a4_na5),
.wr0_a4_a5 (wr0_a4_a5),
.wr0_dat (wr_dat_01[48:71])

);

endmodule

@ -0,0 +1,686 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.


// Logical wrapper for 64x72 array (DDR) - uses 1x clock only (but requires 2w regfile component)
// Configurable for read latching

`timescale 1 ns / 1 ns

`include "toysram.vh"

module ra_4r2w_64x72_ddr_1x (

clk,
reset,
strobe,
rd_enb_0,
rd_adr_0,
rd_dat_0,
rd_enb_1,
rd_adr_1,
rd_dat_1,
rd_enb_2,
rd_adr_2,
rd_dat_2,
rd_enb_3,
rd_adr_3,
rd_dat_3,
wr_enb_0,
wr_adr_0,
wr_dat_0,
wr_enb_1,
wr_adr_1,
wr_dat_1

);

parameter GENMODE = `GENMODE; // 0=NoDelay, 1=Delay
parameter LATCHRD = 1; // 1=latch read data, 0=unlatched

input clk;
input reset;
input strobe;

input rd_enb_0;
input [0:5] rd_adr_0;
output [0:71] rd_dat_0;

input rd_enb_1;
input [0:5] rd_adr_1;
output [0:71] rd_dat_1;

input rd_enb_2;
input [0:5] rd_adr_2;
output [0:71] rd_dat_2;

input rd_enb_3;
input [0:5] rd_adr_3;
output [0:71] rd_dat_3;

input wr_enb_0;
input [0:5] wr_adr_0;
input [0:71] wr_dat_0;

input wr_enb_1;
input [0:5] wr_adr_1;
input [0:71] wr_dat_1;

reg rd_enb_0_q;
reg [0:5] rd_adr_0_q;
//generate
// if (LATCHRD)
reg [0:71] rd_dat_0_q;
//endgenerate

reg rd_enb_1_q;
reg [0:5] rd_adr_1_q;
//generate
// if (LATCHRD)
reg [0:71] rd_dat_1_q;
//endgenerate

reg rd_enb_2_q;
reg [0:5] rd_adr_2_q;
//generate
// if (LATCHRD)
reg [0:71] rd_dat_2_q;
//endgenerate

reg rd_enb_3_q;
reg [0:5] rd_adr_3_q;
//generate
// if (LATCHRD)
reg [0:71] rd_dat_3_q;
//endgenerate

reg wr_enb_0_q;
reg [0:5] wr_adr_0_q;
reg [0:71] wr_dat_0_q;

reg wr_enb_1_q;
reg [0:5] wr_adr_1_q;
reg [0:71] wr_dat_1_q;

// -- read 0
wire rd0_c_na0;
wire rd0_c_a0;
wire rd0_na1_na2;
wire rd0_na1_a2;
wire rd0_a1_na2;
wire rd0_a1_a2;
wire rd0_na3;
wire rd0_a3;
wire rd0_na4_na5;
wire rd0_na4_a5;
wire rd0_a4_na5;
wire rd0_a4_a5;
wire [0:71] ra_rd_dat_0;

// -- read 1
wire rd1_c_na0;
wire rd1_c_a0;
wire rd1_na1_na2;
wire rd1_na1_a2;
wire rd1_a1_na2;
wire rd1_a1_a2;
wire rd1_na3;
wire rd1_a3;
wire rd1_na4_na5;
wire rd1_na4_a5;
wire rd1_a4_na5;
wire rd1_a4_a5;
wire [0:71] ra_rd_dat_1;

// -- read 2
wire rd2_c_na0;
wire rd2_c_a0;
wire rd2_na1_na2;
wire rd2_na1_a2;
wire rd2_a1_na2;
wire rd2_a1_a2;
wire rd2_na3;
wire rd2_a3;
wire rd2_na4_na5;
wire rd2_na4_a5;
wire rd2_a4_na5;
wire rd2_a4_a5;
wire [0:71] ra_rd_dat_2;

// -- read 3
wire rd3_c_na0;
wire rd3_c_a0;
wire rd3_na1_na2;
wire rd3_na1_a2;
wire rd3_a1_na2;
wire rd3_a1_a2;
wire rd3_na3;
wire rd3_a3;
wire rd3_na4_na5;
wire rd3_na4_a5;
wire rd3_a4_na5;
wire rd3_a4_a5;
wire [0:71] ra_rd_dat_3;

// -- write 0
wire wr0_c_na0;
wire wr0_c_a0;
wire wr0_na1_na2;
wire wr0_na1_a2;
wire wr0_a1_na2;
wire wr0_a1_a2;
wire wr0_na3;
wire wr0_a3;
wire wr0_na4_na5;
wire wr0_na4_a5;
wire wr0_a4_na5;
wire wr0_a4_a5;

// -- write 1
wire wr1_c_na0;
wire wr1_c_a0;
wire wr1_na1_na2;
wire wr1_na1_a2;
wire wr1_a1_na2;
wire wr1_a1_a2;
wire wr1_na3;
wire wr1_a3;
wire wr1_na4_na5;
wire wr1_na4_a5;
wire wr1_a4_na5;
wire wr1_a4_a5;

wire strobe_int;

// latch inputs
// reset all; only enb required
always @ (posedge clk) begin
if (reset == 1'b1) begin
rd_enb_0_q <= 0;
rd_adr_0_q <= 0;
rd_enb_1_q <= 0;
rd_adr_1_q <= 0;
rd_enb_2_q <= 0;
rd_adr_2_q <= 0;
rd_enb_3_q <= 0;
rd_adr_3_q <= 0;
wr_enb_0_q <= 0;
wr_adr_0_q <= 0;
wr_dat_0_q <= 0;
wr_enb_1_q <= 0;
wr_adr_1_q <= 0;
wr_dat_1_q <= 0;
end else begin
rd_enb_0_q <= rd_enb_0;
rd_adr_0_q <= rd_adr_0;
rd_enb_1_q <= rd_enb_1;
rd_adr_1_q <= rd_adr_1;
rd_enb_2_q <= rd_enb_2;
rd_adr_2_q <= rd_adr_2;
rd_enb_3_q <= rd_enb_3;
rd_adr_3_q <= rd_adr_3;
wr_enb_0_q <= wr_enb_0;
wr_adr_0_q <= wr_adr_0;
wr_dat_0_q <= wr_dat_0;
wr_enb_1_q <= wr_enb_1;
wr_adr_1_q <= wr_adr_1;
wr_dat_1_q <= wr_dat_1;
end
end

// latch read data conditionally
generate

if (LATCHRD) begin
always @ (posedge clk) begin
rd_dat_0_q <= ra_rd_dat_0;
rd_dat_1_q <= ra_rd_dat_1;
rd_dat_2_q <= ra_rd_dat_2;
rd_dat_3_q <= ra_rd_dat_3;
end
assign rd_dat_0 = rd_dat_0_q;
assign rd_dat_1 = rd_dat_1_q;
assign rd_dat_2 = rd_dat_2_q;
assign rd_dat_3 = rd_dat_3_q;
end else begin
assign rd_dat_0 = ra_rd_dat_0;
assign rd_dat_1 = ra_rd_dat_1;
assign rd_dat_2 = ra_rd_dat_2;
assign rd_dat_3 = ra_rd_dat_3;
end

endgenerate

if (`GENMODE == 0)
assign strobe_int = !reset;
else
assign strobe_int = strobe;

// generate the controls for the array
// dup controls to use same component
// but need new regfile to support 2 writes

address_clock_sdr_2r1w_64

#( .GENMODE(GENMODE)
)

add_clk_01

(
.strobe (strobe_int),

.rd_enb_0 (rd_enb_0_q),
.rd_adr_0 (rd_adr_0_q),
.rd_enb_1 (rd_enb_1_q),
.rd_adr_1 (rd_adr_1_q),
.wr_enb_0 (wr_enb_0_q),
.wr_adr_0 (wr_adr_0_q),

// read 0
.rd0_c_na0 (rd0_c_na0),
.rd0_c_a0 (rd0_c_a0),
.rd0_na1_na2 (rd0_na1_na2),
.rd0_na1_a2 (rd0_na1_a2),
.rd0_a1_na2 (rd0_a1_na2),
.rd0_a1_a2 (rd0_a1_a2),
.rd0_na3 (rd0_na3),
.rd0_a3 (rd0_a3),
.rd0_na4_na5 (rd0_na4_na5),
.rd0_na4_a5 (rd0_na4_a5),
.rd0_a4_na5 (rd0_a4_na5),
.rd0_a4_a5 (rd0_a4_a5),

// read 1
.rd1_c_na0 (rd1_c_na0),
.rd1_c_a0 (rd1_c_a0),
.rd1_na1_na2 (rd1_na1_na2),
.rd1_na1_a2 (rd1_na1_a2),
.rd1_a1_na2 (rd1_a1_na2),
.rd1_a1_a2 (rd1_a1_a2),
.rd1_na3 (rd1_na3),
.rd1_a3 (rd1_a3),
.rd1_na4_na5 (rd1_na4_na5),
.rd1_na4_a5 (rd1_na4_a5),
.rd1_a4_na5 (rd1_a4_na5),
.rd1_a4_a5 (rd1_a4_a5),

// write 0
.wr0_c_na0 (wr0_c_na0),
.wr0_c_a0 (wr0_c_a0),
.wr0_na1_na2 (wr0_na1_na2),
.wr0_na1_a2 (wr0_na1_a2),
.wr0_a1_na2 (wr0_a1_na2),
.wr0_a1_a2 (wr0_a1_a2),
.wr0_na3 (wr0_na3),
.wr0_a3 (wr0_a3),
.wr0_na4_na5 (wr0_na4_na5),
.wr0_na4_a5 (wr0_na4_a5),
.wr0_a4_na5 (wr0_a4_na5),
.wr0_a4_a5 (wr0_a4_a5)

);

address_clock_sdr_2r1w_64

#( .GENMODE(GENMODE)
)

add_clk_23

(
.strobe (strobe_int),

.rd_enb_0 (rd_enb_2_q),
.rd_adr_0 (rd_adr_2_q),
.rd_enb_1 (rd_enb_3_q),
.rd_adr_1 (rd_adr_3_q),
.wr_enb_0 (wr_enb_1_q),
.wr_adr_0 (wr_adr_1_q),

// read 2
.rd0_c_na0 (rd2_c_na0),
.rd0_c_a0 (rd2_c_a0),
.rd0_na1_na2 (rd2_na1_na2),
.rd0_na1_a2 (rd2_na1_a2),
.rd0_a1_na2 (rd2_a1_na2),
.rd0_a1_a2 (rd2_a1_a2),
.rd0_na3 (rd2_na3),
.rd0_a3 (rd2_a3),
.rd0_na4_na5 (rd2_na4_na5),
.rd0_na4_a5 (rd2_na4_a5),
.rd0_a4_na5 (rd2_a4_na5),
.rd0_a4_a5 (rd2_a4_a5),

// read 3
.rd1_c_na0 (rd3_c_na0),
.rd1_c_a0 (rd3_c_a0),
.rd1_na1_na2 (rd3_na1_na2),
.rd1_na1_a2 (rd3_na1_a2),
.rd1_a1_na2 (rd3_a1_na2),
.rd1_a1_a2 (rd3_a1_a2),
.rd1_na3 (rd3_na3),
.rd1_a3 (rd3_a3),
.rd1_na4_na5 (rd3_na4_na5),
.rd1_na4_a5 (rd3_na4_a5),
.rd1_a4_na5 (rd3_a4_na5),
.rd1_a4_a5 (rd3_a4_a5),

// write 1
.wr0_c_na0 (wr1_c_na0),
.wr0_c_a0 (wr1_c_a0),
.wr0_na1_na2 (wr1_na1_na2),
.wr0_na1_a2 (wr1_na1_a2),
.wr0_a1_na2 (wr1_a1_na2),
.wr0_a1_a2 (wr1_a1_a2),
.wr0_na3 (wr1_na3),
.wr0_a3 (wr1_a3),
.wr0_na4_na5 (wr1_na4_na5),
.wr0_na4_a5 (wr1_na4_a5),
.wr0_a4_na5 (wr1_a4_na5),
.wr0_a4_a5 (wr1_a4_a5)

);

// three hard arrays

regfile_4r2w_64x24 array0 (

// read 0
.rd0_c_na0 (rd0_c_na0),
.rd0_c_a0 (rd0_c_a0),
.rd0_na1_na2 (rd0_na1_na2),
.rd0_na1_a2 (rd0_na1_a2),
.rd0_a1_na2 (rd0_a1_na2),
.rd0_a1_a2 (rd0_a1_a2),
.rd0_na3 (rd0_na3),
.rd0_a3 (rd0_a3),
.rd0_na4_na5 (rd0_na4_na5),
.rd0_na4_a5 (rd0_na4_a5),
.rd0_a4_na5 (rd0_a4_na5),
.rd0_a4_a5 (rd0_a4_a5),
.rd0_dat (ra_rd_dat_0[0:23]),

// read 1
.rd1_c_na0 (rd1_c_na0),
.rd1_c_a0 (rd1_c_a0),
.rd1_na1_na2 (rd1_na1_na2),
.rd1_na1_a2 (rd1_na1_a2),
.rd1_a1_na2 (rd1_a1_na2),
.rd1_a1_a2 (rd1_a1_a2),
.rd1_na3 (rd1_na3),
.rd1_a3 (rd1_a3),
.rd1_na4_na5 (rd1_na4_na5),
.rd1_na4_a5 (rd1_na4_a5),
.rd1_a4_na5 (rd1_a4_na5),
.rd1_a4_a5 (rd1_a4_a5),
.rd1_dat (ra_rd_dat_1[0:23]),

// read 2
.rd2_c_na0 (rd2_c_na0),
.rd2_c_a0 (rd2_c_a0),
.rd2_na1_na2 (rd2_na1_na2),
.rd2_na1_a2 (rd2_na1_a2),
.rd2_a1_na2 (rd2_a1_na2),
.rd2_a1_a2 (rd2_a1_a2),
.rd2_na3 (rd2_na3),
.rd2_a3 (rd2_a3),
.rd2_na4_na5 (rd2_na4_na5),
.rd2_na4_a5 (rd2_na4_a5),
.rd2_a4_na5 (rd2_a4_na5),
.rd2_a4_a5 (rd2_a4_a5),
.rd2_dat (ra_rd_dat_2[0:23]),

// read 3
.rd3_c_na0 (rd3_c_na0),
.rd3_c_a0 (rd3_c_a0),
.rd3_na1_na2 (rd3_na1_na2),
.rd3_na1_a2 (rd3_na1_a2),
.rd3_a1_na2 (rd3_a1_na2),
.rd3_a1_a2 (rd3_a1_a2),
.rd3_na3 (rd3_na3),
.rd3_a3 (rd3_a3),
.rd3_na4_na5 (rd3_na4_na5),
.rd3_na4_a5 (rd3_na4_a5),
.rd3_a4_na5 (rd3_a4_na5),
.rd3_a4_a5 (rd3_a4_a5),
.rd3_dat (ra_rd_dat_3[0:23]),

// write 0
.wr0_c_na0 (wr0_c_na0),
.wr0_c_a0 (wr0_c_a0),
.wr0_na1_na2 (wr0_na1_na2),
.wr0_na1_a2 (wr0_na1_a2),
.wr0_a1_na2 (wr0_a1_na2),
.wr0_a1_a2 (wr0_a1_a2),
.wr0_na3 (wr0_na3),
.wr0_a3 (wr0_a3),
.wr0_na4_na5 (wr0_na4_na5),
.wr0_na4_a5 (wr0_na4_a5),
.wr0_a4_na5 (wr0_a4_na5),
.wr0_a4_a5 (wr0_a4_a5),
.wr0_dat (wr_dat_0_q[0:23]),

// write 1
.wr1_c_na0 (wr1_c_na0),
.wr1_c_a0 (wr1_c_a0),
.wr1_na1_na2 (wr1_na1_na2),
.wr1_na1_a2 (wr1_na1_a2),
.wr1_a1_na2 (wr1_a1_na2),
.wr1_a1_a2 (wr1_a1_a2),
.wr1_na3 (wr1_na3),
.wr1_a3 (wr1_a3),
.wr1_na4_na5 (wr1_na4_na5),
.wr1_na4_a5 (wr1_na4_a5),
.wr1_a4_na5 (wr1_a4_na5),
.wr1_a4_a5 (wr1_a4_a5),
.wr1_dat (wr_dat_1_q[0:23])

);

regfile_4r2w_64x24 array1 (

// predecoded address
// read 0
.rd0_c_na0 (rd0_c_na0),
.rd0_c_a0 (rd0_c_a0),
.rd0_na1_na2 (rd0_na1_na2),
.rd0_na1_a2 (rd0_na1_a2),
.rd0_a1_na2 (rd0_a1_na2),
.rd0_a1_a2 (rd0_a1_a2),
.rd0_na3 (rd0_na3),
.rd0_a3 (rd0_a3),
.rd0_na4_na5 (rd0_na4_na5),
.rd0_na4_a5 (rd0_na4_a5),
.rd0_a4_na5 (rd0_a4_na5),
.rd0_a4_a5 (rd0_a4_a5),
.rd0_dat (ra_rd_dat_0[24:47]),

// read 1
.rd1_c_na0 (rd1_c_na0),
.rd1_c_a0 (rd1_c_a0),
.rd1_na1_na2 (rd1_na1_na2),
.rd1_na1_a2 (rd1_na1_a2),
.rd1_a1_na2 (rd1_a1_na2),
.rd1_a1_a2 (rd1_a1_a2),
.rd1_na3 (rd1_na3),
.rd1_a3 (rd1_a3),
.rd1_na4_na5 (rd1_na4_na5),
.rd1_na4_a5 (rd1_na4_a5),
.rd1_a4_na5 (rd1_a4_na5),
.rd1_a4_a5 (rd1_a4_a5),
.rd1_dat (ra_rd_dat_1[24:47]),

// read 2
.rd2_c_na0 (rd2_c_na0),
.rd2_c_a0 (rd2_c_a0),
.rd2_na1_na2 (rd2_na1_na2),
.rd2_na1_a2 (rd2_na1_a2),
.rd2_a1_na2 (rd2_a1_na2),
.rd2_a1_a2 (rd2_a1_a2),
.rd2_na3 (rd2_na3),
.rd2_a3 (rd2_a3),
.rd2_na4_na5 (rd2_na4_na5),
.rd2_na4_a5 (rd2_na4_a5),
.rd2_a4_na5 (rd2_a4_na5),
.rd2_a4_a5 (rd2_a4_a5),
.rd2_dat (ra_rd_dat_2[24:47]),

// read 3
.rd3_c_na0 (rd3_c_na0),
.rd3_c_a0 (rd3_c_a0),
.rd3_na1_na2 (rd3_na1_na2),
.rd3_na1_a2 (rd3_na1_a2),
.rd3_a1_na2 (rd3_a1_na2),
.rd3_a1_a2 (rd3_a1_a2),
.rd3_na3 (rd3_na3),
.rd3_a3 (rd3_a3),
.rd3_na4_na5 (rd3_na4_na5),
.rd3_na4_a5 (rd3_na4_a5),
.rd3_a4_na5 (rd3_a4_na5),
.rd3_a4_a5 (rd3_a4_a5),
.rd3_dat (ra_rd_dat_3[24:47]),

// write 0
.wr0_c_na0 (wr0_c_na0),
.wr0_c_a0 (wr0_c_a0),
.wr0_na1_na2 (wr0_na1_na2),
.wr0_na1_a2 (wr0_na1_a2),
.wr0_a1_na2 (wr0_a1_na2),
.wr0_a1_a2 (wr0_a1_a2),
.wr0_na3 (wr0_na3),
.wr0_a3 (wr0_a3),
.wr0_na4_na5 (wr0_na4_na5),
.wr0_na4_a5 (wr0_na4_a5),
.wr0_a4_na5 (wr0_a4_na5),
.wr0_a4_a5 (wr0_a4_a5),
.wr0_dat (wr_dat_0_q[24:47]),

// write 1
.wr1_c_na0 (wr1_c_na0),
.wr1_c_a0 (wr1_c_a0),
.wr1_na1_na2 (wr1_na1_na2),
.wr1_na1_a2 (wr1_na1_a2),
.wr1_a1_na2 (wr1_a1_na2),
.wr1_a1_a2 (wr1_a1_a2),
.wr1_na3 (wr1_na3),
.wr1_a3 (wr1_a3),
.wr1_na4_na5 (wr1_na4_na5),
.wr1_na4_a5 (wr1_na4_a5),
.wr1_a4_na5 (wr1_a4_na5),
.wr1_a4_a5 (wr1_a4_a5),
.wr1_dat (wr_dat_1_q[24:47])

);

regfile_4r2w_64x24 array2 (

// read 0
.rd0_c_na0 (rd0_c_na0),
.rd0_c_a0 (rd0_c_a0),
.rd0_na1_na2 (rd0_na1_na2),
.rd0_na1_a2 (rd0_na1_a2),
.rd0_a1_na2 (rd0_a1_na2),
.rd0_a1_a2 (rd0_a1_a2),
.rd0_na3 (rd0_na3),
.rd0_a3 (rd0_a3),
.rd0_na4_na5 (rd0_na4_na5),
.rd0_na4_a5 (rd0_na4_a5),
.rd0_a4_na5 (rd0_a4_na5),
.rd0_a4_a5 (rd0_a4_a5),
.rd0_dat (ra_rd_dat_0[48:71]),

// read 1
.rd1_c_na0 (rd1_c_na0),
.rd1_c_a0 (rd1_c_a0),
.rd1_na1_na2 (rd1_na1_na2),
.rd1_na1_a2 (rd1_na1_a2),
.rd1_a1_na2 (rd1_a1_na2),
.rd1_a1_a2 (rd1_a1_a2),
.rd1_na3 (rd1_na3),
.rd1_a3 (rd1_a3),
.rd1_na4_na5 (rd1_na4_na5),
.rd1_na4_a5 (rd1_na4_a5),
.rd1_a4_na5 (rd1_a4_na5),
.rd1_a4_a5 (rd1_a4_a5),
.rd1_dat (ra_rd_dat_1[48:71]),

// read 2
.rd2_c_na0 (rd2_c_na0),
.rd2_c_a0 (rd2_c_a0),
.rd2_na1_na2 (rd2_na1_na2),
.rd2_na1_a2 (rd2_na1_a2),
.rd2_a1_na2 (rd2_a1_na2),
.rd2_a1_a2 (rd2_a1_a2),
.rd2_na3 (rd2_na3),
.rd2_a3 (rd2_a3),
.rd2_na4_na5 (rd2_na4_na5),
.rd2_na4_a5 (rd2_na4_a5),
.rd2_a4_na5 (rd2_a4_na5),
.rd2_a4_a5 (rd2_a4_a5),
.rd2_dat (ra_rd_dat_2[48:71]),

// read 3
.rd3_c_na0 (rd3_c_na0),
.rd3_c_a0 (rd3_c_a0),
.rd3_na1_na2 (rd3_na1_na2),
.rd3_na1_a2 (rd3_na1_a2),
.rd3_a1_na2 (rd3_a1_na2),
.rd3_a1_a2 (rd3_a1_a2),
.rd3_na3 (rd3_na3),
.rd3_a3 (rd3_a3),
.rd3_na4_na5 (rd3_na4_na5),
.rd3_na4_a5 (rd3_na4_a5),
.rd3_a4_na5 (rd3_a4_na5),
.rd3_a4_a5 (rd3_a4_a5),
.rd3_dat (ra_rd_dat_3[48:71]),

// write 0
.wr0_c_na0 (wr0_c_na0),
.wr0_c_a0 (wr0_c_a0),
.wr0_na1_na2 (wr0_na1_na2),
.wr0_na1_a2 (wr0_na1_a2),
.wr0_a1_na2 (wr0_a1_na2),
.wr0_a1_a2 (wr0_a1_a2),
.wr0_na3 (wr0_na3),
.wr0_a3 (wr0_a3),
.wr0_na4_na5 (wr0_na4_na5),
.wr0_na4_a5 (wr0_na4_a5),
.wr0_a4_na5 (wr0_a4_na5),
.wr0_a4_a5 (wr0_a4_a5),
.wr0_dat (wr_dat_0_q[48:71]),

// write 1
.wr1_c_na0 (wr1_c_na0),
.wr1_c_a0 (wr1_c_a0),
.wr1_na1_na2 (wr1_na1_na2),
.wr1_na1_a2 (wr1_na1_a2),
.wr1_a1_na2 (wr1_a1_na2),
.wr1_a1_a2 (wr1_a1_a2),
.wr1_na3 (wr1_na3),
.wr1_a3 (wr1_a3),
.wr1_na4_na5 (wr1_na4_na5),
.wr1_na4_a5 (wr1_na4_a5),
.wr1_a4_na5 (wr1_a4_na5),
.wr1_a4_a5 (wr1_a4_a5),
.wr1_dat (wr_dat_1_q[48:71])

);

endmodule

@ -0,0 +1,169 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.


// Local BIST for arrays
// Pass array inputs through, or generate locally for test/manual access.
// May want status_valid, ctl_valid sigs.
// Want separate cmds for enter/exit functional?
// ctl:
// 00000000 - functional mode
// 800000aa - read adr aa
// 900000aa - write adr aa (next 3 cycs are data)
// F00000tt - run bist test tt
//
// status:
//
//

`timescale 1 ns / 1 ns

`include "toysram.vh"

module ra_bist_ddr (

clk,
reset,
ctl,
status,
rd0_enb_in,
rd0_adr_in,
rd1_enb_in,
rd1_adr_in,
rd2_enb_in,
rd2_adr_in,
rd3_enb_in,
rd3_adr_in,
wr0_enb_in,
wr0_adr_in,
wr0_dat_in,
wr1_enb_in,
wr1_adr_in,
wr1_dat_in,
rd0_enb_out,
rd0_adr_out,
rd0_dat,
rd1_enb_out,
rd1_adr_out,
rd1_dat,
rd2_enb_out,
rd2_adr_out,
rd2_dat,
rd3_enb_out,
rd3_adr_out,
rd3_dat,
wr0_enb_out,
wr0_adr_out,
wr0_dat_out,
wr1_enb_out,
wr1_adr_out,
wr1_dat_out

);

parameter GENMODE = `GENMODE; // 0=NoDelay, 1=Delay

input clk;
input reset;
input [0:31] ctl;

input rd0_enb_in;
input [0:5] rd0_adr_in;
input rd1_enb_in;
input [0:5] rd1_adr_in;
input rd2_enb_in;
input [0:5] rd2_adr_in;
input rd3_enb_in;
input [0:5] rd3_adr_in;
input wr0_enb_in;
input [0:5] wr0_adr_in;
input [0:71] wr0_dat_in;
input wr1_enb_in;
input [0:5] wr1_adr_in;
input [0:71] wr1_dat_in;

output [0:31] status;
output rd0_enb_out;
output [0:5] rd0_adr_out;
input [0:71] rd0_dat;
output rd1_enb_out;
output [0:5] rd1_adr_out;
input [0:71] rd1_dat;
output rd2_enb_out;
output [0:5] rd2_adr_out;
input [0:71] rd2_dat;
output rd3_enb_out;
output [0:5] rd3_adr_out;
input [0:71] rd3_dat;
output wr0_enb_out;
output [0:5] wr0_adr_out;
output [0:71] wr0_dat_out;
output wr1_enb_out;
output [0:5] wr1_adr_out;
output [0:71] wr1_dat_out;

reg [0:5] seq_q;
wire [0:5] seq_d;
wire active;
wire bist_rd0_enb;
wire [0:5] bist_rd0_adr;
wire bist_rd1_enb;
wire [0:5] bist_rd1_adr;
wire bist_rd2_enb;
wire [0:5] bist_rd2_adr;
wire bist_rd3_enb;
wire [0:5] bist_rd3_adr;
wire bist_wr0_enb;
wire [0:5] bist_wr0_adr;
wire [0:71] bist_wr0_dat;
wire bist_wr1_enb;
wire [0:5] bist_wr1_adr;
wire [0:71] bist_wr1_dat;

// ff
always @ (posedge clk) begin
if (reset)
seq_q <= 6'h3F;
else
seq_q <= seq_d;
end

// do something
assign seq_d = seq_q;
assign active = seq_q != 6'h3F;
assign status = 0;

// outputs
assign rd0_enb_out = (active) ? bist_rd0_enb : rd0_enb_in;
assign rd0_adr_out = (active) ? bist_rd0_adr : rd0_adr_in;
assign rd1_enb_out = (active) ? bist_rd1_enb : rd1_enb_in;
assign rd1_adr_out = (active) ? bist_rd1_adr : rd1_adr_in;
assign rd2_enb_out = (active) ? bist_rd2_enb : rd2_enb_in;
assign rd2_adr_out = (active) ? bist_rd2_adr : rd2_adr_in;
assign rd3_enb_out = (active) ? bist_rd3_enb : rd3_enb_in;
assign rd3_adr_out = (active) ? bist_rd3_adr : rd3_adr_in;
assign wr0_enb_out = (active) ? bist_wr0_enb : wr0_enb_in;
assign wr0_adr_out = (active) ? bist_wr0_adr : wr0_adr_in;
assign wr0_dat_out = (active) ? bist_wr0_dat : wr0_dat_in;
assign wr1_enb_out = (active) ? bist_wr1_enb : wr1_enb_in;
assign wr1_adr_out = (active) ? bist_wr1_adr : wr1_adr_in;
assign wr1_dat_out = (active) ? bist_wr1_dat : wr1_dat_in;

endmodule

@ -0,0 +1,123 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.


// Local BIST for arrays
// Pass array inputs through, or generate locally for test/manual access.
// May want status_valid, ctl_valid sigs.
// Want separate cmds for enter/exit functional?
// ctl:
// 00000000 - functional mode
// 800000aa - read adr aa
// 900000aa - write adr aa (next 3 cycs are data)
// F00000tt - run bist test tt
//
// status:
//
//

`timescale 1 ns / 1 ns

`include "toysram.vh"

module ra_bist_sdr (

clk,
reset,
ctl,
status,
rd0_enb_in,
rd0_adr_in,
rd1_enb_in,
rd1_adr_in,
wr0_enb_in,
wr0_adr_in,
wr0_dat_in,
rd0_enb_out,
rd0_adr_out,
rd0_dat,
rd1_enb_out,
rd1_adr_out,
rd1_dat,
wr0_enb_out,
wr0_adr_out,
wr0_dat_out

);

parameter GENMODE = `GENMODE; // 0=NoDelay, 1=Delay

input clk;
input reset;
input [31:0] ctl;

input rd0_enb_in;
input [5:0] rd0_adr_in;
input rd1_enb_in;
input [5:0] rd1_adr_in;
input wr0_enb_in;
input [5:0] wr0_adr_in;
input [71:0] wr0_dat_in;

output [31:0] status;
output rd0_enb_out;
output [5:0] rd0_adr_out;
input [71:0] rd0_dat;
output rd1_enb_out;
output [5:0] rd1_adr_out;
input [71:0] rd1_dat;
output wr0_enb_out;
output [5:0] wr0_adr_out;
output [71:0] wr0_dat_out;

reg [5:0] seq_q;
wire [5:0] seq_d;
wire active;
wire bist_rd0_enb;
wire [5:0] bist_rd0_adr;
wire bist_rd1_enb;
wire [5:0] bist_rd1_adr;
wire bist_wr0_enb;
wire [5:0] bist_wr0_adr;
wire [71:0] bist_wr0_dat;

// ff
always @ (posedge clk) begin
if (reset)
seq_q <= 6'h3F;
else
seq_q <= seq_d;
end

// do something
assign seq_d = seq_q;
assign active = seq_q != 6'h3F;
assign status = 0;

// outputs
assign rd0_enb_out = (active) ? bist_rd0_enb : rd0_enb_in;
assign rd0_adr_out = (active) ? bist_rd0_adr : rd0_adr_in;
assign rd1_enb_out = (active) ? bist_rd1_enb : rd1_enb_in;
assign rd1_adr_out = (active) ? bist_rd1_adr : rd1_adr_in;
assign wr0_enb_out = (active) ? bist_wr0_enb : wr0_enb_in;
assign wr0_adr_out = (active) ? bist_wr0_adr : wr0_adr_in;
assign wr0_dat_out = (active) ? bist_wr0_dat : wr0_dat_in;
//assign rd0_dat = (active) ? haven't done anything here yet

endmodule

@ -0,0 +1,154 @@
`timescale 1 ns / 1 ns

`include "toysram.vh"

module ra_bist_sdr_32x32 (

clk,
reset,
ctl,
status,
rd0_enb_in,
rd0_adr_in,
rd1_enb_in,
rd1_adr_in,
wr0_enb_in,
wr0_adr_in,
wr0_dat_in,
rd0_enb_out,
rd0_adr_out,
rd0_dat,
rd1_enb_out,
rd1_adr_out,
rd1_dat,
wr0_enb_out,
wr0_adr_out,
wr0_dat_out,
bist_fail,
bist_passed
);

parameter GENMODE = `GENMODE; // 0=NoDelay, 1=Delay

input clk;
input reset;
input [0:31] ctl;

input rd0_enb_in;
input [0:4] rd0_adr_in;
input rd1_enb_in;
input [0:4] rd1_adr_in;
input wr0_enb_in;
input [0:4] wr0_adr_in;
input [0:31] wr0_dat_in;

output [0:31] status;
output rd0_enb_out;
output [0:4] rd0_adr_out;
input [0:31] rd0_dat;
output rd1_enb_out;
output [0:4] rd1_adr_out;
input [0:31] rd1_dat;
output wr0_enb_out;
output [0:4] wr0_adr_out;
output [0:31] wr0_dat_out;

reg [0:5] seq_q;
wire [0:5] seq_d;
wire active;
wire bist_rd0_enb;
wire [0:4] bist_rd0_adr;
wire bist_rd1_enb;
wire [0:4] bist_rd1_adr;
wire bist_wr0_enb;
wire [0:4] bist_wr0_adr;
wire [0:31] bist_wr0_dat;

output bist_fail;
output bist_passed;

// ff
always @ (posedge clk) begin
if (reset)
seq_q <= 6'h3F;
else
seq_q <= seq_d;
end

// do something
assign seq_d = seq_q;
assign active = seq_q != 6'h3F;
assign status = 0;

/*
A more practical implementation:
make an up/down counter for interating through addresses.

state machine for each part of the step: the best part about this is that
states could be added for implementation withb GPIO/wishbone for external
controls/different steps.

s0: write 0s up (Idle)
s1: write 1s down
s2: read 1s down/check
s3: write 0s up
s4: read 0s up/check
s5: write 1s up
s6: read 1s up/check
s7: flags


*/
/*
Outline for BIST
----------------------------------------------------------------------
first off, how I think this thing is supposed to work is that we need a
final flag signifying the BIST is successfully ran, and one where it fa-
ils.
uhhhhhh something's gotta happen here
like:
enable write data
assign all 0s to addr 0x00-0x3F (using signals wr0_adr_in &
wr0_dat_in)

enable read data (rd0_enb_in)

read addr 0x00-0x3f one at a time (rd0_adr_in/out and rd0_dat)

after each read, write all 1s to each addr 0x00-0x3F
^^this happens after each read, so like, read data at 0x00, write all
ones to 0x00, step forward to next address, 0x01 (process A)

for each valid read of all 0s, save output in a 6-bit bus that counts
up for each valid read or something

now, step through the exact same read/write process but replacing
all 1s with all 0s.

read all 0s through same process (NO WRITE CHANGE THIS TIME)

Now, write all 1s to each address 0x3F-0x00.
repeat the process A, reading data at each address,replacing all 1s
with all 0s for each address 0x3F-0x00, and keeping track of whether
working or not.

finally, read all 0s through same process (NO WRITE HERE EITHER)
at the end, there's gotta be some kinda comparison where you check
that the tests were valid for both ascending and descending runs.

if both are valid, flag BIST_PASSED. if one of the runs is invalid,
flag BIST_FAIL_UP, or BIST_FAIL_DOWN or both.

*/

// outputs
assign rd0_enb_out = (active) ? bist_rd0_enb : rd0_enb_in;
assign rd0_adr_out = (active) ? bist_rd0_adr : rd0_adr_in;
assign rd1_enb_out = (active) ? bist_rd1_enb : rd1_enb_in;
assign rd1_adr_out = (active) ? bist_rd1_adr : rd1_adr_in;
assign wr0_enb_out = (active) ? bist_wr0_enb : wr0_enb_in;
assign wr0_adr_out = (active) ? bist_wr0_adr : wr0_adr_in;
assign wr0_dat_out = (active) ? bist_wr0_dat : wr0_dat_in;
//assign rd0_dat = (active) ? haven't done anything here yet

endmodule

@ -0,0 +1,160 @@
`timescale 1 ns / 1 ns

`include "toysram.vh"

module ra_bist_sdr (

clk,
reset, picture,
ctl,
status,
rd0_enb_in,
rd0_adr_in,
rd1_enb_in,
rd1_adr_in,
wr0_enb_in,
wr0_adr_in,
wr0_dat_in,
rd0_enb_out,
rd0_adr_out,
rd0_dat,
rd1_enb_out,
rd1_adr_out,
rd1_dat,
wr0_enb_out,
wr0_adr_out,
wr0_dat_out,
bist_fail,
bist_passed


);

parameter GENMODE = `GENMODE; // 0=NoDelay, 1=Delay

input clk;
input reset;
input [31:0] ctl;

input rd0_enb_in;
input [5:0] rd0_adr_in;
input rd1_enb_in;
input [5:0] rd1_adr_in;
input wr0_enb_in;
input [5:0] wr0_adr_in;
input [71:0] wr0_dat_in;

output [31:0] status;
output rd0_enb_out;
output [5:0] rd0_adr_out;
input [71:0] rd0_dat;
output rd1_enb_out;
output [5:0] rd1_adr_out;
input [71:0] rd1_dat;
output wr0_enb_out;
output [5:0] wr0_adr_out;
output [71:0] wr0_dat_out;



reg [5:0] seq_q;
wire [5:0] seq_d;
wire active;
wire bist_rd0_enb;
wire [5:0] bist_rd0_adr;
wire bist_rd1_enb;
wire [5:0] bist_rd1_adr;
wire bist_wr0_enb;
wire [5:0] bist_wr0_adr;
wire [71:0] bist_wr0_dat;

output bist_fail;
output bist_passed;

// ff
always @ (posedge clk) begin
if (reset)
seq_q <= 6'h3F;
else
seq_q <= seq_d;
end

// do something
assign seq_d = seq_q;
assign active = seq_q != 6'h3F;
assign status = 0;

assign wr0_enb_in = 1;

/*
A more practical implementation:
make an up/down counter for interating through addresses.

state machine for each part of the step: the best part about this is that
states could be added for implementation withb GPIO/wishbone for external
controls/different steps.

s0: write 0s up (Idle)
s1: write 1s down
s2: read 1s down/check
s3: write 0s up
s4: read 0s up/check
s5: write 1s up
s6: read 1s up/check
s7: flags


*/
/*
Outline for BIST
----------------------------------------------------------------------
first off, how I think this thing is supposed to work is that we need a
final flag signifying the BIST is successfully ran, and one where it fa-
ils.
uhhhhhh something's gotta happen here
like:
enable write data
assign all 0s to addr 0x00-0x3F (using signals wr0_adr_in &
wr0_dat_in)

enable read data (rd0_enb_in)

read addr 0x00-0x3f one at a time (rd0_adr_in/out and rd0_dat)

after each read, write all 1s to each addr 0x00-0x3F
^^this happens after each read, so like, read data at 0x00, write all
ones to 0x00, step forward to next address, 0x01 (process A)

for each valid read of all 0s, save output in a 6-bit bus that counts
up for each valid read or something

now, step through the exact same read/write process but replacing
all 1s with all 0s.

read all 0s through same process (NO WRITE CHANGE THIS TIME)

Now, write all 1s to each address 0x3F-0x00.
repeat the process A, reading data at each address,replacing all 1s
with all 0s for each address 0x3F-0x00, and keeping track of whether
working or not.

finally, read all 0s through same process (NO WRITE HERE EITHER)
at the end, there's gotta be some kinda comparison where you check
that the tests were valid for both ascending and descending runs.

if both are valid, flag BIST_PASSED. if one of the runs is invalid,
flag BIST_FAIL_UP, or BIST_FAIL_DOWN or both.

*/

// outputs
assign rd0_enb_out = (active) ? bist_rd0_enb : rd0_enb_in;
assign rd0_adr_out = (active) ? bist_rd0_adr : rd0_adr_in;
assign rd1_enb_out = (active) ? bist_rd1_enb : rd1_enb_in;
assign rd1_adr_out = (active) ? bist_rd1_adr : rd1_adr_in;
assign wr0_enb_out = (active) ? bist_wr0_enb : wr0_enb_in;
assign wr0_adr_out = (active) ? bist_wr0_adr : wr0_adr_in;
assign wr0_dat_out = (active) ? bist_wr0_dat : wr0_dat_in;
//assign rd0_dat = (active) ? haven't done anything here yet

endmodule

@ -0,0 +1,65 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.


// Local Configuration for arrays
//

`timescale 1 ns / 1 ns

`include "toysram.vh"

module ra_cfg_ddr (

clk,
reset,
cfg_wr,
cfg_dat,
cfg

);

parameter GENMODE = `GENMODE; // 0=NoDelay, 1=Delay
parameter INIT = `LCBDDR_CONFIGWIDTH'b0;

input clk;
input reset;
input cfg_wr;
input [0:`LCBDDR_CONFIGWIDTH-1] cfg_dat;
output [0:`LCBDDR_CONFIGWIDTH-1] cfg;

reg [0:`LCBDDR_CONFIGWIDTH-1] cfg_q;
wire [0:`LCBDDR_CONFIGWIDTH-1] cfg_d;

// ff
always @ (posedge clk) begin
if (reset)
cfg_q <= INIT;
else
cfg_q <= cfg_d;
end

// do something
assign cfg_d = (cfg_wr) ? cfg_dat : cfg_q;

// outputs
assign cfg = cfg_q;

endmodule

@ -0,0 +1,65 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.


// Local Configuration for arrays
//

`timescale 1 ns / 1 ns

`include "toysram.vh"

module ra_cfg_sdr(

clk,
reset,
cfg_wr,
cfg_dat,
cfg

);

parameter GENMODE = `GENMODE; // 0=NoDelay, 1=Delay
parameter INIT = `LCBSDR_CONFIGWIDTH'b0;

input clk;
input reset;
input cfg_wr;
input [0:`LCBSDR_CONFIGWIDTH-1] cfg_dat;
output [0:`LCBSDR_CONFIGWIDTH-1] cfg;

reg [0:`LCBSDR_CONFIGWIDTH-1] cfg_q;
wire [0:`LCBSDR_CONFIGWIDTH-1] cfg_d;

// ff
always @ (posedge clk) begin
if (reset)
cfg_q <= INIT;
else
cfg_q <= cfg_d;
end

// do something
assign cfg_d = (cfg_wr) ? cfg_dat : cfg_q;

// outputs
assign cfg = cfg_q;

endmodule

@ -0,0 +1,51 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.


// Delay Block for Array Strobe

`timescale 1 ns / 1 ns

`include "toysram.vh"

module ra_delay(

i,
o

);

parameter GENMODE = `GENMODE; // 0=NoDelay, 1=Delay

input i;
output o;

// generate strobe
generate

if (GENMODE == 0)
assign o = 1;
else begin
assign o = 1'bX; //wtf this will be a specific tech cell instantiation
end

endgenerate

endmodule

@ -0,0 +1,124 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.


// Local Clock Buffer for arrays
// Generates sim or implementation logic, depending on GENMODE.
// el_sel is early/late select (first/second pulse of cycle)

`timescale 1 ns / 1 ns

`include "toysram.vh"

module ra_lcb_ddr (

clk, // =clk2x for genmode=0
reset, // used for genmode=1? seems not; could kill strobe with it
cfg,
strobe,
el_sel

);

parameter GENMODE = `GENMODE; // 0=NoDelay, 1=Delay

input clk;
input reset;
input [0:`LCBDDR_CONFIGWIDTH-1] cfg;
output strobe;
output el_sel;

//generate
// if (GENMODE == 0)
reg el_sel_q;
//endgenerate

wire clk_dly;
wire o0;
wire o1;
wire clk_dly2;

// generate strobe
generate

if (GENMODE == 0)
assign strobe = !clk & !reset; // strobe is inverted clk2x
else begin

// generate a strobe for ddr - is late pulse a delay of this, or gen'd independently from clk??
// clk -> [delay] -> * --------------------- * -- and ---
// | -- [delay] --- inv ---|

// first edge delay
ra_delay d0 (
.i(clk),
.o(o0)
);
// remaining
/*
genvar i;
for (i = 1; i < `MAX_PULSE_DELAYS-1; i = i + 1) begin : d1
ra_delay (
.i()
.o()
)
end
*/
// select tap based on cfg

assign clk_dly = o0;

// first width delay
ra_delay w0 (
.i(clk_dly),
.o(o1)
);

// remaining
// select tap based on cfg

assign clk_dly2 = o1;

// create strobe
assign strobe = clk_dly & !clk_dly2;

end

endgenerate

// generate el_sel
generate

if (GENMODE == 0) begin
always @ (posedge clk)
if (reset)
el_sel_q <= 1'b0;
else
el_sel_q <= !el_sel_q;
assign el_sel = el_sel_q;
end else begin

// el_sel is delayed version of clk

end

endgenerate

endmodule

@ -0,0 +1,98 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.


// Local Clock Buffer for arrays
// Generates sim or implementation logic, depending on GENMODE.

`timescale 1 ns / 1 ns

`include "toysram.vh"

module ra_lcb_sdr (

clk,
reset,
cfg,
strobe

);

parameter GENMODE = `GENMODE; // 0=NoDelay, 1=Delay
input clk;
input reset;
input [0:`LCBSDR_CONFIGWIDTH-1] cfg;
output strobe;

wire clk_dly;
wire o0;
wire o1;
wire clk_dly2;

// generate strobe
generate

if (GENMODE == 0)
assign strobe = !clk & !reset;
else begin

// generate a strobe for sdr
// clk -> [delay] -> * --------------------- * -- and ---
// | -- [delay] --- inv ---|

// first edge delay
ra_delay d0 (
.i(i),
.o(o0)
);
// remaining
/*
genvar i;
for (i = 1; i < `MAX_PULSE_DELAYS-1; i = i + 1) begin : d1
ra_delay (
.i()
.o()
)
end
*/
// select tap based on cfg

assign clk_dly = o0;

// first width delay
ra_delay w0 (
.i(clk_dly),
.o(o1)
);

// remaining
// select tap based on cfg

assign clk_dly2 = o1;


// create strobe
assign strobe = clk_dly & !clk_dly2;

end

endgenerate

endmodule

@ -0,0 +1,194 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.


// Behavioral for 32x32 toysram (sdr or ddr)
// I/Os are equivalent to physical macro
// This version has the enables encoded in a0.

`timescale 1 ps / 1 ps

module regfile_2r1w_32x32(

rd0_c_na0,
rd0_c_a0,
rd0_na1_na2,
rd0_na1_a2,
rd0_a1_na2,
rd0_a1_a2,
rd0_na3,
rd0_a3,
rd0_na4,
rd0_a4,
rd0_dat,

rd1_c_na0,
rd1_c_a0,
rd1_na1_na2,
rd1_na1_a2,
rd1_a1_na2,
rd1_a1_a2,
rd1_na3,
rd1_a3,
rd1_na4,
rd1_a4,
rd1_dat,

wr0_c_na0,
wr0_c_a0,
wr0_na1_na2,
wr0_na1_a2,
wr0_a1_na2,
wr0_a1_a2,
wr0_na3,
wr0_a3,
wr0_na4,
wr0_a4,
wr0_dat

);

// -- predecoded address
// -- four groups of one hot encoded signals

// -- read address 0
input rd0_c_na0;
input rd0_c_a0;

input rd0_na1_na2;
input rd0_na1_a2;
input rd0_a1_na2;
input rd0_a1_a2;

input rd0_na3;
input rd0_a3;

input rd0_na4;
input rd0_a4;

// -- read address 1
input rd1_c_na0;
input rd1_c_a0;

input rd1_na1_na2;
input rd1_na1_a2;
input rd1_a1_na2;
input rd1_a1_a2;

input rd1_na3;
input rd1_a3;

input rd1_na4;
input rd1_a4;

// -- write address 0
input wr0_c_na0;
input wr0_c_a0;

input wr0_na1_na2;
input wr0_na1_a2;
input wr0_a1_na2;
input wr0_a1_a2;

input wr0_na3;
input wr0_a3;

input wr0_na4;
input wr0_a4;

// -- data ports
output [0:31] rd0_dat;
output [0:31] rd1_dat;
input [0:31] wr0_dat;

wire rd0_enable;
wire rd1_enable;
wire wr0_enable;

wire rd0_a0;
wire rd0_a1;
wire rd0_a2;
// wire rd0_a3;
// wire rd0_a4;

wire rd1_a0;
wire rd1_a1;
wire rd1_a2;
// wire rd1_a3;
// wire rd1_a4;

wire wr0_a0;
wire wr0_a1;
wire wr0_a2;
//wire wr0_a3;
// wire wr0_a4;

// array cells
reg[0:31] mem[0:31];

//wtf:icarus $dumpvars cannot dump a vpiMemory
generate
genvar i;
for (i = 0; i < 31; i=i+1) begin: ra
wire [0:31] q;
assign q = mem[i];
end
endgenerate

// decode inputs, rd0
assign rd0_enable = rd0_c_a0 | rd0_c_na0;
assign rd0_a0 = rd0_c_a0;
assign rd0_a1 = rd0_a1_a2 | rd0_a1_na2;
assign rd0_a2 = rd0_a1_a2 | rd0_na1_a2;
// assign rd0_a3 = rd0_a3;
// assign rd0_a4 = rd0_a4;

// deocde inputs, rd1
assign rd1_enable = rd1_c_a0 | rd1_c_na0;
assign rd1_a0 = rd1_c_a0;
assign rd1_a1 = rd1_a1_a2 | rd1_a1_na2;
assign rd1_a2 = rd1_a1_a2 | rd1_na1_a2;
// assign rd1_a3 = rd1_a3;
// assign rd1_a4 = rd1_a4;

// decode inputs, wr0
assign wr0_enable = wr0_c_a0 | wr0_c_na0;
assign wr0_a0 = wr0_c_a0;
assign wr0_a1 = wr0_a1_a2 | wr0_a1_na2;
assign wr0_a2 = wr0_a1_a2 | wr0_na1_a2;
// assign wr0_a3 = wr0_a3;
// assign wr0_a4 = wr0_a4;

// read ports
assign rd0_dat = (rd0_enable) ? mem[{rd0_a0, rd0_a1, rd0_a2, rd0_a3, rd0_a4}] : 31'bX;
assign rd1_dat = (rd1_enable) ? mem[{rd1_a0, rd1_a1, rd1_a2, rd1_a3, rd1_a4}] : 31'bX;

// write port
always @* begin
if (wr0_enable) begin
#10; // make sure addr settles
if (wr0_enable) begin
mem[{wr0_a0, wr0_a1, wr0_a2, wr0_a3, wr0_a4}] <= wr0_dat;
//$display("%0d wr0_en=%h @%0h=%0h", $time, wr0_enable, {wr0_a0, wr0_a1, wr0_a2, wr0_a3, wr0_a4}, mem[{wr0_a0, wr0_a1, wr0_a2, wr0_a3, wr0_a4}]);
end
end
end

endmodule

@ -0,0 +1,204 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.


// Behavioral for 64x24 toysram (sdr or ddr)
// I/Os are equivalent to physical macro
// This version has the enables encoded in a0.

`timescale 1 ps / 1 ps

module regfile_2r1w_64x24(

rd0_c_na0,
rd0_c_a0,
rd0_na1_na2,
rd0_na1_a2,
rd0_a1_na2,
rd0_a1_a2,
rd0_na3,
rd0_a3,
rd0_na4_na5,
rd0_na4_a5,
rd0_a4_na5,
rd0_a4_a5,
rd0_dat,

rd1_c_na0,
rd1_c_a0,
rd1_na1_na2,
rd1_na1_a2,
rd1_a1_na2,
rd1_a1_a2,
rd1_na3,
rd1_a3,
rd1_na4_na5,
rd1_na4_a5,
rd1_a4_na5,
rd1_a4_a5,
rd1_dat,

wr0_c_na0,
wr0_c_a0,
wr0_na1_na2,
wr0_na1_a2,
wr0_a1_na2,
wr0_a1_a2,
wr0_na3,
wr0_a3,
wr0_na4_na5,
wr0_na4_a5,
wr0_a4_na5,
wr0_a4_a5,
wr0_dat

);

// -- predecoded address
// -- four groups of one hot encoded signals
// -- read address 0
input rd0_c_na0;
input rd0_c_a0;

input rd0_na1_na2;
input rd0_na1_a2;
input rd0_a1_na2;
input rd0_a1_a2;

input rd0_na3;
input rd0_a3;

input rd0_na4_na5;
input rd0_na4_a5;
input rd0_a4_na5;
input rd0_a4_a5;

// -- read address 1
input rd1_c_na0;
input rd1_c_a0;

input rd1_na1_na2;
input rd1_na1_a2;
input rd1_a1_na2;
input rd1_a1_a2;

input rd1_na3;
input rd1_a3;

input rd1_na4_na5;
input rd1_na4_a5;
input rd1_a4_na5;
input rd1_a4_a5;

// -- write address 0
input wr0_c_na0;
input wr0_c_a0;

input wr0_na1_na2;
input wr0_na1_a2;
input wr0_a1_na2;
input wr0_a1_a2;

input wr0_na3;
input wr0_a3;

input wr0_na4_na5;
input wr0_na4_a5;
input wr0_a4_na5;
input wr0_a4_a5;

// -- data ports
output [0:23] rd0_dat;
output [0:23] rd1_dat;
input [0:23] wr0_dat;

wire rd0_enable;
wire rd1_enable;
wire wr0_enable;

wire rd0_a0;
wire rd0_a1;
wire rd0_a2;
// wire rd0_a3;
wire rd0_a4;
wire rd0_a5;

wire rd1_a0;
wire rd1_a1;
wire rd1_a2;
// wire rd1_a3;
wire rd1_a4;
wire rd1_a5;

wire wr0_a0;
wire wr0_a1;
wire wr0_a2;
//wire wr0_a3;
wire wr0_a4;
wire wr0_a5;

// array cells
reg[0:23] mem[0:63];

// decode inputs, rd0
assign rd0_enable = rd0_c_a0 | rd0_c_na0;
assign rd0_a0 = rd0_c_a0;
assign rd0_a1 = rd0_a1_a2 | rd0_a1_na2;
assign rd0_a2 = rd0_a1_a2 | rd0_na1_a2;
// assign rd0_a3 = rd0_a3;
assign rd0_a4 = rd0_a4_a5 | rd0_a4_na5;
assign rd0_a5 = rd0_a4_a5 | rd0_na4_a5;

// deocde inputs, rd1
assign rd1_enable = rd1_c_a0 | rd1_c_na0;
assign rd1_a0 = rd1_c_a0;
assign rd1_a1 = rd1_a1_a2 | rd1_a1_na2;
assign rd1_a2 = rd1_a1_a2 | rd1_na1_a2;
// assign rd1_a3 = rd1_a3;
assign rd1_a4 = rd1_a4_a5 | rd1_a4_na5;
assign rd1_a5 = rd1_a4_a5 | rd1_na4_a5;


// decode inputs, wr0
assign wr0_enable = wr0_c_a0 | wr0_c_na0;
assign wr0_a0 = wr0_c_a0;
assign wr0_a1 = wr0_a1_a2 | wr0_a1_na2;
assign wr0_a2 = wr0_a1_a2 | wr0_na1_a2;
// assign wr0_a3 = wr0_a3;
assign wr0_a4 = wr0_a4_a5 | wr0_a4_na5;
assign wr0_a5 = wr0_a4_a5 | wr0_na4_a5;


// read ports
assign rd0_dat = (rd0_enable) ? mem[{rd0_a0, rd0_a1, rd0_a2, rd0_a3, rd0_a4, rd0_a5}] : 24'bX;
assign rd1_dat = (rd1_enable) ? mem[{rd1_a0, rd1_a1, rd1_a2, rd1_a3, rd1_a4, rd1_a5}] : 24'bX;

// write port
always @* begin
if (wr0_enable) begin
#10; // make sure addr settles
if (wr0_enable) begin
mem[{wr0_a0, wr0_a1, wr0_a2, wr0_a3, wr0_a4, wr0_a5}] <= wr0_dat;
//$display("%0d wr0_en=%h @%0h=%0h", $time, wr0_enable, {wr0_a0, wr0_a1, wr0_a2, wr0_a3, wr0_a4, wr0_a5}, mem[{wr0_a0, wr0_a1, wr0_a2, wr0_a3, wr0_a4, wr0_a5}]);
end
end
end

endmodule

@ -0,0 +1,335 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.


// Behavioral for 64x24 toysram (sdr or ddr)
// I/Os are equivalent to physical macro
// This version has the enables encoded in a0.

`timescale 1 ns / 1 ns

module regfile_4r2w_64x24 (

rd0_c_na0,
rd0_c_a0,
rd0_na1_na2,
rd0_na1_a2,
rd0_a1_na2,
rd0_a1_a2,
rd0_na3,
rd0_a3,
rd0_na4_na5,
rd0_na4_a5,
rd0_a4_na5,
rd0_a4_a5,
rd0_dat,

rd1_c_na0,
rd1_c_a0,
rd1_na1_na2,
rd1_na1_a2,
rd1_a1_na2,
rd1_a1_a2,
rd1_na3,
rd1_a3,
rd1_na4_na5,
rd1_na4_a5,
rd1_a4_na5,
rd1_a4_a5,
rd1_dat,

rd2_c_na0,
rd2_c_a0,
rd2_na1_na2,
rd2_na1_a2,
rd2_a1_na2,
rd2_a1_a2,
rd2_na3,
rd2_a3,
rd2_na4_na5,
rd2_na4_a5,
rd2_a4_na5,
rd2_a4_a5,
rd2_dat,

rd3_c_na0,
rd3_c_a0,
rd3_na1_na2,
rd3_na1_a2,
rd3_a1_na2,
rd3_a1_a2,
rd3_na3,
rd3_a3,
rd3_na4_na5,
rd3_na4_a5,
rd3_a4_na5,
rd3_a4_a5,
rd3_dat,

wr0_c_na0,
wr0_c_a0,
wr0_na1_na2,
wr0_na1_a2,
wr0_a1_na2,
wr0_a1_a2,
wr0_na3,
wr0_a3,
wr0_na4_na5,
wr0_na4_a5,
wr0_a4_na5,
wr0_a4_a5,
wr0_dat,

wr1_c_na0,
wr1_c_a0,
wr1_na1_na2,
wr1_na1_a2,
wr1_a1_na2,
wr1_a1_a2,
wr1_na3,
wr1_a3,
wr1_na4_na5,
wr1_na4_a5,
wr1_a4_na5,
wr1_a4_a5,
wr1_dat

);

// -- predecoded address
// -- four groups of one hot encoded signals
// -- read address 0
input rd0_c_na0;
input rd0_c_a0;
input rd0_na1_na2;
input rd0_na1_a2;
input rd0_a1_na2;
input rd0_a1_a2;
input rd0_na3;
input rd0_a3;
input rd0_na4_na5;
input rd0_na4_a5;
input rd0_a4_na5;
input rd0_a4_a5;

// -- read address 1
input rd1_c_na0;
input rd1_c_a0;
input rd1_na1_na2;
input rd1_na1_a2;
input rd1_a1_na2;
input rd1_a1_a2;
input rd1_na3;
input rd1_a3;
input rd1_na4_na5;
input rd1_na4_a5;
input rd1_a4_na5;
input rd1_a4_a5;

// -- read address 2
input rd2_c_na0;
input rd2_c_a0;
input rd2_na1_na2;
input rd2_na1_a2;
input rd2_a1_na2;
input rd2_a1_a2;
input rd2_na3;
input rd2_a3;
input rd2_na4_na5;
input rd2_na4_a5;
input rd2_a4_na5;
input rd2_a4_a5;

// -- read address 3
input rd3_c_na0;
input rd3_c_a0;
input rd3_na1_na2;
input rd3_na1_a2;
input rd3_a1_na2;
input rd3_a1_a2;
input rd3_na3;
input rd3_a3;
input rd3_na4_na5;
input rd3_na4_a5;
input rd3_a4_na5;
input rd3_a4_a5;

// -- write address 0
input wr0_c_na0;
input wr0_c_a0;
input wr0_na1_na2;
input wr0_na1_a2;
input wr0_a1_na2;
input wr0_a1_a2;
input wr0_na3;
input wr0_a3;
input wr0_na4_na5;
input wr0_na4_a5;
input wr0_a4_na5;
input wr0_a4_a5;

// -- write address 1
input wr1_c_na0;
input wr1_c_a0;
input wr1_na1_na2;
input wr1_na1_a2;
input wr1_a1_na2;
input wr1_a1_a2;
input wr1_na3;
input wr1_a3;
input wr1_na4_na5;
input wr1_na4_a5;
input wr1_a4_na5;
input wr1_a4_a5;

// -- data ports
output [0:23] rd0_dat;
output [0:23] rd1_dat;
output [0:23] rd2_dat;
output [0:23] rd3_dat;
input [0:23] wr0_dat;
input [0:23] wr1_dat;

wire rd0_enable;
wire rd1_enable;
wire rd2_enable;
wire rd3_enable;
wire wr0_enable;
wire wr1_enable;


wire rd0_a0;
wire rd0_a1;
wire rd0_a2;
// wire rd0_a3;
wire rd0_a4;
wire rd0_a5;

wire rd1_a0;
wire rd1_a1;
wire rd1_a2;
// wire rd1_a3;
wire rd1_a4;
wire rd1_a5;

wire rd2_a0;
wire rd2_a1;
wire rd2_a2;
// wire rd2_a3;
wire rd2_a4;
wire rd2_a5;

wire rd3_a0;
wire rd3_a1;
wire rd3_a2;
// wire rd3_a3;
wire rd3_a4;
wire rd3_a5;

wire wr0_a0;
wire wr0_a1;
wire wr0_a2;
//wire wr0_a3;
wire wr0_a4;
wire wr0_a5;

wire wr1_a0;
wire wr1_a1;
wire wr1_a2;
//wire wr1_a3;
wire wr1_a4;
wire wr1_a5;

// array cells
reg[0:23] mem[0:63];

// decode inputs, rd0
assign rd0_enable = rd0_c_a0 | rd0_c_na0;
assign rd0_a0 = rd0_c_a0;
assign rd0_a1 = rd0_a1_a2 | rd0_a1_na2;
assign rd0_a2 = rd0_a1_a2 | rd0_na1_a2;
// assign rd0_a3 = rd0_a3;
assign rd0_a4 = rd0_a4_a5 | rd0_a4_na5;
assign rd0_a5 = rd0_a4_a5 | rd0_na4_a5;

// deocde inputs, rd1
assign rd1_enable = rd1_c_a0 | rd1_c_na0;
assign rd1_a0 = rd1_c_a0;
assign rd1_a1 = rd1_a1_a2 | rd1_a1_na2;
assign rd1_a2 = rd1_a1_a2 | rd1_na1_a2;
// assign rd1_a3 = rd1_a3;
assign rd1_a4 = rd1_a4_a5 | rd1_a4_na5;
assign rd1_a5 = rd1_a4_a5 | rd1_na4_a5;

// deocde inputs, rd2
assign rd2_enable = rd2_c_a0 | rd2_c_na0;
assign rd2_a0 = rd2_c_a0;
assign rd2_a1 = rd2_a1_a2 | rd2_a1_na2;
assign rd2_a2 = rd2_a1_a2 | rd2_na1_a2;
// assign rd2_a3 = rd2_a3;
assign rd2_a4 = rd2_a4_a5 | rd2_a4_na5;
assign rd2_a5 = rd2_a4_a5 | rd2_na4_a5;

// deocde inputs, rd3
assign rd3_enable = rd3_c_a0 | rd3_c_na0;
assign rd3_a0 = rd3_c_a0;
assign rd3_a1 = rd3_a1_a2 | rd3_a1_na2;
assign rd3_a2 = rd3_a1_a2 | rd3_na1_a2;
// assign rd3_a3 = rd3_a3;
assign rd3_a4 = rd3_a4_a5 | rd3_a4_na5;
assign rd3_a5 = rd3_a4_a5 | rd3_na4_a5;

// decode inputs, wr0
assign wr0_enable = wr0_c_a0 | wr0_c_na0;
assign wr0_a0 = wr0_c_a0;
assign wr0_a1 = wr0_a1_a2 | wr0_a1_na2;
assign wr0_a2 = wr0_a1_a2 | wr0_na1_a2;
// assign wr0_a3 = wr0_a3;
assign wr0_a4 = wr0_a4_a5 | wr0_a4_na5;
assign wr0_a5 = wr0_a4_a5 | wr0_na4_a5;

// decode inputs, wr1
assign wr1_enable = wr1_c_a0 | wr1_c_na0;
assign wr1_a0 = wr1_c_a0;
assign wr1_a1 = wr1_a1_a2 | wr1_a1_na2;
assign wr1_a2 = wr1_a1_a2 | wr1_na1_a2;
// assign wr1_a3 = wr1_a3;
assign wr1_a4 = wr1_a4_a5 | wr1_a4_na5;
assign wr1_a5 = wr1_a4_a5 | wr1_na4_a5;

// read ports
assign rd0_dat = (rd0_enable) ? mem[{rd0_a0, rd0_a1, rd0_a2, rd0_a3, rd0_a4, rd0_a5}] : 24'bX;
assign rd1_dat = (rd1_enable) ? mem[{rd1_a0, rd1_a1, rd1_a2, rd1_a3, rd1_a4, rd1_a5}] : 24'bX;
assign rd2_dat = (rd2_enable) ? mem[{rd2_a0, rd2_a1, rd2_a2, rd2_a3, rd2_a4, rd2_a5}] : 24'bX;
assign rd3_dat = (rd3_enable) ? mem[{rd3_a0, rd3_a1, rd3_a2, rd3_a3, rd3_a4, rd3_a5}] : 24'bX;

//wtf should have checking for collision
always @* begin
if (wr0_enable) begin
mem[{wr0_a0, wr0_a1, wr0_a2, wr0_a3, wr0_a4, wr0_a5}] <= wr0_dat;
//$display("%0d wr0_en=%h @%0h=%0h", $time, wr0_enable, {wr0_a0, wr0_a1, wr0_a2, wr0_a3, wr0_a4, wr0_a5}, mem[{wr0_a0, wr0_a1, wr0_a2, wr0_a3, wr0_a4, wr0_a5}]);
end
if (wr1_enable) begin
mem[{wr1_a0, wr1_a1, wr1_a2, wr1_a3, wr1_a4, wr1_a5}] <= wr1_dat;
//$display("%0d wr1_en=%h @%0h=%0h", $time, wr1_enable, {wr1_a0, wr1_a1, wr1_a2, wr1_a3, wr0_a4, wr1_a5}, mem[{wr1_a0, wr1_a1, wr1_a2, wr1_a3, wr1_a4, wr1_a5}]);
end
end

endmodule

@ -0,0 +1,197 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.

// Test array (SDR)
// 64 word 72 bit array
// LCB for strobe generation
// Config, BIST, etc.

`timescale 1 ns/1 ps
`include "toysram.vh"

module test_ra_ddr ();

logic clk;
logic clk2x;
logic reset;
logic cfg_wr;
logic [0:`LCBDDR_CONFIGWIDTH-1] cfg_dat;
logic [0:31] bist_ctl;
logic [0:31] bist_status;
logic rd_enb_0;
logic [0:5] rd_adr_0;
logic [0:71] rd_dat_0;
logic rd_enb_1;
logic [0:5] rd_adr_1;
logic [0:71] rd_dat_1;
logic rd_enb_2;
logic [0:5] rd_adr_2;
logic [0:71] rd_dat_2;
logic rd_enb_3;
logic [0:5] rd_adr_3;
logic [0:71] rd_dat_3;
logic wr_enb_0;
logic [0:5] wr_adr_0;
logic [0:71] wr_dat_0;
logic wr_enb_1;
logic [0:5] wr_adr_1;
logic [0:71] wr_dat_1;
logic strobe;
logic el_sel;
logic [0:`LCBDDR_CONFIGWIDTH-1] cfg;
logic mux_rd0_enb;
logic [0:5] mux_rd0_adr;
logic mux_rd1_enb;
logic [0:5] mux_rd1_adr;
logic mux_rd2_enb;
logic [0:5] mux_rd2_adr;
logic mux_rd3_enb;
logic [0:5] mux_rd3_adr;
logic mux_wr0_enb;
logic [0:5] mux_wr0_adr;
logic [0:71] mux_wr0_dat;
logic mux_wr1_enb;
logic [0:5] mux_wr1_adr;
logic [0:71] mux_wr1_dat;
initial
begin
clk = 1'b1;
clk2x = 1'b1;
forever #10 clk = ~clk;
forever #5 clk2x = ~clk2x;
end


ra_lcb_ddr lcb (

.clk (clk2x),
.reset (reset),
.cfg (cfg),
.strobe (strobe),
.el_sel (el_sel)

);

ra_cfg_ddr #(.INIT(-1)) cfig (

.clk (clk),
.reset (reset),
.cfg_wr (cfg_wr),
.cfg_dat (cfg_dat),
.cfg (cfg)

);

ra_bist_ddr bist (

.clk (clk),
.reset (reset),
.ctl (bist_ctl),
.status (bist_status),
.rd0_enb_in (rd_enb_0),
.rd0_adr_in (rd_adr_0),
.rd0_dat (rd_dat_0),
.rd1_enb_in (rd_enb_1),
.rd1_adr_in (rd_adr_1),
.rd1_dat (rd_dat_1),
.rd2_enb_in (rd_enb_2),
.rd2_adr_in (rd_adr_2),
.rd2_dat (rd_dat_2),
.rd3_enb_in (rd_enb_3),
.rd3_adr_in (rd_adr_3),
.rd3_dat (rd_dat_3),
.wr0_enb_in (wr_enb_0),
.wr0_adr_in (wr_adr_0),
.wr0_dat_in (wr_dat_0),
.wr1_enb_in (wr_enb_1),
.wr1_adr_in (wr_adr_1),
.wr1_dat_in (wr_dat_1),
.rd0_enb_out (mux_rd0_enb),
.rd0_adr_out (mux_rd0_adr),
.rd1_enb_out (mux_rd1_enb),
.rd1_adr_out (mux_rd1_adr),
.rd2_enb_out (mux_rd2_enb),
.rd2_adr_out (mux_rd2_adr),
.rd3_enb_out (mux_rd3_enb),
.rd3_adr_out (mux_rd3_adr),
.wr0_enb_out (mux_wr0_enb),
.wr0_adr_out (mux_wr0_adr),
.wr0_dat_out (mux_wr0_dat),
.wr1_enb_out (mux_wr1_enb),
.wr1_adr_out (mux_wr1_adr),
.wr1_dat_out (mux_wr1_dat)

);

ra_4r2w_64x72_ddr ra (

.clk (clk),
.reset (reset),
.strobe (strobe),
.el_sel (el_sel),
.rd_enb_0 (mux_rd0_enb),
.rd_adr_0 (mux_rd0_adr),
.rd_dat_0 (rd_dat_0),
.rd_enb_1 (mux_rd1_enb),
.rd_adr_1 (mux_rd1_adr),
.rd_dat_1 (rd_dat_1),
.rd_enb_2 (mux_rd2_enb),
.rd_adr_2 (mux_rd2_adr),
.rd_dat_2 (rd_dat_2),
.rd_enb_3 (mux_rd3_enb),
.rd_adr_3 (mux_rd3_adr),
.rd_dat_3 (rd_dat_3),
.wr_enb_0 (mux_wr0_enb),
.wr_adr_0 (mux_wr0_adr),
.wr_dat_0 (mux_wr0_dat),
.wr_enb_1 (mux_wr1_enb),
.wr_adr_1 (mux_wr1_adr),
.wr_dat_1 (mux_wr1_dat)

);

initial
begin
#0 reset = 1'b1;
#0 wr_enb_0 = 1'b0;
#0 wr_adr_0 = 6'h0;
#0 rd_adr_0 = 6'h0;
#0 rd_adr_1 = 6'h0;
#0 rd_enb_0 = 1'b0;
#0 rd_enb_1 = 1'b0;
#0 bist_ctl = 32'h0;
#0 cfg_wr = 1'b0;
#0 cfg_dat = 16'h0;
#31 reset = 1'b0;

#400 wr_enb_0 = 1'b1;
#0 wr_adr_0 = 6'h0;
#0 wr_adr_0 = 6'b00_0000;
#10 wr_adr_0 = 6'b00_0010;
#10 wr_adr_0 = 6'b00_0100;
#10 wr_adr_0 = 6'b00_0110;
#10 wr_adr_0 = 6'b00_1000;


end

endmodule

@ -0,0 +1,199 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.


// Test array (DDR)
// 64 word 72 bit array
// LCB for strobe generation
// Config, BIST, etc.

`timescale 1 ns / 1 ns

`include "toysram.vh"

module test_ra_ddr (

clk,
clk2x,
reset,
cfg_wr,
cfg_dat,
bist_ctl,
bist_status,

rd_enb_0,
rd_adr_0,
rd_dat_0,

rd_enb_1,
rd_adr_1,
rd_dat_1,

rd_enb_2,
rd_adr_2,
rd_dat_2,

rd_enb_3,
rd_adr_3,
rd_dat_3,

wr_enb_0,
wr_adr_0,
wr_dat_0,

wr_enb_1,
wr_adr_1,
wr_dat_1

);

input clk;
input clk2x;
input reset;
input cfg_wr;
input [0:`LCBDDR_CONFIGWIDTH-1] cfg_dat;
input [0:31] bist_ctl;
output [0:31] bist_status;
input rd_enb_0;
input [0:5] rd_adr_0;
output [0:71] rd_dat_0;
input rd_enb_1;
input [0:5] rd_adr_1;
output [0:71] rd_dat_1;
input rd_enb_2;
input [0:5] rd_adr_2;
output [0:71] rd_dat_2;
input rd_enb_3;
input [0:5] rd_adr_3;
output [0:71] rd_dat_3;
input wr_enb_0;
input [0:5] wr_adr_0;
input [0:71] wr_dat_0;
input wr_enb_1;
input [0:5] wr_adr_1;
input [0:71] wr_dat_1;

wire strobe;
wire el_sel;
wire [0:`LCBDDR_CONFIGWIDTH-1] cfg;
wire mux_rd0_enb;
wire [0:5] mux_rd0_adr;
wire mux_rd1_enb;
wire [0:5] mux_rd1_adr;
wire mux_rd2_enb;
wire [0:5] mux_rd2_adr;
wire mux_rd3_enb;
wire [0:5] mux_rd3_adr;
wire mux_wr0_enb;
wire [0:5] mux_wr0_adr;
wire [0:71] mux_wr0_dat;
wire mux_wr1_enb;
wire [0:5] mux_wr1_adr;
wire [0:71] mux_wr1_dat;


ra_lcb_ddr lcb (

.clk (clk2x),
.reset (reset),
.cfg (cfg),
.strobe (strobe),
.el_sel (el_sel)

);

ra_cfg_ddr #(.INIT(-1)) cfig (

.clk (clk),
.reset (reset),
.cfg_wr (cfg_wr),
.cfg_dat (cfg_dat),
.cfg (cfg)

);

ra_bist_ddr bist (

.clk (clk),
.reset (reset),
.ctl (bist_ctl),
.status (bist_status),
.rd0_enb_in (rd_enb_0),
.rd0_adr_in (rd_adr_0),
.rd0_dat (rd_dat_0),
.rd1_enb_in (rd_enb_1),
.rd1_adr_in (rd_adr_1),
.rd1_dat (rd_dat_1),
.rd2_enb_in (rd_enb_2),
.rd2_adr_in (rd_adr_2),
.rd2_dat (rd_dat_2),
.rd3_enb_in (rd_enb_3),
.rd3_adr_in (rd_adr_3),
.rd3_dat (rd_dat_3),
.wr0_enb_in (wr_enb_0),
.wr0_adr_in (wr_adr_0),
.wr0_dat_in (wr_dat_0),
.wr1_enb_in (wr_enb_1),
.wr1_adr_in (wr_adr_1),
.wr1_dat_in (wr_dat_1),
.rd0_enb_out (mux_rd0_enb),
.rd0_adr_out (mux_rd0_adr),
.rd1_enb_out (mux_rd1_enb),
.rd1_adr_out (mux_rd1_adr),
.rd2_enb_out (mux_rd2_enb),
.rd2_adr_out (mux_rd2_adr),
.rd3_enb_out (mux_rd3_enb),
.rd3_adr_out (mux_rd3_adr),
.wr0_enb_out (mux_wr0_enb),
.wr0_adr_out (mux_wr0_adr),
.wr0_dat_out (mux_wr0_dat),
.wr1_enb_out (mux_wr1_enb),
.wr1_adr_out (mux_wr1_adr),
.wr1_dat_out (mux_wr1_dat)

);

ra_4r2w_64x72_ddr ra (

.clk (clk),
.reset (reset),
.strobe (strobe),
.el_sel (el_sel),
.rd_enb_0 (mux_rd0_enb),
.rd_adr_0 (mux_rd0_adr),
.rd_dat_0 (rd_dat_0),
.rd_enb_1 (mux_rd1_enb),
.rd_adr_1 (mux_rd1_adr),
.rd_dat_1 (rd_dat_1),
.rd_enb_2 (mux_rd2_enb),
.rd_adr_2 (mux_rd2_adr),
.rd_dat_2 (rd_dat_2),
.rd_enb_3 (mux_rd3_enb),
.rd_adr_3 (mux_rd3_adr),
.rd_dat_3 (rd_dat_3),
.wr_enb_0 (mux_wr0_enb),
.wr_adr_0 (mux_wr0_adr),
.wr_dat_0 (mux_wr0_dat),
.wr_enb_1 (mux_wr1_enb),
.wr_adr_1 (mux_wr1_adr),
.wr_dat_1 (mux_wr1_dat)

);

endmodule

@ -0,0 +1,196 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.


// Test array (DDR1x (sim only) - acts like DDR but only uses single clock
// 64 word 72 bit array
// LCB for strobe generation
// Config, BIST, etc.

`timescale 1 ns / 1 ns

`include "toysram.vh"

module test_ra_ddr_1x (

clk,
reset,
cfg_wr,
cfg_dat,
bist_ctl,
bist_status,

rd_enb_0,
rd_adr_0,
rd_dat_0,

rd_enb_1,
rd_adr_1,
rd_dat_1,

rd_enb_2,
rd_adr_2,
rd_dat_2,

rd_enb_3,
rd_adr_3,
rd_dat_3,

wr_enb_0,
wr_adr_0,
wr_dat_0,

wr_enb_1,
wr_adr_1,
wr_dat_1

);

input clk;
input reset;
input cfg_wr;
input [0:`LCBDDR_CONFIGWIDTH-1] cfg_dat;
input [0:31] bist_ctl;
output [0:31] bist_status;
input rd_enb_0;
input [0:5] rd_adr_0;
output [0:71] rd_dat_0;
input rd_enb_1;
input [0:5] rd_adr_1;
output [0:71] rd_dat_1;
input rd_enb_2;
input [0:5] rd_adr_2;
output [0:71] rd_dat_2;
input rd_enb_3;
input [0:5] rd_adr_3;
output [0:71] rd_dat_3;
input wr_enb_0;
input [0:5] wr_adr_0;
input [0:71] wr_dat_0;
input wr_enb_1;
input [0:5] wr_adr_1;
input [0:71] wr_dat_1;

wire strobe;
wire el_sel;
wire [0:`LCBDDR_CONFIGWIDTH-1] cfg;
wire mux_rd0_enb;
wire [0:5] mux_rd0_adr;
wire mux_rd1_enb;
wire [0:5] mux_rd1_adr;
wire mux_rd2_enb;
wire [0:5] mux_rd2_adr;
wire mux_rd3_enb;
wire [0:5] mux_rd3_adr;
wire mux_wr0_enb;
wire [0:5] mux_wr0_adr;
wire [0:71] mux_wr0_dat;
wire mux_wr1_enb;
wire [0:5] mux_wr1_adr;
wire [0:71] mux_wr1_dat;


ra_lcb_ddr lcb (

.clk (clk),
.reset (reset),
.cfg (cfg),
.strobe (strobe), // not used
.el_sel (el_sel)

);

ra_cfg_ddr #(.INIT(-1)) cfig (

.clk (clk),
.reset (reset),
.cfg_wr (cfg_wr),
.cfg_dat (cfg_dat),
.cfg (cfg)

);

ra_bist_ddr bist (

.clk (clk),
.reset (reset),
.ctl (bist_ctl),
.status (bist_status),
.rd0_enb_in (rd_enb_0),
.rd0_adr_in (rd_adr_0),
.rd0_dat (rd_dat_0),
.rd1_enb_in (rd_enb_1),
.rd1_adr_in (rd_adr_1),
.rd1_dat (rd_dat_1),
.rd2_enb_in (rd_enb_2),
.rd2_adr_in (rd_adr_2),
.rd2_dat (rd_dat_2),
.rd3_enb_in (rd_enb_3),
.rd3_adr_in (rd_adr_3),
.rd3_dat (rd_dat_3),
.wr0_enb_in (wr_enb_0),
.wr0_adr_in (wr_adr_0),
.wr0_dat_in (wr_dat_0),
.wr1_enb_in (wr_enb_1),
.wr1_adr_in (wr_adr_1),
.wr1_dat_in (wr_dat_1),
.rd0_enb_out (mux_rd0_enb),
.rd0_adr_out (mux_rd0_adr),
.rd1_enb_out (mux_rd1_enb),
.rd1_adr_out (mux_rd1_adr),
.rd2_enb_out (mux_rd2_enb),
.rd2_adr_out (mux_rd2_adr),
.rd3_enb_out (mux_rd3_enb),
.rd3_adr_out (mux_rd3_adr),
.wr0_enb_out (mux_wr0_enb),
.wr0_adr_out (mux_wr0_adr),
.wr0_dat_out (mux_wr0_dat),
.wr1_enb_out (mux_wr1_enb),
.wr1_adr_out (mux_wr1_adr),
.wr1_dat_out (mux_wr1_dat)

);

ra_4r2w_64x72_ddr_1x ra (

.clk (clk),
.reset (reset),
.strobe (1'b1),
.rd_enb_0 (mux_rd0_enb),
.rd_adr_0 (mux_rd0_adr),
.rd_dat_0 (rd_dat_0),
.rd_enb_1 (mux_rd1_enb),
.rd_adr_1 (mux_rd1_adr),
.rd_dat_1 (rd_dat_1),
.rd_enb_2 (mux_rd2_enb),
.rd_adr_2 (mux_rd2_adr),
.rd_dat_2 (rd_dat_2),
.rd_enb_3 (mux_rd3_enb),
.rd_adr_3 (mux_rd3_adr),
.rd_dat_3 (rd_dat_3),
.wr_enb_0 (mux_wr0_enb),
.wr_adr_0 (mux_wr0_adr),
.wr_dat_0 (mux_wr0_dat),
.wr_enb_1 (mux_wr1_enb),
.wr_adr_1 (mux_wr1_adr),
.wr_dat_1 (mux_wr1_dat)

);

endmodule

@ -0,0 +1,171 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.

// Test array (SDR)
// 64 word 72 bit array
// LCB for strobe generation
// Config, BIST, etc.

`timescale 1 ns/1 ps
`include "toysram.vh"

module test_ra_sdr ();

logic clk;
logic reset;
logic cfg_wr;
logic [0:`LCBSDR_CONFIGWIDTH-1] cfg_dat;
logic [0:31] bist_ctl;
logic [0:31] bist_status;
logic rd_enb_0;
logic [0:5] rd_adr_0;
logic [0:71] rd_dat_0;
logic rd_enb_1;
logic [0:5] rd_adr_1;
logic [0:71] rd_dat_1;
logic wr_enb_0;
logic [0:5] wr_adr_0;
logic [0:71] wr_dat_0;

logic strobe;
logic [0:`LCBSDR_CONFIGWIDTH-1] cfg;
logic mux_rd0_enb;
logic [0:5] mux_rd0_adr;
logic mux_rd1_enb;
logic [0:5] mux_rd1_adr;
logic mux_wr0_enb;
logic [0:5] mux_wr0_adr;
logic [0:71] mux_wr0_dat;

initial
begin
$dumpfile("test_ra_sdr.vcd");
$dumpvars (0,test_ra_sdr.lcb);
$dumpvars (0,test_ra_sdr.cfig);
$dumpvars (0,test_ra_sdr.bist);
$dumpvars (0,test_ra_sdr.ra);
end


initial
begin
clk = 1'b1;
forever #5 clk = ~clk;
end



ra_lcb_sdr lcb (.clk (clk),
.reset (reset),
.cfg (cfg),
.strobe (strobe));

ra_cfg_sdr #(.INIT(-1)) cfig (.clk (clk),
.reset (reset),
.cfg_wr (cfg_wr),
.cfg_dat (cfg_dat),
.cfg (cfg));

ra_bist_sdr bist (.clk (clk),
.reset (reset),
.ctl (bist_ctl),
.status (bist_status),
.rd0_enb_in (rd_enb_0),
.rd0_adr_in (rd_adr_0),
.rd0_dat (rd_dat_0),
.rd1_enb_in (rd_enb_1),
.rd1_adr_in (rd_adr_1),
.rd1_dat (rd_dat_1),
.wr0_enb_in (wr_enb_0),
.wr0_adr_in (wr_adr_0),
.wr0_dat_in (wr_dat_0),
.rd0_enb_out (mux_rd0_enb),
.rd0_adr_out (mux_rd0_adr),
.rd1_enb_out (mux_rd1_enb),
.rd1_adr_out (mux_rd1_adr),
.wr0_enb_out (mux_wr0_enb),
.wr0_adr_out (mux_wr0_adr),
.wr0_dat_out (mux_wr0_dat));


ra_2r1w_64x72_sdr ra (.clk (clk),
.reset (reset),
.strobe (strobe),
.rd_enb_0 (mux_rd0_enb),
.rd_adr_0 (mux_rd0_adr),
.rd_dat_0 (rd_dat_0),
.rd_enb_1 (mux_rd1_enb),
.rd_adr_1 (mux_rd1_adr),
.rd_dat_1 (rd_dat_1),
.wr_enb_0 (mux_wr0_enb),
.wr_adr_0 (mux_wr0_adr),
.wr_dat_0 (mux_wr0_dat));

initial
begin
#0 reset = 1'b1;
#0 wr_enb_0 = 1'b0;
#0 wr_adr_0 = 6'h0;
#0 rd_adr_0 = 6'h0;
#0 rd_adr_1 = 6'h0;
#0 rd_enb_0 = 1'b0;
#0 rd_enb_1 = 1'b0;
#0 bist_ctl = 32'h0;
#0 cfg_wr = 1'b0;
#0 cfg_dat = 16'h0;
#15 reset = 1'b0;

#400 wr_enb_0 = 1'b1;
#0 wr_adr_0 = 6'h0;

#0 wr_adr_0 = 6'b00_0000;
#0 wr_dat_0 = 6'b00_1111;

#10 wr_adr_0 = 6'b00_0010;
#0 wr_dat_0 = 6'b00_1001;

#10 wr_adr_0 = 6'b00_0100;
#0 wr_dat_0 = 6'b00_1100;

#10 wr_adr_0 = 6'b00_0110;
#0 wr_adr_0 = 6'b00_1101;

#10 wr_adr_0 = 6'b00_1000;
#0 wr_adr_0 = 6'b00_1000;

#5 wr_enb_0 = 0;

#5 rd_enb_0 = 1;
#0 rd_enb_1 = 1;

#10 rd_adr_0 = 6'b00_0000;
#0 rd_adr_1 = 6'b00_0010;

#10 rd_adr_0 = 6'b00_0100;
#0 rd_adr_1 = 6'b00_0110;

#10 rd_adr_0 = 6'b00_1000;

#5 rd_enb_0 = 0;
#0 rd_enb_1 = 0;


end

endmodule

@ -0,0 +1,143 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.


// Test array (SDR)
// 32 word 32 bit array
// LCB for strobe generation
// Config, BIST, etc.

`timescale 1 ns / 1 ns

`include "toysram.vh"

module test_ra_sdr_32x32 (

clk,
reset,
cfg_wr,
cfg_dat,
bist_ctl,
bist_status,

rd_enb_0,
rd_adr_0,
rd_dat_0,

rd_enb_1,
rd_adr_1,
rd_dat_1,

wr_enb_0,
wr_adr_0,
wr_dat_0

);

input clk;
input reset;
input cfg_wr;
input [0:`LCBSDR_CONFIGWIDTH-1] cfg_dat;
input [0:31] bist_ctl;
output [0:31] bist_status;
input rd_enb_0;
input [0:4] rd_adr_0;
output [0:31] rd_dat_0;
input rd_enb_1;
input [0:4] rd_adr_1;
output [0:31] rd_dat_1;
input wr_enb_0;
input [0:4] wr_adr_0;
input [0:31] wr_dat_0;

wire strobe;
wire [0:`LCBSDR_CONFIGWIDTH-1] cfg;
wire mux_rd0_enb;
wire [0:4] mux_rd0_adr;
wire mux_rd1_enb;
wire [0:4] mux_rd1_adr;
wire mux_wr0_enb;
wire [0:4] mux_wr0_adr;
wire [0:31] mux_wr0_dat;

ra_lcb_sdr lcb (

.clk (clk),
.reset (reset),
.cfg (cfg),
.strobe (strobe)

);

ra_cfg_sdr #(.INIT(-1)) cfig (

.clk (clk),
.reset (reset),
.cfg_wr (cfg_wr),
.cfg_dat (cfg_dat),
.cfg (cfg)

);

ra_bist_sdr_32x32 bist (

.clk (clk),
.reset (reset),
.ctl (bist_ctl),
.status (bist_status),
.rd0_enb_in (rd_enb_0),
.rd0_adr_in (rd_adr_0),
.rd0_dat (rd_dat_0),
.rd1_enb_in (rd_enb_1),
.rd1_adr_in (rd_adr_1),
.rd1_dat (rd_dat_1),
.wr0_enb_in (wr_enb_0),
.wr0_adr_in (wr_adr_0),
.wr0_dat_in (wr_dat_0),
.rd0_enb_out (mux_rd0_enb),
.rd0_adr_out (mux_rd0_adr),
.rd1_enb_out (mux_rd1_enb),
.rd1_adr_out (mux_rd1_adr),
.wr0_enb_out (mux_wr0_enb),
.wr0_adr_out (mux_wr0_adr),
.wr0_dat_out (mux_wr0_dat)

);

ra_2r1w_32x32_sdr ra (

.clk (clk),
.reset (reset),
.strobe (strobe),
.rd_enb_0 (mux_rd0_enb),
.rd_adr_0 (mux_rd0_adr),
.rd_dat_0 (rd_dat_0),
.rd_enb_1 (mux_rd1_enb),
.rd_adr_1 (mux_rd1_adr),
.rd_dat_1 (rd_dat_1),
.wr_enb_0 (mux_wr0_enb),
.wr_adr_0 (mux_wr0_adr),
.wr_dat_0 (mux_wr0_dat)

);



endmodule

@ -0,0 +1,143 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.


// Test array (SDR)
// 64 word 72 bit array
// LCB for strobe generation
// Config, BIST, etc.

`timescale 1 ns / 1 ns

`include "toysram.vh"

module test_ra_sdr (

clk,
reset,
cfg_wr,
cfg_dat,
bist_ctl,
bist_status,

rd_enb_0,
rd_adr_0,
rd_dat_0,

rd_enb_1,
rd_adr_1,
rd_dat_1,

wr_enb_0,
wr_adr_0,
wr_dat_0

);

input clk;
input reset;
input cfg_wr;
input [0:`LCBSDR_CONFIGWIDTH-1] cfg_dat;
input [0:31] bist_ctl;
output [0:31] bist_status;
input rd_enb_0;
input [0:5] rd_adr_0;
output [0:71] rd_dat_0;
input rd_enb_1;
input [0:5] rd_adr_1;
output [0:71] rd_dat_1;
input wr_enb_0;
input [0:5] wr_adr_0;
input [0:71] wr_dat_0;

wire strobe;
wire [0:`LCBSDR_CONFIGWIDTH-1] cfg;
wire mux_rd0_enb;
wire [0:5] mux_rd0_adr;
wire mux_rd1_enb;
wire [0:5] mux_rd1_adr;
wire mux_wr0_enb;
wire [0:5] mux_wr0_adr;
wire [0:71] mux_wr0_dat;

ra_lcb_sdr lcb (

.clk (clk),
.reset (reset),
.cfg (cfg),
.strobe (strobe)

);

ra_cfg_sdr #(.INIT(-1)) cfig (

.clk (clk),
.reset (reset),
.cfg_wr (cfg_wr),
.cfg_dat (cfg_dat),
.cfg (cfg)

);

ra_bist_sdr bist (

.clk (clk),
.reset (reset),
.ctl (bist_ctl),
.status (bist_status),
.rd0_enb_in (rd_enb_0),
.rd0_adr_in (rd_adr_0),
.rd0_dat (rd_dat_0),
.rd1_enb_in (rd_enb_1),
.rd1_adr_in (rd_adr_1),
.rd1_dat (rd_dat_1),
.wr0_enb_in (wr_enb_0),
.wr0_adr_in (wr_adr_0),
.wr0_dat_in (wr_dat_0),
.rd0_enb_out (mux_rd0_enb),
.rd0_adr_out (mux_rd0_adr),
.rd1_enb_out (mux_rd1_enb),
.rd1_adr_out (mux_rd1_adr),
.wr0_enb_out (mux_wr0_enb),
.wr0_adr_out (mux_wr0_adr),
.wr0_dat_out (mux_wr0_dat)

);

ra_2r1w_64x72_sdr ra (

.clk (clk),
.reset (reset),
.strobe (strobe),
.rd_enb_0 (mux_rd0_enb),
.rd_adr_0 (mux_rd0_adr),
.rd_dat_0 (rd_dat_0),
.rd_enb_1 (mux_rd1_enb),
.rd_adr_1 (mux_rd1_adr),
.rd_dat_1 (rd_dat_1),
.wr_enb_0 (mux_wr0_enb),
.wr_adr_0 (mux_wr0_adr),
.wr_dat_0 (mux_wr0_dat)

);



endmodule

@ -0,0 +1,8 @@
// Global Parameters for ToySRAM Testsite

`define GENMODE 0 // 0=NoDelay, 1=Delay

// RA LCB
`define LCBSDR_CONFIGWIDTH 16
`define LCBDDR_CONFIGWIDTH 32

@ -0,0 +1,130 @@
# // Questa Sim-64
# // Version 2020.3_1 linux_x86_64 Aug 25 2020
# //
# // Copyright 1991-2020 Mentor Graphics Corporation
# // All Rights Reserved.
# //
# // QuestaSim and its associated documentation contain trade
# // secrets and commercial or financial information that are the property of
# // Mentor Graphics Corporation and are privileged, confidential,
# // and exempt from disclosure under the Freedom of Information Act,
# // 5 U.S.C. Section 552. Furthermore, this information
# // is prohibited from disclosure under the Trade Secrets Act,
# // 18 U.S.C. Section 1905.
# //
pwd
# /home/ptikals/IBM/osu-toy-sram/src
do top.do
# Cannot open macro file: top.do
cd ../sim
do top.do
# QuestaSim-64 vlog 2020.3_1 Compiler 2020.08 Aug 25 2020
# Start time: 11:20:19 on Dec 14,2021
# vlog -reportprogress 300 -lint ../src/address_clock_sdr_2r1w_64.v ../src/ra_bist_ddr.v ../src/predecode_sdr_64.v ../src/ra_bist_sdr.v ../src/ra_2r1w_64x72_sdr.v ../src/ra_cfg_ddr.v ../src/regfile_2r1w_64x24.v ../src/toysram.vh ../src/ra_4r2w_64x72_ddr_1x.v ../src/ra_cfg_sdr.v ../src/regfile_4r2w_64x24.v ../src/ra_4r2w_64x72_ddr.v ../src/ra_delay.v ../src/ra_lcb_sdr.v ../src/ra_lcb_ddr.v ../src/test_ra_ddr.v ../src/test_ra_sdr.sv ../src/test_ra_ddr_1x.v
# -- Compiling module address_clock_sdr_2r1w_64
# -- Compiling module ra_bist_ddr
# -- Compiling module predecode_sdr_64
# -- Compiling module ra_bist_sdr
# -- Compiling module ra_2r1w_64x72_sdr
# -- Compiling module ra_cfg_ddr
# -- Compiling module regfile_2r1w_64x24
# -- Compiling module ra_4r2w_64x72_ddr_1x
# -- Compiling module ra_cfg_sdr
# -- Compiling module regfile_4r2w_64x24
# -- Compiling module ra_4r2w_64x72_ddr
# -- Compiling module ra_delay
# -- Compiling module ra_lcb_sdr
# ** Warning: ../src/ra_lcb_sdr.v(61): (vlog-2623) Undefined variable: i.
# -- Compiling module ra_lcb_ddr
# -- Compiling module test_ra_ddr
# -- Compiling module test_ra_sdr
# ** Warning: ../src/test_ra_sdr.sv(28): (vlog-2605) empty port name in port list.
# -- Compiling module test_ra_ddr_1x
#
# Top level modules:
# ra_bist_sdr
# test_ra_ddr
# test_ra_sdr
# test_ra_ddr_1x
# End time: 11:20:19 on Dec 14,2021, Elapsed time: 0:00:00
# Errors: 0, Warnings: 2
# vsim -debugdb -voptargs="+acc" work.test_ra_sdr
# Start time: 11:20:19 on Dec 14,2021
# ** Note: (vsim-3812) Design is being optimized...
# ** Note: (vsim-8611) Generating debug db.
# ** Error: ../src/test_ra_sdr.sv(85): Module 'ra_bist_sdr_osu' is not defined.
# Optimization failed
# ** Note: (vsim-12126) Error and warning message counts have been restored: Errors=1, Warnings=0.
# Error loading design
# Error: Error loading design
# Pausing macro execution
# MACRO ./top.do PAUSED at line 33
do top.do
# QuestaSim-64 vlog 2020.3_1 Compiler 2020.08 Aug 25 2020
# Start time: 11:29:26 on Dec 14,2021
# vlog -reportprogress 300 -lint ../src/address_clock_sdr_2r1w_64.v ../src/ra_bist_ddr.v ../src/predecode_sdr_64.v ../src/ra_bist_sdr_osu.v ../src/ra_2r1w_64x72_sdr.v ../src/ra_cfg_ddr.v ../src/regfile_2r1w_64x24.v ../src/toysram.vh ../src/ra_4r2w_64x72_ddr_1x.v ../src/ra_cfg_sdr.v ../src/regfile_4r2w_64x24.v ../src/ra_4r2w_64x72_ddr.v ../src/ra_delay.v ../src/ra_lcb_sdr.v ../src/ra_lcb_ddr.v ../src/test_ra_ddr.v ../src/test_ra_sdr.sv ../src/test_ra_ddr_1x.v
# -- Compiling module address_clock_sdr_2r1w_64
# -- Compiling module ra_bist_ddr
# -- Compiling module predecode_sdr_64
# -- Compiling module ra_bist_sdr
# ** Error: ../src/ra_bist_sdr_osu.v(88): (vlog-2730) Undefined variable: 'int'.
# ** Error: (vlog-13069) ../src/ra_bist_sdr_osu.v(88): near "i": syntax error, unexpected IDENTIFIER, expecting '='.
# ** Error: (vlog-13036) ../src/ra_bist_sdr_osu.v(88): near "++": Operator only allowed in SystemVerilog.
# ** Error: ../src/ra_bist_sdr_osu.v(88): (vlog-13205) Syntax error found in the scope following 'i'. Is there a missing '::'?
# -- Compiling module ra_2r1w_64x72_sdr
# -- Compiling module ra_cfg_ddr
# -- Compiling module regfile_2r1w_64x24
# -- Compiling module ra_4r2w_64x72_ddr_1x
# -- Compiling module ra_cfg_sdr
# -- Compiling module regfile_4r2w_64x24
# -- Compiling module ra_4r2w_64x72_ddr
# -- Compiling module ra_delay
# -- Compiling module ra_lcb_sdr
# ** Warning: ../src/ra_lcb_sdr.v(61): (vlog-2623) Undefined variable: i.
# -- Compiling module ra_lcb_ddr
# -- Compiling module test_ra_ddr
# -- Compiling module test_ra_sdr
# ** Warning: ../src/test_ra_sdr.sv(28): (vlog-2605) empty port name in port list.
# -- Compiling module test_ra_ddr_1x
# End time: 11:29:26 on Dec 14,2021, Elapsed time: 0:00:00
# Errors: 4, Warnings: 2
# ** Error: /opt/Mentor/questasim/linux_x86_64/vlog failed.
# Error in macro ./top.do line 30
# /opt/Mentor/questasim/linux_x86_64/vlog failed.
# while executing
# "vlog -lint ../src/address_clock_sdr_2r1w_64.v ../src/ra_bist_ddr.v ../src/predecode_sdr_64.v ../src/ra_bist_sdr_osu.v ../src/ra_2r1w_64x72_sdr.v ../sr..."
do top.do
# QuestaSim-64 vlog 2020.3_1 Compiler 2020.08 Aug 25 2020
# Start time: 11:49:53 on Dec 14,2021
# vlog -reportprogress 300 -lint ../src/address_clock_sdr_2r1w_64.v ../src/ra_bist_ddr.v ../src/predecode_sdr_64.v ../src/ra_bist_sdr_osu.v ../src/ra_2r1w_64x72_sdr.v ../src/ra_cfg_ddr.v ../src/regfile_2r1w_64x24.v ../src/toysram.vh ../src/ra_4r2w_64x72_ddr_1x.v ../src/ra_cfg_sdr.v ../src/regfile_4r2w_64x24.v ../src/ra_4r2w_64x72_ddr.v ../src/ra_delay.v ../src/ra_lcb_sdr.v ../src/ra_lcb_ddr.v ../src/test_ra_ddr.v ../src/test_ra_sdr.sv ../src/test_ra_ddr_1x.v
# -- Compiling module address_clock_sdr_2r1w_64
# -- Compiling module ra_bist_ddr
# -- Compiling module predecode_sdr_64
# -- Compiling module ra_bist_sdr
# ** Error: ../src/ra_bist_sdr_osu.v(88): (vlog-2730) Undefined variable: 'int'.
# ** Error: (vlog-13069) ../src/ra_bist_sdr_osu.v(88): near "i": syntax error, unexpected IDENTIFIER, expecting '='.
# ** Error: ../src/ra_bist_sdr_osu.v(88): (vlog-13205) Syntax error found in the scope following 'i'. Is there a missing '::'?
# -- Compiling module ra_2r1w_64x72_sdr
# -- Compiling module ra_cfg_ddr
# -- Compiling module regfile_2r1w_64x24
# -- Compiling module ra_4r2w_64x72_ddr_1x
# -- Compiling module ra_cfg_sdr
# -- Compiling module regfile_4r2w_64x24
# -- Compiling module ra_4r2w_64x72_ddr
# -- Compiling module ra_delay
# -- Compiling module ra_lcb_sdr
# ** Warning: ../src/ra_lcb_sdr.v(61): (vlog-2623) Undefined variable: i.
# -- Compiling module ra_lcb_ddr
# -- Compiling module test_ra_ddr
# -- Compiling module test_ra_sdr
# ** Warning: ../src/test_ra_sdr.sv(28): (vlog-2605) empty port name in port list.
# -- Compiling module test_ra_ddr_1x
# End time: 11:49:53 on Dec 14,2021, Elapsed time: 0:00:00
# Errors: 3, Warnings: 2
# ** Error: /opt/Mentor/questasim/linux_x86_64/vlog failed.
# Error in macro ./top.do line 30
# /opt/Mentor/questasim/linux_x86_64/vlog failed.
# while executing
# "vlog -lint ../src/address_clock_sdr_2r1w_64.v ../src/ra_bist_ddr.v ../src/predecode_sdr_64.v ../src/ra_bist_sdr_osu.v ../src/ra_2r1w_64x72_sdr.v ../sr..."
# End time: 12:39:15 on Dec 14,2021, Elapsed time: 1:18:56
# Errors: 3, Warnings: 0

@ -0,0 +1,427 @@
#!/usr/bin/python3
#
# Parse table comments and create equations.

from optparse import OptionParser
import re
from shutil import copyfile

#--------------------------------------------------------------------------------------------------
# Initialize

TYPE_INPUT = 0
TYPE_OUTPUT = 1
TYPE_SKIP = 99

lines = []
tableMatches = []
tableNames = []
tableLines = []
tables = {}

failOnError = True
inFile = 'test.vhdl'
outFileExt = 'vtable'
overwrite = True
backupExt = 'orig'
backup = True
noisy = False
quiet = False
verilog = False

#--------------------------------------------------------------------------------------------------
# Handle command line

usage = 'vtable [options] inFile'

parser = OptionParser(usage)
parser.add_option('-f', '--outfile', dest='outFile', help='output file, default=[inFile]' + outFileExt)
parser.add_option('-o', '--overwrite', dest='overwrite', help='overwrite inFile, default=' + str(overwrite))
parser.add_option('-b', '--backup', dest='backup', help='backup original file, default=' + str(backup))
parser.add_option('-q', '--quiet', dest='quiet', action='store_true', help='quiet messages, default=' + str(quiet))
parser.add_option('-n', '--noisy', dest='noisy', action='store_true', help='noisy messages, default=' + str(noisy))
parser.add_option('-V', '--verilog', dest='verilog', action='store_true', help='source is verilog, default=' + str(verilog))

options, args = parser.parse_args()

if len(args) != 1:
parser.error(usage)
quit(-1)
else:
inFile = args[0]

if options.overwrite == '0':
overwrite = False
elif options.overwrite == '1':
overwrite == True
if options.outFile is not None:
parser.error('Can\'t specify outfile and overrite!')
quit(-1)
elif options.overwrite is not None:
parser.error('overwrite: 0|1')
quit(-1)

if options.quiet is not None:
quiet = True

if options.noisy is not None:
noisy = True

if options.verilog is not None:
verilog = True

if options.backup == '0':
backup = False
elif options.backup == '1':
backup == True
elif options.backup is not None:
parser.error('backup: 0|1')
quit(-1)

if options.outFile is not None:
outFile = options.outFile
elif overwrite:
outFile = inFile
else:
outFile = inFile + '.' + outFileExt

backupFile = inFile + '.' + backupExt

#--------------------------------------------------------------------------------------------------
# Objects

class Signal:

def __init__(self, name, type):
self.name = name;
self.type = type;

class Table:

def __init__(self, name):
self.name = name
self.source = []
self.signals = {}
self.signalsByCol = {}
self.typesByCol = {}
self.specs = [] # list of specsByCol
self.equations = []
self.added = False

def validate(self):
# check that all signals have a good type
for col in self.signalsByCol:
if col not in self.typesByCol:
error('Table ' + self.name + ': no signal type for ' + self.signalsByCol[col])
elif self.typesByCol[col] == None:
error('Table ' + self.name + ': bad signal type (' + str(self.typesByCol[col]) + ') for ' + str(self.signalsByCol[col]))

def makeRTL(self, form=None):
outputsByCol = {}


#for col,type in self.typesByCol.items():
for col in sorted(self.typesByCol):
type = self.typesByCol[col]
if type == TYPE_OUTPUT:
if col in self.signalsByCol:
outputsByCol[col] = self.signalsByCol[col]
else:
print(self.signalsByCol)
print(self.typesByCol)
error('Table ' + self.name + ': output is specified in col ' + str(col) + ' but no signal exists')

#for sigCol,sig in outputsByCol.items():
for sigCol in sorted(outputsByCol):
sig = outputsByCol[sigCol]
if not verilog:
line = sig + ' <= '
else:
line = 'assign ' + sig + ' = '
nonzero = False
for specsByCol in self.specs:
terms = []
if sigCol not in specsByCol:
#error('* Output ' + sig + ' has no specified value for column ' + str(col))
1 # no error, can be dontcare
elif specsByCol[sigCol] == '1':
for col,val in specsByCol.items():
if col not in self.typesByCol:
if noisy:
error('Table ' + self.name +': unexpected value in spec column ' + str(col) + ' (' + str(val) + ') - no associated signal', False) #wtf UNTIL CAN HANDLE COMMENTS AT END!!!!!!!!!!!!!!!!!!!
elif self.typesByCol[col] == TYPE_INPUT:
if val == '0':
terms.append(opNot + self.signalsByCol[col])
if nonzero and len(terms) == 1:
line = line + ') ' + opOr + '\n (';
elif len(terms) == 1:
line = line + '\n ('
nonzero = True
elif val == '1':
terms.append(self.signalsByCol[col])
if nonzero and len(terms) == 1:
line = line + ') ' + opOr + '\n (';
elif len(terms) == 1:
line = line + '\n ('
nonzero = True
else:
error('Table ' + self.name +': unexpected value in spec column ' + str(col) + ' (' + str(val) + ')')
if len(terms) > 0:
line = line + (' ' + opAnd + ' ').join(terms)
if not nonzero:
line = line + zero + ";";
else:
line = line + ');'
self.equations.append(line)

return self.equations

def printv(self):
self.makeRTL()
print('\n'.join(self.equations))

def printinfo(self):
print('Table: ' + self.name)
print
for l in self.source:
print(l)
print
print('Signals by column:')
for col in sorted(self.signalsByCol):
print('{0:>3}. {1:} ({2:}) '.format(col, self.signalsByCol[col], 'in' if self.typesByCol[col] == TYPE_INPUT else 'out'))


#--------------------------------------------------------------------------------------------------
# Functions

def error(msg, quitOverride=None):
print('*** ' + msg)
if quitOverride == False:
1
elif (quitOverride == None) or failOnError:
quit(-10)
elif quitOverride:
quit(-10)

#--------------------------------------------------------------------------------------------------
# Do something

if not verilog:
openBracket = '('
closeBracket = ')'
opAnd = 'and'
opOr = 'or'
opNot = 'not '
zero = "'0'"
tablePattern = re.compile(r'^\s*?--tbl(?:\s+([^\s]+).*$|\s*$)')
tableGenPattern = re.compile(r'^\s*?--vtable(?:\s+([^\s]+).*$)')
commentPattern = re.compile(r'^\s*?(--.*$|\s*$)')
tableLinePattern = re.compile(r'^.*?--(.*)')
namePattern = re.compile(r'([a-zA-z\d_\(\)\.\[\]]+)')
else:
openBracket = '['
closeBracket = ']'
opAnd = '&'
opOr = '+'
opNot = '~'
zero = "'b0"
tablePattern = re.compile(r'^\s*?\/\/tbl(?:\s+([^\s]+).*$|\s*$)')
tableGenPattern = re.compile(r'^\s*?\/\/vtable(?:\s+([^\s]+).*$)')
commentPattern = re.compile(r'^\s*?(\/\/.*$|\s*$)')
tableLinePattern = re.compile(r'^.*?\/\/(.*)')
namePattern = re.compile(r'([a-zA-z\d_\(\)\.\[\]]+)')

# find the lines with table spec
try:
inf = open(inFile)
for i, line in enumerate(inf):
lines.append(line.strip('\n'))
for match in re.finditer(tablePattern, line):
tableMatches.append(i)
inf.close()
except Exception as e:
error('Error opening input file ' + inFile + '\n' + str(e), True)

# validate matches; should be paired, nothing but comments and empties; table may be named
# between them

for i in range(0, len(tableMatches), 2):

if i + 1 > len(tableMatches) - 1:
error('Mismatched table tags.\nFound so far: ' + ', '.join(tableNames), True)

tLines = lines[tableMatches[i]:tableMatches[i+1]+1]
tableLines.append(tLines)
tName = re.match(tablePattern, lines[tableMatches[i]]).groups()[0]
if tName is None:
tName = 'noname_' + str(tableMatches[i] + 1)
tableNames.append(tName)

for line in tLines:
if not re.match(commentPattern, line):
error('Found noncomment, nonempty line in table ' + tName + ':\n' + line, True)

print('Found tables: ' + ', '.join(tableNames))

# build table objects

for table, tName in zip(tableLines, tableNames):
print('Parsing ' + tName + '...')
namesByCol = {}
colsByName = {}
bitsByCol = {}
typesByCol = {}
specs = []

# parse the table - do by Table.parse()
tLines = table[1:-1] # exclude --tbl
for line in tLines:
if line.strip() == '':
continue
try:
spec = re.search(tableLinePattern, line).groups()[0]
except Exception as e:
error('Problem parsing table line:\n' + line, True)
if len(spec) > 0:
if spec[0] == 'n':
for match in re.finditer(namePattern, spec[1:]):
# col 0 is first col after n
namesByCol[match.start()] = match.groups()[0]
colsByName[match.groups()[0]] = match.start()
elif spec[0] == 'b':
for i, c in enumerate(spec[1:]):
if c == ' ' or c == '|':
continue
try:
bit = int(c)
except:
error('Unexpected char in bit line at position ' + str(i) + ' (' + c + ')\n' + line)
bit = None
if i in bitsByCol and bitsByCol[i] is not None:
bitsByCol[i] = bitsByCol[i]*10+bit
else:
bitsByCol[i] = bit
elif spec[0] == 't':
for i, c in enumerate(spec[1:]):
if c.lower() == 'i':
typesByCol[i] = TYPE_INPUT
elif c.lower() == 'o':
typesByCol[i] = TYPE_OUTPUT
elif c.lower() == '*':
typesByCol[i] = TYPE_SKIP
elif c != ' ':
error('Unexpected char in type line at position ' + str(i) + ' (' + c + ')\n' + line)
typesByCol[i] = None
else:
typesByCol[i] = None
elif spec[0] == 's':
specsByCol = {}
for i, c in enumerate(spec[1:]):
if c == '0' or c == '1':
specsByCol[i] = c
specs.append(specsByCol)
else:
#print('other:')
#print(line)
1

# create table object

# add strand to name where defined; don't combine for now into vector
# consecutive strands belong to the last defined name
lastName = None
lastCol = 0
signalsByCol = {}

for col,name in namesByCol.items(): # load with unstranded names
signalsByCol[col] = name

# sort by col so consecutive columns can be easily tracked
#for col,val in bitsByCol.items(): # update with stranded names
for col in sorted(bitsByCol):
val = bitsByCol[col]

if col > lastCol + 1:
lastName = None
if val is None:
lastName = None
if col in namesByCol:
if val is None:
signalsByCol[col] = namesByCol[col]
else:
lastName = namesByCol[col]
signalsByCol[col] = lastName + openBracket + str(val) + closeBracket
elif lastName is not None:
signalsByCol[col] = lastName + openBracket + str(val) + closeBracket
else:
error('Can\'t associate bit number ' + str(val) + ' in column ' + str(col) + ' with a signal name.')
lastCol = col

t = Table(tName)
t.source = table
t.signalsByCol = signalsByCol
t.typesByCol = typesByCol
t.specs = specs

tables[tName] = t

for name in tables:
t = tables[name]
t.validate()
t.makeRTL()

print()
print('Results:')

# find the lines with generate spec and replace them with new version
outLines = []
inTable = False
for i, line in enumerate(lines):
if not inTable:
match = re.search(tableGenPattern, line)
if match is not None:
tName = match.groups(1)[0]
if tName not in tables:
if tName == 1:
tName = '<blank>'
error('Found vtable start for \'' + tName + '\' but didn\'t generate that table: line ' + str(i+1) + '\n' + line, True)
else:
outLines.append(line)
outLines += tables[tName].equations
tables[tName].added = True
inTable = True
else:
outLines.append(line)
else:
match = re.search(tableGenPattern, line)
if match is not None:
if match.groups(1)[0] != tName:
error('Found vtable end for \'' + match.groups(1)[0] + '\' but started table \'' + tName + '\': line ' + str(i+1) + '\n' + line, True)
outLines.append(line)
inTable = False
else:
1#print('stripped: ' + line)

if backup:
try:
copyfile(inFile, backupFile)
except Exception as e:
error('Error creating backup file!\n' + str(e), True)

try:
of = open(outFile, 'w')
for line in outLines:
of.write("%s\n" % line)
except Exception as e:
error('Error writing output file ' + outFile + '!\n' + str(e), True)

print('Generated ' + str(len(tables)) + ' tables: ' + ', '.join(tableNames))
notAdded = {}
for table in tables:
if not tables[table].added:
notAdded[table] = True
print('Output file: ' + outFile)
if backup:
print('Backup file: ' + backupFile)
if len(notAdded) != 0:
error('Tables generated but not added to file! ' + ', '.join(notAdded))

@ -0,0 +1,96 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.

`timescale 1 ns / 1 ns

`include "../toysram.vh"

// configuration macro
// Manages config registers and routes cmd val

module cfg #(
parameter CFG0_INIT = 'h00000000,
parameter ADDR_MASK = 'hFFFF0000,
parameter CFG_ADDR = 'h00000000,
parameter CTL_ADDR = 'h00010000,
parameter RA0_ADDR = 'h00100000
)(
`ifdef USE_POWER_PINS
inout vccd1, // User area 1 1.8V supply
inout vssd1, // User area 1 digital ground
`endif

input clk,
input rst,
input wb_cmd_val,
input [31:0] wb_cmd_adr,
input wb_cmd_we,
input [3:0] wb_cmd_sel,
input [31:0] wb_cmd_dat,
output wb_rd_ack,
output [31:0] wb_rd_dat,

output [31:0] cmd_adr,
output cmd_we,
output [3:0] cmd_sel,
output [31:0] cmd_dat,

output ctl_cmd_val,
output cfg_cmd_val,
output ra0_cmd_val,
input ctl_rd_ack,
input [31:0] ctl_rd_dat

);

reg [7:0] seq_q;
wire [7:0] seq_d;

reg [31:0] cfg0_q;
wire [31:0] cfg0_d;

// FF
always @(posedge clk) begin
if (rst) begin
seq_q <= 'hFF;
cfg0_q <= CFG0_INIT;
end else begin
seq_q <= seq_d;
cfg0_q <= cfg0_d;
end
end

// Common
assign cmd_adr = wb_cmd_adr;
assign cmd_we = wb_cmd_we;
assign cmd_sel = wb_cmd_sel;
assign cmd_dat = wb_cmd_dat;

// Macro Routing
assign cfg_cmd_val = wb_cmd_val & ((wb_cmd_adr & ADDR_MASK) == (CFG_ADDR & ADDR_MASK));
assign cfg0_d = cfg_cmd_val & cmd_we ? cmd_dat : cfg0_q;


assign ctl_cmd_val = wb_cmd_val & ((wb_cmd_adr & ADDR_MASK) == (CTL_ADDR & ADDR_MASK));
assign ra0_cmd_val = wb_cmd_val & ((wb_cmd_adr & ADDR_MASK) == (RA0_ADDR & ADDR_MASK));

assign wb_rd_ack = ctl_rd_ack;
assign wb_rd_dat = ctl_rd_dat;

endmodule

@ -0,0 +1,421 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.

`timescale 1 ns / 1 ns

`include "defines.v"
`include "../toysram.vh"

// control macro
// does stuff

module control #(
parameter ADDR_MASK = 'h0000F000,
parameter CFG_ADDR = 'h0000E000, // offset within RAx_ADDR
parameter BIST_ADDR = 'h0000F000, // offset within RAx_ADDR
parameter CFG0_ADDR = 'h00000000,
parameter CFG0_INIT = 'h00000001
)(
`ifdef USE_POWER_PINS
inout vccd1,
inout vssd1
`endif

input clk,
input rst,

input [`MPRJ_IO_PADS-1:0] io_in,
output [`MPRJ_IO_PADS-1:0] io_out,
output [`MPRJ_IO_PADS-1:0] io_oeb,

input ctl_cmd_val,
input ra0_cmd_val,
input [31:0] cmd_adr,
input cmd_we,
input [3:0] cmd_sel,
input [31:0] cmd_dat,
output rd_ack,
output [31:0] rd_dat,

output ra0_clk,
output ra0_rst,
output ra0_cfg_wr,
input [31:0] ra0_cfg_rdat,
output [31:0] ra0_cfg_wdat,
output [31:0] ra0_bist_ctl,
input [31:0] ra0_bist_status,
output ra0_r0_enb,
output [4:0] ra0_r0_adr,
input [31:0] ra0_r0_dat,
output ra0_r1_enb,
output [4:0] ra0_r1_adr,
input [31:0] ra0_r1_dat,
output ra0_w0_enb,
output [4:0] ra0_w0_adr,
output [31:0] ra0_w0_dat

);

reg [31:0] cfg0_q;
wire [31:0] cfg0_d;
reg [4:0] seq_q;
wire [4:0] seq_d;
reg [2:0] rd_wait_q;
wire [2:0] rd_wait_d;
reg [127:0] scan_reg_q;
wire [127:0] scan_reg_d;

wire ra0_bist_rd;
wire adr_bist;
wire adr_config;
wire special;
wire rd_start;
wire [1:0] rd_type;
wire [2:0] rdata_sel;
wire rd_data;

wire test_enable;
wire scan_clk;
wire scan_di;
wire scan_do;
wire [16:0] scan_config;
wire io_ra0_clk;
wire io_ra0_rst;
wire io_ra0_r0_enb;
wire io_ra0_r1_enb;
wire io_ra0_w0_enb;
wire [4:0] io_ra0_r0_adr;
wire [4:0] io_ra0_r1_adr;
wire [4:0] io_ra0_w0_adr;
wire [31:0] io_ra0_w0_dat;

// FF
always @(posedge clk) begin
if (rst) begin
seq_q <= 'hFF;
cfg0_q <= CFG0_INIT;
rd_wait_q <= 0;
end else begin
seq_q <= seq_d;
cfg0_q <= cfg0_d;
rd_wait_q <= rd_wait_d;
end
end

always @(posedge scan_clk) begin
begin
if (test_enable == 'b1) begin
scan_reg_q <= {scan_reg_q[126:0], scan_di};
end
end
end

always @(posedge io_ra0_clk) begin
if (test_enable == 'b1) begin
scan_reg_q[122:91] <= {ra0_r0_dat};
scan_reg_q[85:54] <= {ra0_r1_dat};
end
end

// GPIO
//
// Scan Controls
// test enable
// scan_clk
// scan_di
// scan_do
//
// Scan Config
// * have a way to single-step on-chip clk so can use it plus scan?
//
// Array Controls
// ra_clk
// ra_rst
// ra_r0_enb
// ra_r1_enb
// ra_w0_enb
//
//
// Scannable RA0 Reg
// ra0_r0_adr
// ra0_r0_dat
// ra0_r1_adr
// ra0_r1_dat
// ra0_w0_adr
// ra0_w0_dat
//
//
// Array Read/Write
// 1. scan in adr/dat reg
// 2. activate ra_clk and ra_xx_enb for port control (n cycles)
// 3. scan out adr/dat reg
//
//
// * not enough I/O to do full-speed reads/writes through I/O; enough for addresses, and could have data gen/chk logic for data

assign test_enable = io_in[0];
assign scan_clk = io_in[1];
assign scan_di = io_in[2];
assign io_out[3] = scan_do;

assign io_ra0_clk = io_in[4];
assign io_ra0_rst = io_in[5];
assign io_ra0_r0_enb = io_in[6];
assign io_ra0_r1_enb = io_in[7];
assign io_ra0_w0_enb = io_in[8];

//assign io_oeb = '{`MPRJ_IO_PADS'('h0000000000000008)};
assign io_oeb = ~'h0000000000000008;

assign io_ra0_r0_adr = scan_reg_q[127:123];
//assign io_ra0_r0_dat = scan_reg_q[122:91]; // loaded by io_ra0_clk
assign io_ra0_r1_adr = scan_reg_q[90:86];
//assign io_ra0_r1_dat = scan_reg_q[85:54]; // loaded by io_ra0_clk
assign io_ra0_w0_adr = scan_reg_q[53:49];
assign io_ra0_w0_dat = scan_reg_q[48:17];

assign scan_config = scan_reg_q[16:0];
assign scan_do = scan_reg_q[127];

// Internal Routing

// CFG0
// 31:03 Reserved
// 02:00 Read Data Wait Cycles (after cmd cycle)
assign cfg0_d = ctl_cmd_val & cmd_we & ((cmd_adr & ~ADDR_MASK) == CFG0_ADDR) ? cmd_dat : cfg0_q;

// Array Routing

assign adr_bist = (cmd_adr & ADDR_MASK) == (BIST_ADDR & ADDR_MASK);
assign adr_config = (cmd_adr & ADDR_MASK) == (CFG_ADDR & ADDR_MASK);
assign special = adr_bist | adr_config;

assign ra0_bist_ctl = ra0_cmd_val & cmd_we & adr_bist ? cmd_dat : 'h00000000;
assign ra0_bist_rd = ra0_cmd_val & ~cmd_we & adr_bist;
assign ra0_cfg_wr = ra0_cmd_val & cmd_we & adr_config;
assign ra0_cfg_wdat = cmd_dat;

// reads can use r0, r1, or both; if both, return either both hi or both lo data

assign rd_type = cmd_adr[15:14]; // port addr 14 bits

// or send test_enable and test_clk/rst to array
assign ra0_clk = test_enable ? io_ra0_clk : clk;
assign ra0_rst = test_enable ? io_ra0_rst : rst;

assign ra0_r0_enb = test_enable ? io_ra0_r0_enb : ra0_cmd_val & ~special & ~cmd_we & (rd_type[0] | ~rd_type[1]);
assign ra0_r1_enb = test_enable ? io_ra0_r1_enb : ra0_cmd_val & ~special & ~cmd_we & (rd_type[0] | rd_type[1]);
assign ra0_r0_adr = test_enable ? io_ra0_r0_adr : cmd_adr[4:0]; // adr=row
assign ra0_r1_adr = test_enable ? io_ra0_r1_adr : rd_type == 'b01 ? cmd_adr[4:0] : cmd_adr[10:6]; // adr=row
assign ra0_w0_enb = test_enable ? io_ra0_w0_enb : ra0_cmd_val & cmd_we & cmd_sel[0]; // sel=port
assign ra0_w0_adr = test_enable ? io_ra0_w0_adr : cmd_adr[4:0]; // adr=row
assign ra0_w0_dat = test_enable ? io_ra0_w0_dat : cmd_dat; //


// Command Sequencer
// rd_data in 1+ cycs; all reads use same timing

//tbl cmdseq
//n seq_q seq_d
//n | ctl_cmd_val | rd_start
//n | |ra0_cmd_val | | rd_ack
//n | ||cmd_we | | | rdata_sel
//n | ||| rd_type | | | |
//n | ||| | adr_bist | | | |
//n | ||| | |adr_config | | | |
//n | ||| | || rd_data | | | |
//n | ||| | || | | | | |
//n | ||| | || | | | | |
//n | ||| | || | | | | |
//b 43210 ||| 10 || | 43210 | | 210
//t iiiii iii ii ii i ooooo o o ooo
//*------------------------------------------------
//* Idle ******************************************
//s 11111 00- -- -- - 11111 0 0 000 * ...zzz..zzzzz....
//s 11111 1-1 -- -- - 11111 0 0 000 * write ctl
//s 11111 -11 -- -- - 11111 0 0 000 * write ra
//s 11111 1-0 -- 00 - 00001 1 0 000 * rd ctl cfg
//s 11111 1-0 -- 1- - 00010 1 0 000 * rd bist
//s 11111 1-0 -- -1 - 00011 1 0 000 * rd cfg
//s 11111 -10 00 -- - 00100 1 0 000 * rd r0
//s 11111 -10 01 -- - 00101 1 0 000 * rd r1
//s 11111 -10 10 -- - 00110 1 0 000 * rd r0+r1 lo
//s 11111 -10 11 -- - 00111 1 0 000 * rd r0_r1 hi
//* Read CTL **************************************
//s 00001 --- -- -- 0 00001 0 0 100
//s 00001 --- -- -- 1 11111 0 1 100
//* Read BIST *************************************
//s 00010 --- -- -- 0 00010 0 0 101
//s 00010 --- -- -- 1 11111 0 1 101
//* Read CFG **************************************
//s 00011 --- -- -- 0 00011 0 0 110
//s 00011 --- -- -- 1 11111 0 1 110
//* Read R0 ***************************************
//s 00100 --- -- -- 0 00100 0 0 000
//s 00100 --- -- -- 1 11111 0 1 000
//* Read R1 ***************************************
//s 00101 --- -- -- 0 00101 0 0 001
//s 00101 --- -- -- 1 11111 0 1 001
//* Read R0+R1 Lo *********************************
//s 00110 --- -- -- 0 00110 0 0 010
//s 00110 --- -- -- 1 11111 0 1 010
//* Read R0+R1 Hi *********************************
//s 00111 --- -- -- 0 00111 0 0 011
//s 00111 --- -- -- 1 11111 0 1 011

//*------------------------------------------------
//tbl cmdseq_d

// use same timing for ra accesses and others
assign rd_wait_d = rd_start ? cfg0_q[2:0] :
(rd_wait_q != 0) ? rd_wait_q - 1 :
rd_wait_q;

assign rd_data = rd_wait_q == 0;

assign rd_dat = rdata_sel == 'b000 ? ra0_r0_dat :
rdata_sel == 'b001 ? ra0_r1_dat :
rdata_sel == 'b010 ? {ra0_r1_dat[15:0],ra0_r0_dat[15:0]} :
rdata_sel == 'b011 ? {ra0_r1_dat[31:16],ra0_r0_dat[31:16]} :
rdata_sel == 'b100 ? cfg0_q :
rdata_sel == 'b101 ? ra0_bist_status :
rdata_sel == 'b110 ? ra0_cfg_rdat :
'hFFFFFFFF;

// Generated...
//vtable cmdseq
assign seq_d[4] =
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ~ctl_cmd_val & ~ra0_cmd_val) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ctl_cmd_val & cmd_we) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ra0_cmd_val & cmd_we) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & ~seq_q[1] & seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & seq_q[1] & ~seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & seq_q[1] & seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & ~seq_q[1] & ~seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & ~seq_q[1] & seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & seq_q[1] & ~seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & rd_data);
assign seq_d[3] =
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ~ctl_cmd_val & ~ra0_cmd_val) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ctl_cmd_val & cmd_we) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ra0_cmd_val & cmd_we) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & ~seq_q[1] & seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & seq_q[1] & ~seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & seq_q[1] & seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & ~seq_q[1] & ~seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & ~seq_q[1] & seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & seq_q[1] & ~seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & rd_data);
assign seq_d[2] =
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ~ctl_cmd_val & ~ra0_cmd_val) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ctl_cmd_val & cmd_we) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ra0_cmd_val & cmd_we) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ra0_cmd_val & ~cmd_we & ~rd_type[1] & ~rd_type[0]) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ra0_cmd_val & ~cmd_we & ~rd_type[1] & rd_type[0]) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ra0_cmd_val & ~cmd_we & rd_type[1] & ~rd_type[0]) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ra0_cmd_val & ~cmd_we & rd_type[1] & rd_type[0]) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & ~seq_q[1] & seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & seq_q[1] & ~seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & seq_q[1] & seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & ~seq_q[1] & ~seq_q[0] & ~rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & ~seq_q[1] & ~seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & ~seq_q[1] & seq_q[0] & ~rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & ~seq_q[1] & seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & seq_q[1] & ~seq_q[0] & ~rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & seq_q[1] & ~seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ~rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & rd_data);
assign seq_d[1] =
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ~ctl_cmd_val & ~ra0_cmd_val) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ctl_cmd_val & cmd_we) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ra0_cmd_val & cmd_we) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ctl_cmd_val & ~cmd_we & adr_bist) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ctl_cmd_val & ~cmd_we & adr_config) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ra0_cmd_val & ~cmd_we & rd_type[1] & ~rd_type[0]) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ra0_cmd_val & ~cmd_we & rd_type[1] & rd_type[0]) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & ~seq_q[1] & seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & seq_q[1] & ~seq_q[0] & ~rd_data) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & seq_q[1] & ~seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & seq_q[1] & seq_q[0] & ~rd_data) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & seq_q[1] & seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & ~seq_q[1] & ~seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & ~seq_q[1] & seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & seq_q[1] & ~seq_q[0] & ~rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & seq_q[1] & ~seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ~rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & rd_data);
assign seq_d[0] =
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ~ctl_cmd_val & ~ra0_cmd_val) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ctl_cmd_val & cmd_we) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ra0_cmd_val & cmd_we) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ctl_cmd_val & ~cmd_we & ~adr_bist & ~adr_config) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ctl_cmd_val & ~cmd_we & adr_config) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ra0_cmd_val & ~cmd_we & ~rd_type[1] & rd_type[0]) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ra0_cmd_val & ~cmd_we & rd_type[1] & rd_type[0]) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & ~seq_q[1] & seq_q[0] & ~rd_data) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & ~seq_q[1] & seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & seq_q[1] & ~seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & seq_q[1] & seq_q[0] & ~rd_data) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & seq_q[1] & seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & ~seq_q[1] & ~seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & ~seq_q[1] & seq_q[0] & ~rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & ~seq_q[1] & seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & seq_q[1] & ~seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ~rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & rd_data);
assign rd_start =
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ctl_cmd_val & ~cmd_we & ~adr_bist & ~adr_config) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ctl_cmd_val & ~cmd_we & adr_bist) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ctl_cmd_val & ~cmd_we & adr_config) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ra0_cmd_val & ~cmd_we & ~rd_type[1] & ~rd_type[0]) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ra0_cmd_val & ~cmd_we & ~rd_type[1] & rd_type[0]) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ra0_cmd_val & ~cmd_we & rd_type[1] & ~rd_type[0]) +
(seq_q[4] & seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ra0_cmd_val & ~cmd_we & rd_type[1] & rd_type[0]);
assign rd_ack =
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & ~seq_q[1] & seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & seq_q[1] & ~seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & seq_q[1] & seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & ~seq_q[1] & ~seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & ~seq_q[1] & seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & seq_q[1] & ~seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & rd_data);
assign rdata_sel[2] =
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & ~seq_q[1] & seq_q[0] & ~rd_data) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & ~seq_q[1] & seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & seq_q[1] & ~seq_q[0] & ~rd_data) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & seq_q[1] & ~seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & seq_q[1] & seq_q[0] & ~rd_data) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & seq_q[1] & seq_q[0] & rd_data);
assign rdata_sel[1] =
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & seq_q[1] & seq_q[0] & ~rd_data) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & seq_q[1] & seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & seq_q[1] & ~seq_q[0] & ~rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & seq_q[1] & ~seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ~rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & rd_data);
assign rdata_sel[0] =
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & seq_q[1] & ~seq_q[0] & ~rd_data) +
(~seq_q[4] & ~seq_q[3] & ~seq_q[2] & seq_q[1] & ~seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & ~seq_q[1] & seq_q[0] & ~rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & ~seq_q[1] & seq_q[0] & rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & ~rd_data) +
(~seq_q[4] & ~seq_q[3] & seq_q[2] & seq_q[1] & seq_q[0] & rd_data);
//vtable cmdseq

endmodule

@ -0,0 +1,61 @@
// SPDX-FileCopyrightText: 2020 Efabless Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// SPDX-License-Identifier: Apache-2.0

`default_nettype none

`ifndef __GLOBAL_DEFINE_H
// Global parameters
`define __GLOBAL_DEFINE_H

`define MPRJ_IO_PADS_1 19 /* number of user GPIO pads on user1 side */
`define MPRJ_IO_PADS_2 19 /* number of user GPIO pads on user2 side */
`define MPRJ_IO_PADS (`MPRJ_IO_PADS_1 + `MPRJ_IO_PADS_2)

`define MPRJ_PWR_PADS_1 2 /* vdda1, vccd1 enable/disable control */
`define MPRJ_PWR_PADS_2 2 /* vdda2, vccd2 enable/disable control */
`define MPRJ_PWR_PADS (`MPRJ_PWR_PADS_1 + `MPRJ_PWR_PADS_2)

// Analog pads are only used by the "caravan" module and associated
// modules such as user_analog_project_wrapper and chip_io_alt.

`define ANALOG_PADS_1 5
`define ANALOG_PADS_2 6

`define ANALOG_PADS (`ANALOG_PADS_1 + `ANALOG_PADS_2)

// Size of soc_mem_synth

// Type and size of soc_mem
// `define USE_OPENRAM
`define USE_CUSTOM_DFFRAM
// don't change the following without double checking addr widths
`define MEM_WORDS 256

// Number of columns in the custom memory; takes one of three values:
// 1 column : 1 KB, 2 column: 2 KB, 4 column: 4KB
`define COLS 1

// not really parameterized but just to easily keep track of the number
// of ram_block across different modules
`define RAM_BLOCKS 2

// Clock divisor default value
`define CLK_DIV 3'b010

// GPIO conrol default mode and enable
`define DM_INIT 3'b110
`define OENB_INIT 1'b1

`endif // __GLOBAL_DEFINE_H

@ -0,0 +1,45 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.

`timescale 1 ns / 1 ns

`include "../toysram.vh"

// I/O interface macro

module io_intf #(
parameter BITS = 32
)(
`ifdef USE_POWER_PINS
inout vdda1, // User area 1 3.3V supply
inout vdda2, // User area 2 3.3V supply
inout vssa1, // User area 1 analog ground
inout vssa2, // User area 2 analog ground
inout vccd1, // User area 1 1.8V supply
inout vccd2, // User area 2 1.8v supply
inout vssd1, // User area 1 digital ground
inout vssd2, // User area 2 digital ground
`endif

input clk,
input reset
);


endmodule

@ -0,0 +1,58 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.

`timescale 1 ns / 1 ns

`include "../toysram.vh"

// miscellaneous logic macro

module misc #(
parameter BITS = 32
)(
`ifdef USE_POWER_PINS
inout vdda1, // User area 1 3.3V supply
inout vdda2, // User area 2 3.3V supply
inout vssa1, // User area 1 analog ground
inout vssa2, // User area 2 analog ground
inout vccd1, // User area 1 1.8V supply
inout vccd2, // User area 2 1.8v supply
inout vssd1, // User area 1 digital ground
inout vssd2, // User area 2 digital ground
`endif

input clk,
input reset,

// Logic Analyzer Signals
input [127:0] la_data_in,
output [127:0] la_data_out,
input [127:0] la_oen,

// Analog (direct connection to GPIO pad---use with caution)
// Note that analog I/O is not available on the 7 lowest-numbered
// GPIO pads, and so the analog_io indexing is offset from the
// GPIO indexing by 7.
inout [`MPRJ_IO_PADS-8:0] analog_io,

// Independent clock (on independent integer divider)
input user_clock2
);

endmodule

@ -0,0 +1,223 @@
<!---
# SPDX-FileCopyrightText: 2020 Efabless Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
-->

A quick documentation of the Caravel memory map and operation
---------------------------------------------------------------

Caravel pinout:
---------------

vddio 3.3V supply for all I/O and ESD
vssio Ground for all I/O and ESD
vdda 3.3V supply for management area
vssa Ground for management area
vccd 1.8V supply for management area
vssd Digital ground for management area

vdda1 3.3V supply for user area 1
vdda2 3.3V supply for user area 2
vssa1 Ground for user area 1
vssa2 Ground for user area 2
vccd1 1.8 supply for user area 1
vccd2 1.8 supply for user area 2
vssd1 Digital ground for user area 1
vssd2 Digital ground for user area 2

clock Master clock input
gpio 1 bit, mainly used for external LDO control of user power supply
mprj_io 32 bits general purpose programmable digital or analog I/O
resetb Master reset (sense inverted) input
flash_csb SPI flash controller chip select (sense inverted)
flash_clk SPI flash controller clock
flash_io0 SPI flash controller data out
flash_io1 SPI flash controller data in

Special-use pins for the management SoC:
----------------------------------------

On power-up, the "mprj_io" GPIO are under complete control of the managment
SoC. The first 8 user GPIO are special-purpose pads with dedicated functions
for the management SoC:

mprj_io[0] JTAG I/O
mprj_io[1] SDO, housekeeping SPI
mprj_io[2] SDI, housekeeping SPI
mprj_io[3] CSB, housekeeping SPI
mprj_io[4] SCK, housekeeping SPI
mprj_io[5] Rx, UART
mprj_io[6] Tx, UART
mprj_io[7] IRQ

The next 4 user GPIO are designed to be used with an SPI flash controller in
the user space. They allow the four pins to be overridden by the housekeeping
SPI to access the SPI flash in pass-through mode.

mprj_io[8] user flash CSB
mprj_io[9] user flash SCK
mprj_io[10] user flash IO0
mprj_io[11] user flash IO1

The last 2 GPIO pins can be used by the management SoC to drive the SPI flash
io2 and io3 pins for quad and DDR access, although they are set as inputs by
default and whenever the SPI flash is not in quad mode:

mprj_io[36] SPI flash io2
mprj_io[37] SPI flash io3

The user may additionally use any available GPIO for the SPI flash IO2 and IO3
lines; the pass-through mode only uses the basic 4-pin SPI mode.

All of the special-use pins are configured through a memory-mapped region. But
to avoid a large number of wires in the user space to reach all of the GPIO
pad controls, each user GPIO pad has a corresponding local control block. The
control block holds the configuration data for the corresponding pad. This
configuration data is a mirror of the data in the memory-mapped region, and is
loaded by a "transfer" bit in another memory-mapped register. In addition to
all of the static control bits for the GPIO, each block contains a single bit
that specifies whether that pad is under the control of the user or the management
area. All pins are configured from the management area. However, the configuration
of static control bits leaves three dynamic signals: input, output, and output
enable. One set of these three signals is available to the user when the pad is
under user control. The other set of these three signals is available to the
management SoC. Again, to reduce wiring, only the two pads for JTAG and the
housekeeping SDO have all three pins under control of the SoC; the remaining
pads have a single wire to the management SoC which is either an input wire
or an output wire, depending on how the control signals for the pad are set.

This setup gives a simplified view of the pad to the user: For digital
applications, the user can treat the pad as a simple bidirectional digital
pad with an output enable to switch between output and input functions.
The user can set the output enable line high or low for a static input or
output function. The user will also have access to the ESD-protected
pad connections for analog signals, and can connect to the VDDA domain
input digital signal if needed.

Memory map:
-----------

The Caravel memory map is as follows:

SRAM: 0000 0000

Flash: Config: 1000 0000

UART: Clock divider: 2000 0000
Data: 2000 0004
Enable 2000 0008

GPIO: Data: 2100 0000
Output enable: 2100 0004
Pullup 2100 0008
Pulldown 2100 000c

Counter 1: Config: 2200 0000
Value: 2200 0004
Data: 2200 0008

Counter 2: Config: 2300 0000
Value: 2300 0004
Data: 2300 0008

SPI master: Config: 2400 0000
Data: 2400 0004

Logic analyzer: Data 0: 2500 0000
Data 1: 2500 0004
Data 2: 2500 0008
Data 3: 2500 000c
Enable 0: 2500 0010
Enable 1: 2500 0014
Enable 2: 2500 0018
Enable 3: 2500 001c

Project ctrl: Data (L): 2600 0000
Data (H): 2600 0004
Transfer: 2600 0008
I/O Config: 2600 000c
to 2600 009c
Power Config: 2600 00a0
to 2600 0130

Flash ctrl: Config: 2D00 0000

System: PLL out: 2F00 0000
Trap out: 2F00 0004
IRQ7 source: 2F00 0008

User area base: 3000 0000

Crossbar: QSPI control 8000 0000
Storage area 9000 0000
Any slave 1 a000 0000
Any slave 2 b000 0000

Project I/O Control:
---------------------

Configuration bits per I/O (13 bits for each GPIO pad):
Global Default
Bits 12-10: digital mode (3 bits) 001
Bit 9: voltage trip point select 0
Bit 8: slow slew select 0
Bit 7: analog bus polarity 0
Bit 6: analog bus select 0
Bit 5: analog bus enable 0
Bit 4: IB mode select 0
Bit 3: input disable 0
Bit 2: holdover value 0
Bit 1: output disable 1
Bit 0: management control enable 1

Default I/O modes:
------------------
mprj_io[0] JTAG I/O 110 0 0 0 0 0 0 0 0 0 1
mprj_io[1] SDO, housekeeping SPI 110 0 0 0 0 0 0 0 0 0 1
all others: 001 0 0 0 0 0 0 0 0 1 1

Standard GPIO output configuration:
mprj_io[6] Tx, UART 110 0 0 0 0 0 0 1 0 0 1

Standard GPIO input configuration:
mprj_io[*] 001 0 0 0 0 0 0 0 0 1 1

Standard GPIO input configuration with pullup:
mprj_io[*] 010 0 0 0 0 0 0 0 0 1 1

Standard GPIO input configuration with pulldown:
mprj_io[*] 011 0 0 0 0 0 0 0 0 1 1

Specifically:
JTAG and SDO are set to output. The output enable configure bit
is a don't-care, since the output enable line is directly controlled
by the module (JTAG or housekeeping SPI, respectively).

All other I/O are set as input mode only, with output disabled.
Tx is set to input like the others; before enabling the UART
from a program in flash, the I/O must be set to an output configuration.
Note that the standard input configurations with pull-up and pull-down
require that "out" be set 1 or 0, respectively; since the I/O are
designed with minimal wiring, there is only one wire for input and
output, so the wire is used for input in these cases, and special
signal handling is done locally to set the value of "out" equal to
~dm[0]. This is a (minor) restriction on the available I/O modes.

Other possible modes are open-drain (for I2C), weak drive strength
output (5k up + down), and analog mode (digital disabled)

@ -0,0 +1,287 @@
// SPDX-FileCopyrightText: 2020 Efabless Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// SPDX-License-Identifier: Apache-2.0

`default_nettype none
/*
* toysram_site
* user_project for custom toysram cell/array


*-------------------------------------------------------------
*
* user_proj_example
*
* This is an example of a (trivially simple) user project,
* showing how the user project can connect to the logic
* analyzer, the wishbone bus, and the I/O pads.
*
* This project generates an integer count, which is output
* on the user area GPIO pads (digital output only). The
* wishbone connection allows the project to be controlled
* (start and stop) from the management SoC program.
*
* See the testbenches in directory "mprj_counter" for the
* example programs that drive this user project. The three
* testbenches are "io_ports", "la_test1", and "la_test2".
*
*-------------------------------------------------------------
*/

module toysram_site #(
parameter BITS = 32
/*
.CFG_ADDR('h00000000),
.CTL_ADDR('h00000100),
.RA0_ADDR('h00001000),
.ADDR_MASK
CFG_ADDR = 'h0000E000, // offset within RAx_ADDR
BIST_ADDR = 'h0000F000 // offset within RAx_ADDR

*/
)(
`ifdef USE_POWER_PINS
inout vccd1, // User area 1 1.8V supply
inout vssd1, // User area 1 digital ground
`endif

// Wishbone Slave ports (WB MI A)
input wb_clk_i,
input wb_rst_i,
input wbs_stb_i,
input wbs_cyc_i,
input wbs_we_i,
input [3:0] wbs_sel_i,
input [31:0] wbs_dat_i,
input [31:0] wbs_adr_i,
output wbs_ack_o,
output [31:0] wbs_dat_o,

// Logic Analyzer Signals
input [127:0] la_data_in,
output [127:0] la_data_out,
input [127:0] la_oenb,

// IOs
input [`MPRJ_IO_PADS-1:0] io_in,
output [`MPRJ_IO_PADS-1:0] io_out,
output [`MPRJ_IO_PADS-1:0] io_oeb,

// IRQ
output [2:0] irq
);

wire clk;
wire rst;

wire [31:0] rdata;
wire [31:0] wdata;
wire [31:0] count;

wire valid;
wire [3:0] wstrb;
wire [31:0] la_write;

wire wb_cmd_val;
wire [31:0] wb_cmd_adr;
wire wb_cmd_we;
wire [3:0] wb_cmd_sel;
wire [31:0] wb_cmd_dat;
wire wb_rd_ack;
wire [31:0] wb_rd_dat;
wire [31:0] cmd_adr;
wire cmd_we;
wire [3:0] cmd_sel;
wire [31:0] cmd_dat;
wire ctl_cmd_val;
wire cfg_cmd_val;
wire ra0_cmd_val;
wire ctl_rd_ack;
wire [31:0] ctl_rd_dat;
wire ra0_clk;
wire ra0_rst;
wire ra0_cfg_wr;
wire [31:0] ra0_cfg_rdat;
wire [31:0] ra0_cfg_wdat;
wire [31:0] ra0_bist_ctl;
wire [31:0] ra0_bist_status;
wire ra0_r0_enb;
wire [4:0] ra0_r0_adr;
wire [31:0] ra0_r0_dat;
wire ra0_r1_enb;
wire [4:0] ra0_r1_adr;
wire [31:0] ra0_r1_dat;
wire ra0_w0_enb;
wire [4:0] ra0_w0_adr;
wire [31:0] ra0_w0_dat;

// WB MI A
assign valid = wbs_cyc_i && wbs_stb_i;
assign wstrb = wbs_sel_i & {4{wbs_we_i}};
assign wbs_dat_o = rdata;
assign wdata = wbs_dat_i;

// IRQ
assign irq = 3'b000; // Unused


//wtf connect these to the array sigs?
// LA
//assign la_data_out = {{(127-BITS){1'b0}}, count};
assign la_data_out = 0;
// Assuming LA probes [63:32] are for controlling the count register
//assign la_write = ~la_oenb[63:32] & ~{BITS{valid}};
assign la_write = 0;

// Assuming LA probes [65:64] are for controlling the count clk & reset
//assign clk = (~la_oenb[64]) ? la_data_in[64]: wb_clk_i;
//assign rst = (~la_oenb[65]) ? la_data_in[65]: wb_rst_i;
assign clk = wb_clk_i;
assign rst = wb_rst_i;

// WB slave
// convert rd/wr commands to/from WB and route to:
// 1. config space
// 2. array space
wb_slave wb (

`ifdef USE_POWER_PINS
.vccd1(vccd1),
.vssd1(vssd1),
`endif
.clk(clk),
.rst(rst),
.wbs_stb_i(wbs_stb_i),
.wbs_cyc_i(wbs_cyc_i),
.wbs_we_i(wbs_we_i),
.wbs_sel_i(wbs_sel_i),
.wbs_dat_i(wbs_dat_i),
.wbs_adr_i(wbs_adr_i),
.wbs_ack_o(wbs_ack_o),
.wbs_dat_o(wbs_dat_o),
.cmd_val(wb_cmd_val),
.cmd_adr(wb_cmd_adr),
.cmd_we(wb_cmd_we),
.cmd_sel(wb_cmd_sel),
.cmd_dat(wb_cmd_dat),
.rd_ack(wb_rd_ack),
.rd_dat(wb_rd_dat)
);


// register/config space
cfg #(
.CFG_ADDR('h00000000),
.CTL_ADDR('h00010000),
.RA0_ADDR('h00100000)
) cfg (

`ifdef USE_POWER_PINS
.vccd1(vccd1),
.vssd1(vssd1),
`endif
.clk(clk),
.rst(rst),
.wb_cmd_val(wb_cmd_val),
.wb_cmd_adr(wb_cmd_adr),
.wb_cmd_we(wb_cmd_we),
.wb_cmd_sel(wb_cmd_sel),
.wb_cmd_dat(wb_cmd_dat),
.wb_rd_ack(wb_rd_ack),
.wb_rd_dat(wb_rd_dat),
.cmd_adr(cmd_adr),
.cmd_we(cmd_we),
.cmd_sel(cmd_sel),
.cmd_dat(cmd_dat),
.ctl_cmd_val(ctl_cmd_val),
.cfg_cmd_val(cfg_cmd_val),
.ra0_cmd_val(ra0_cmd_val),
.ctl_rd_ack(ctl_rd_ack),
.ctl_rd_dat(ctl_rd_dat)
);

/*
// I/O interface
io_intf io (

`ifdef USE_POWER_PINS
.vccd1(vccd1),
.vssd1(vssd1),
`endif
.clk(clk),
.rst(rst)

);
*/

// array interfaces
control #(
) ctl (
`ifdef USE_POWER_PINS
.vccd1(vccd1),
.vssd1(vssd1),
`endif
.clk(clk),
.rst(rst),
.io_in(io_in),
.io_out(io_out),
.io_oeb(io_oeb),
.ctl_cmd_val(ctl_cmd_val),
.ra0_cmd_val(ra0_cmd_val),
.cmd_we(cmd_we),
.cmd_adr(cmd_adr),
.cmd_sel(cmd_sel),
.cmd_dat(cmd_dat),
.rd_ack(ctl_rd_ack),
.rd_dat(ctl_rd_dat),
.ra0_clk(ra0_clk),
.ra0_rst(ra0_rst),
.ra0_cfg_wr(ra0_cfg_wr),
.ra0_cfg_rdat(), //'hFFFFFFFF'), //wtf need to add to ra for read
.ra0_cfg_wdat(ra0_cfg_wdat),
.ra0_bist_ctl(ra0_bist_ctl),
.ra0_bist_status(ra0_bist_status),
.ra0_r0_enb(ra0_r0_enb),
.ra0_r0_adr(ra0_r0_adr),
.ra0_r0_dat(ra0_r0_dat),
.ra0_r1_enb(ra0_r1_enb),
.ra0_r1_adr(ra0_r1_adr),
.ra0_r1_dat(ra0_r1_dat),
.ra0_w0_enb(ra0_w0_enb),
.ra0_w0_adr(ra0_w0_adr),
.ra0_w0_dat(ra0_w0_dat)
);

// arrays
test_ra_sdr_32x32 ra_0 (
.clk(ra0_clk),
.reset(ra0_rst),
.cfg_wr(ra0_cfg_wr),
.cfg_dat(ra0_cfg_wdat),
.bist_ctl(ra0_bist_ctl),
.bist_status(ra0_bist_status),
.rd_enb_0(ra0_r0_enb),
.rd_adr_0(ra0_r0_adr),
.rd_dat_0(ra0_r0_dat),
.rd_enb_1(ra0_r1_enb),
.rd_adr_1(ra0_r1_adr),
.rd_dat_1(ra0_r1_dat),
.wr_enb_0(ra0_w0_enb),
.wr_adr_0(ra0_w0_adr),
.wr_dat_0(ra0_w0_dat)
);

endmodule

`default_nettype wire

@ -0,0 +1,83 @@
// SPDX-FileCopyrightText: 2020 Efabless Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// SPDX-License-Identifier: Apache-2.0

`default_nettype none

`include "../toysram.vh"

/*
*-------------------------------------------------------------
*
* user_project_wrapper
*
* This wrapper enumerates all of the pins available to the
* user for the user project.
*
* An example user project is provided in this wrapper. The
* example should be removed and replaced with the actual
* user project.
*
*-------------------------------------------------------------
*/

module user_project_wrapper #(
parameter BITS = 32
)(
`ifdef USE_POWER_PINS
inout vdda1, // User area 1 3.3V supply
inout vdda2, // User area 2 3.3V supply
inout vssa1, // User area 1 analog ground
inout vssa2, // User area 2 analog ground
inout vccd1, // User area 1 1.8V supply
inout vccd2, // User area 2 1.8v supply
inout vssd1, // User area 1 digital ground
inout vssd2, // User area 2 digital ground
`endif

// Wishbone Slave ports (WB MI A)
input wb_clk_i,
input wb_rst_i,
input wbs_stb_i,
input wbs_cyc_i,
input wbs_we_i,
input [3:0] wbs_sel_i,
input [31:0] wbs_dat_i,
input [31:0] wbs_adr_i,
output wbs_ack_o,
output [31:0] wbs_dat_o,

// Logic Analyzer Signals
input [127:0] la_data_in,
output [127:0] la_data_out,
input [127:0] la_oen,

// IOs
input [`MPRJ_IO_PADS-1:0] io_in,
output [`MPRJ_IO_PADS-1:0] io_out,
output [`MPRJ_IO_PADS-1:0] io_oeb,

// Analog (direct connection to GPIO pad---use with caution)
// Note that analog I/O is not available on the 7 lowest-numbered
// GPIO pads, and so the analog_io indexing is offset from the
// GPIO indexing by 7.
inout [`MPRJ_IO_PADS-8:0] analog_io,

// Independent clock (on independent integer divider)
input user_clock2
);



endmodule // user_project_wrapper

@ -0,0 +1,117 @@
// © IBM Corp. 2021
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by the terms below; you may not use the files in this
// repository except in compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the License, the "Work" hereby includes implementations of
// the work of authorship in physical form.
//
// Unless required by applicable law or agreed to in writing, the reference design distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
// Brief explanation of modifications:
//
// Modification 1: This modification extends the patent license to an implementation of the Work in physical form i.e.,
// it unambiguously permits a user to make and use the physical chip.

`timescale 1 ns / 1 ns

`include "../toysram.vh"

// Wishbone slave macro
// Bridges internal read/write commands to/from Wishbone.

module wb_slave (
`ifdef USE_POWER_PINS
inout vccd1,
inout vssd1,
`endif

input clk,
input rst,
input wbs_stb_i,
input wbs_cyc_i,
input wbs_we_i,
input [3:0] wbs_sel_i,
input [31:0] wbs_dat_i,
input [31:0] wbs_adr_i,
output wbs_ack_o,
output [31:0] wbs_dat_o,
output cmd_val,
output [31:0] cmd_adr,
output cmd_we,
output [3:0] cmd_sel,
output [31:0] cmd_dat,
input rd_ack,
input [31:0] rd_dat

);

reg cmd_val_q;
wire cmd_val_d;
reg [31:0] cmd_adr_q;
wire [31:0] cmd_adr_d;
reg cmd_we_q;
wire cmd_we_d;
reg [3:0] cmd_sel_q;
wire [3:0] cmd_sel_d;
reg [31:0] cmd_dat_q;
wire [31:0] cmd_dat_d;
reg rd_ack_q;
wire rd_ack_d;
reg [31:0] rd_dat_q;
wire [31:0] rd_dat_d;

wire stall;
wire base_match;

// FF
always @(posedge clk) begin
if (rst) begin
cmd_val_q <= 1'b0;
cmd_adr_q <= 31'h0;
cmd_we_q <= 1'b0;
cmd_sel_q <= 4'b0;
cmd_dat_q <= 32'h0;
rd_ack_q <= 1'b0;
rd_dat_q <= 32'h0;
end else begin
cmd_val_q <= cmd_val_d;
cmd_adr_q <= cmd_adr_d;
cmd_we_q <= cmd_we_d;
cmd_sel_q <= cmd_sel_d;
cmd_dat_q <= cmd_dat_d;
rd_ack_q <= rd_ack_d;
rd_dat_q <= rd_dat_d;
end
end

// WB

assign stall = 'b0;
assign base_match = 'b1;

assign cmd_val_d = base_match & wbs_stb_i & ~stall;
assign cmd_adr_d = wbs_adr_i[27:0];
assign cmd_we_d = wbs_we_i;
assign cmd_sel_d = wbs_sel_i;
assign cmd_dat_d = wbs_dat_i;
assign wbs_ack_o = rd_ack_q | (cmd_val_q & cmd_we_q); // block with reset?
assign wbs_dat_o = rd_dat_q;

// Outputs

assign cmd_val = cmd_val_q;
assign cmd_adr = cmd_adr_q;
assign cmd_we = cmd_we_q;
assign cmd_sel = cmd_sel_q;
assign cmd_dat = cmd_dat_q;

// Inputs
assign rd_ack_d = rd_ack;
assign rd_dat_d = rd_dat;

endmodule

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save