init
commit
f9d5f06f61
Binary file not shown.
Binary file not shown.
Binary file not shown.
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 |
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
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
@ -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,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,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,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,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
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue