Merge pull request #859 from litghost/timing_minitest

Adds timing minitest
This commit is contained in:
litghost 2019-05-30 07:30:22 -07:00 committed by GitHub
commit d876d6b9e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 5299 additions and 0 deletions

60
minitests/timing/Makefile Normal file
View File

@ -0,0 +1,60 @@
all:
clean:
rm -r build
build/.touch:
mkdir -p build
touch build/.touch
%.json: %.json5
python3 clean_json5.py < $< > $@
CURDIR=$(shell pwd)
define output_timing
# $(1) - ITER
# $(2) - DESIGN_NAME
# $(3) - VERILOGS
build/$(2)_$(1)/timing_$(2)_$(1).json5: build/.touch runme.tcl $(3)
rm -rf build/$(2)_$(1)
mkdir -p build/$(2)_$(1)
export ITER=$(1) DESIGN_NAME=$(2) VERILOGS="$(3)" && cd build/$(2)_$(1) && \
${XRAY_VIVADO} -mode batch -source ${CURDIR}/runme.tcl > design_$(2)_$(1)_vivado.log
build/timing_$(2)_$(1).xlsx: build/$(2)_$(1)/timing_$(2)_$(1).json create_timing_worksheet_db.py
python3 create_timing_worksheet_db.py \
--timing_json build/$(2)_$(1)/timing_$(2)_$(1).json \
--db_root ${XRAY_DATABASE_DIR}/${XRAY_DATABASE} \
--output_xlsx build/timing_$(2)_$(1).xlsx
build/$(2)_$(1)/design_$(2)_$(1).fasm: build/$(2)_$(1)/timing_$(2)_$(1).json
${XRAY_BIT2FASM} --verbose build/$(2)_$(1)/design_$(2)_$(1).bit > build/$(2)_$(1)/design_$(2)_$(1).fasm
$(2)_$(1): build/timing_$(2)_$(1).xlsx build/$(2)_$(1)/design_$(2)_$(1).fasm
$(2): $(2)_$(1)
.PHONY: $(2) $(2)_$(1)
all: $(2)_$(1)
endef
$(foreach ITER,$(shell seq 1 63), $(eval $(call output_timing,$(ITER),dff,${CURDIR}/top_dff.v)))
$(foreach ITER,$(shell seq 1 63), $(eval $(call output_timing,$(ITER),cff,${CURDIR}/top_cff.v)))
$(foreach ITER,$(shell seq 1 63), $(eval $(call output_timing,$(ITER),bff,${CURDIR}/top_bff.v)))
$(foreach ITER,$(shell seq 1 63), $(eval $(call output_timing,$(ITER),aff,${CURDIR}/top_aff.v)))
$(foreach ITER,$(shell seq 1 63), $(eval $(call output_timing,$(ITER),dff2,${CURDIR}/top_dff2.v)))
$(foreach ITER,$(shell seq 1 63), $(eval $(call output_timing,$(ITER),dff_inter,${CURDIR}/top_dff_inter.v)))
$(foreach ITER,$(shell seq 1 63), $(eval $(call output_timing,$(ITER),dff_slicem,${CURDIR}/top_dff_slicem.v)))
$(foreach ITER,20 50 100 1000 10000, $(eval $(call output_timing,$(ITER),fanout,${CURDIR}/top_fanout.v)))
$(foreach ITER,0, $(eval $(call output_timing,$(ITER),fanout_ex,${CURDIR}/fanout_ex.v)))
$(foreach ITER,0, $(eval $(call output_timing,$(ITER),counter,${CURDIR}/top_counter.v)))
$(foreach ITER,$(shell seq 1 3), $(eval $(call output_timing,$(ITER),picorv32, \
$(addprefix ${CURDIR}/, \
picosoc_noflash.v picorv32.v progmem.v basys3_demo.v simpleuart.v))))
.PHONY: all clean

View File

@ -0,0 +1,35 @@
Timing minitest
===============
This minitest uses Vivado to compile a design and extracts the relevant timing
metadata from the design, e.g. what are the nets and how was the design routed.
For each clock path, the final timing is provided for each of the 4 corners of
analysis.
From the timing metadata, ``create_timing_worksheet_db.py`` creates a worksheet
breaking down the interconnect timing calculation and generating a final
comparision between the reduced model implemented in prjxray and the Vivado
timing results.
Model quality
=============
The prjxray timing handles most nets +/- 1.5% delay. The large exception to
this is clock nets, which appear to use a table lookup that is not understood
at this time.
Running the model
=================
The provided Makefile will by default compile all examples. It a specific design
family is desired, the family name can be provided. If a specific design within
a family is desired, use ``<family name>_<iter>``.
Example:
```
# Build all variants of the DFF loopback test
make dff
# Build only DESIGN_NAME=dff ITER=63
make dff_63
```

View File

@ -0,0 +1,88 @@
/*
* PicoSoC - A simple example SoC using PicoRV32
*
* Copyright (C) 2017 Clifford Wolf <clifford@clifford.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
module top (
input clk,
input di,
input stb,
output do
);
wire ser_tx;
wire ser_rx;
wire [3:0] leds;
assign ser_rx = di ^ stb;
assign do = ^leds ^ ser_tx;
reg [5:0] reset_cnt = 0;
wire resetn = &reset_cnt;
always @(posedge clk) begin
reset_cnt <= reset_cnt + !resetn;
end
wire iomem_valid;
reg iomem_ready;
wire [3:0] iomem_wstrb;
wire [31:0] iomem_addr;
wire [31:0] iomem_wdata;
reg [31:0] iomem_rdata;
reg [31:0] gpio;
assign leds = gpio[3:0];
always @(posedge clk) begin
if (!resetn) begin
gpio <= 0;
end else begin
iomem_ready <= 0;
if (iomem_valid && !iomem_ready && iomem_addr[31:24] == 8'h 03) begin
iomem_ready <= 1;
iomem_rdata <= gpio;
if (iomem_wstrb[0]) gpio[ 7: 0] <= iomem_wdata[ 7: 0];
if (iomem_wstrb[1]) gpio[15: 8] <= iomem_wdata[15: 8];
if (iomem_wstrb[2]) gpio[23:16] <= iomem_wdata[23:16];
if (iomem_wstrb[3]) gpio[31:24] <= iomem_wdata[31:24];
end
end
end
picosoc_noflash soc (
.clk (clk),
.resetn (resetn ),
.ser_tx (ser_tx ),
.ser_rx (ser_rx ),
.irq_5 (1'b0 ),
.irq_6 (1'b0 ),
.irq_7 (1'b0 ),
.iomem_valid (iomem_valid ),
.iomem_ready (iomem_ready ),
.iomem_wstrb (iomem_wstrb ),
.iomem_addr (iomem_addr ),
.iomem_wdata (iomem_wdata ),
.iomem_rdata (iomem_rdata )
);
endmodule

View File

@ -0,0 +1,11 @@
import pyjson5
import simplejson
import sys
def main():
simplejson.dump(pyjson5.load(sys.stdin), sys.stdout, indent=2)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,518 @@
import argparse
import json
from openpyxl import Workbook, utils
from prjxray.tile import OutPinTiming, InPinTiming
from prjxray.timing import Outpin, Inpin, Wire, Buffer, \
PassTransistor, IntristicDelay, RcElement, PvtCorner
from prjxray.math_models import ExcelMathModel
from prjxray.db import Database
FAST = PvtCorner.FAST
SLOW = PvtCorner.SLOW
class TimingLookup(object):
def __init__(self, db, nodes):
self.db = db
self.grid = db.grid()
self.nodes = nodes
def try_find_site_pin(self, site_pin_node, node_idx):
site_pin_wire = self.nodes[site_pin_node]['wires'][node_idx]['name']
tile, wire_in_tile = site_pin_wire.split('/')
gridinfo = self.grid.gridinfo_at_tilename(tile)
tile_type = self.db.get_tile_type(gridinfo.tile_type)
for site in tile_type.get_sites():
for site_pin in site.site_pins:
if site_pin.wire == wire_in_tile:
return site_pin
return None
def find_site_pin(self, site_pin_node, node_idx):
site_pin = self.try_find_site_pin(site_pin_node, node_idx)
assert site_pin is not None, site_pin_node
return site_pin
def find_pip(self, pip_name):
tile, pip = pip_name.split('/')
gridinfo = self.grid.gridinfo_at_tilename(tile)
tile_type = self.db.get_tile_type(gridinfo.tile_type)
return tile_type.get_pip_by_name(pip)
def find_wire(self, wire_name):
tile, wire_in_tile = wire_name.split('/')
gridinfo = self.grid.gridinfo_at_tilename(tile)
tile_type = self.db.get_tile_type(gridinfo.tile_type)
return tile_type.wires[wire_in_tile]
def delays_to_cells(ws, row, delays, cells):
cells['FAST_MAX'] = 'E{}'.format(row)
cells['FAST_MIN'] = 'F{}'.format(row)
cells['SLOW_MAX'] = 'G{}'.format(row)
cells['SLOW_MIN'] = 'H{}'.format(row)
if delays is not None:
ws[cells['FAST_MAX']] = delays[FAST].max
ws[cells['FAST_MIN']] = delays[FAST].min
ws[cells['SLOW_MAX']] = delays[SLOW].max
ws[cells['SLOW_MIN']] = delays[SLOW].min
else:
ws[cells['FAST_MAX']] = 0
ws[cells['FAST_MIN']] = 0
ws[cells['SLOW_MAX']] = 0
ws[cells['SLOW_MIN']] = 0
def cells_to_delays(cells):
return {
FAST: IntristicDelay(min=cells['FAST_MIN'], max=cells['FAST_MAX']),
SLOW: IntristicDelay(min=cells['SLOW_MIN'], max=cells['SLOW_MAX']),
}
class Net(object):
def __init__(self, net):
self.net = net
self.ipin_nodes = {}
self.row = None
self.math = ExcelMathModel()
self.models = {}
for ipin in net['ipins']:
self.ipin_nodes[ipin['node']] = ipin
# Map of wire name to parent node
self.wire_to_node = {}
# Map of node name to node
self.node_name_to_node = {}
for node in net['nodes']:
self.node_name_to_node[node['name']] = node
for wire in node['wires']:
self.wire_to_node[wire['name']] = node
# Map of (src node, dst wire).
self.pips = {}
for pip in net['pips']:
src_node = self.wire_to_node[pip['src_wire']]['name']
dst_wire = pip['dst_wire'].split('/')[1]
self.pips[(src_node, dst_wire)] = pip
if not pip['is_directional']:
dst_node = self.wire_to_node[pip['dst_wire']]['name']
src_wire = pip['src_wire'].split('/')[1]
self.pips[(dst_node, src_wire)] = pip
def extend_rc_tree(self, ws, current_rc_root, timing_lookup, node):
rc_elements = []
for wire in node['wires']:
wire_timing = timing_lookup.find_wire(wire['name'])
ws['A{}'.format(self.row)] = wire['name']
ws['B{}'.format(self.row)] = 'Part of wire'
if wire_timing is not None:
cells = {}
cells['R'] = 'C{}'.format(self.row)
cells['C'] = 'D{}'.format(self.row)
ws[cells['R']] = wire_timing.resistance
ws[cells['C']] = wire_timing.capacitance
rc_elements.append(
RcElement(
resistance=cells['R'],
capacitance=cells['C'],
))
self.row += 1
wire_rc_node = Wire(rc_elements=rc_elements, math=self.math)
self.models[self.row - 1] = wire_rc_node
current_rc_root.set_sink_wire(wire_rc_node)
return wire_rc_node
def descend_route(
self,
ws,
timing_lookup,
current_node,
route,
route_idx,
current_rc_root,
was_opin=False):
""" Traverse the next pip, or recurse deeper. """
# descend_route should've consumed this token
assert route[route_idx] != '}'
while route[route_idx] == '{':
# Go deeper
route_idx = self.descend_route(
ws,
timing_lookup,
current_node,
route,
route_idx=route_idx + 1,
current_rc_root=current_rc_root,
was_opin=was_opin)
next_edge = (current_node, route[route_idx])
route_idx += 1
assert next_edge in self.pips, (next_edge, self.pips.keys())
pip = self.pips[next_edge]
is_backward = self.wire_to_node[
pip['dst_wire']]['name'] == current_node
if not is_backward:
assert self.wire_to_node[
pip['src_wire']]['name'] == current_node, (current_node, pip)
pip_info = timing_lookup.find_pip(pip['name'])
if not is_backward:
pip_timing = pip_info.timing
current_node = self.wire_to_node[pip['dst_wire']]['name']
else:
pip_timing = pip_info.backward_timing
current_node = self.wire_to_node[pip['src_wire']]['name']
ws['A{}'.format(self.row)] = pip['name']
cells = {}
cells['R'] = 'C{}'.format(self.row)
cells['C'] = 'D{}'.format(self.row)
delays_to_cells(
ws, row=self.row, delays=pip_timing.delays, cells=cells)
delays = cells_to_delays(cells)
if pip_info.is_pass_transistor:
ws['B{}'.format(self.row)] = 'PassTransistor'
ws[cells['R']] = pip_timing.drive_resistance
pip_model = PassTransistor(
drive_resistance=cells['R'],
delays=delays,
)
else:
ws['B{}'.format(self.row)] = 'Buffer'
if pip_timing.drive_resistance is not None:
ws[cells['R']] = pip_timing.drive_resistance
if pip_timing.drive_resistance == 0 and was_opin:
new_site_pin = timing_lookup.try_find_site_pin(
current_node, node_idx=0)
if new_site_pin is not None:
ws[cells['R']] = new_site_pin.timing.drive_resistance
else:
ws[cells['R']] = 0
if pip_timing.internal_capacitance is not None:
ws[cells['C']] = pip_timing.internal_capacitance
else:
ws[cells['C']] = 0
pip_model = Buffer(
drive_resistance=cells['R'],
internal_capacitance=cells['C'],
delays=cells_to_delays(cells),
)
self.models[self.row] = pip_model
current_rc_root.add_child(pip_model)
self.row += 1
if current_node in self.ipin_nodes:
assert route[route_idx] == '}'
route_idx += 1
node = self.node_name_to_node[current_node]
current_rc_root = self.extend_rc_tree(
ws, pip_model, timing_lookup, node)
if current_node in self.ipin_nodes:
ipin = self.ipin_nodes[current_node]
cells = {}
name = '{} to {}'.format(self.net['opin']['name'], ipin['name'])
ws['A{}'.format(self.row)] = ipin['name']
ws['B{}'.format(self.row)] = 'Inpin'
site_pin = timing_lookup.find_site_pin(ipin['node'], node_idx=-1)
assert isinstance(site_pin.timing, InPinTiming)
cells = {}
cells['C'] = 'D{}'.format(self.row)
delays_to_cells(
ws, row=self.row, delays=site_pin.timing.delays, cells=cells)
delays = cells_to_delays(cells)
ws[cells['C']] = site_pin.timing.capacitance
ipin_model = Inpin(
capacitance=cells['C'], delays=delays, name=name)
self.models[self.row] = ipin_model
current_rc_root.add_child(ipin_model)
self.row += 1
#Sum delays only (sum*1000)
#Sum delays + capacitive delay
#
#Total delay (from Vivado)
ws['A{}'.format(self.row)] = '{}: {} sum delays'.format(
self.net['net'], name)
self.row += 1
ws['A{}'.format(self.row)] = '{}: {}sum delays + cap delay'.format(
self.net['net'], name)
self.row += 2
ws['A{}'.format(
self.row)] = '{}: {}Total delay (from Vivado)'.format(
self.net['net'], name)
ws['E{}'.format(self.row)] = ipin['ic_delays']['FAST_MAX']
ws['F{}'.format(self.row)] = ipin['ic_delays']['FAST_MIN']
ws['G{}'.format(self.row)] = ipin['ic_delays']['SLOW_MAX']
ws['H{}'.format(self.row)] = ipin['ic_delays']['SLOW_MIN']
self.row += 2
return route_idx
else:
return self.descend_route(
ws,
timing_lookup,
current_node,
route,
route_idx=route_idx,
current_rc_root=current_rc_root)
def walk_route(self, ws, timing_lookup):
""" Walk route, creating rows in table.
First row will always be the OPIN, followed by the node/wire connected
to the OPIN. After a node/wire is always 1 or more pips. After a pip
is always a node/wire. A terminal node/wire will then reach an IPIN.
"""
self.row = 2
ws['A{}'.format(self.row)] = self.net['opin']['wire']
site_pin = timing_lookup.find_site_pin(
self.net['opin']['node'], node_idx=0)
assert isinstance(site_pin.timing, OutPinTiming)
ws['B{}'.format(self.row)] = 'Outpin'
ws['C{}'.format(self.row)] = site_pin.timing.drive_resistance
cells = {}
cells['R'] = 'C{}'.format(self.row)
delays_to_cells(
ws, row=self.row, delays=site_pin.timing.delays, cells=cells)
model_root = Outpin(
resistance=cells['R'], delays=cells_to_delays(cells))
self.models[self.row] = model_root
self.row += 1
node = self.net['opin']['node']
tile, first_wire = self.net['opin']['node'].split('/')
route = [r for r in self.net['route'].strip().split(' ') if r != '']
assert route[0] == '{'
assert route[1] == first_wire
node = self.node_name_to_node[node]
current_rc_root = self.extend_rc_tree(
ws, model_root, timing_lookup, node)
self.descend_route(
ws,
timing_lookup,
node['name'],
route,
route_idx=2,
current_rc_root=current_rc_root,
was_opin=True)
model_root.propigate_delays(self.math)
model_rows = {}
for row, model in self.models.items():
model_rows[id(model)] = row
for row, model in self.models.items():
rc_delay = model.get_rc_delay()
if rc_delay is not None:
ws['J{}'.format(row)] = self.math.eval(rc_delay)
downstream_cap = model.get_downstream_cap()
if downstream_cap is not None:
ws['I{}'.format(row)] = self.math.eval(downstream_cap)
if isinstance(model, Inpin):
ipin_results = {
'Name': model.name,
'truth': {},
'computed': {},
}
ipin_delays = {}
DELAY_COLS = (
('E', 'FAST_MAX'),
('F', 'FAST_MIN'),
('G', 'SLOW_MAX'),
('H', 'SLOW_MIN'),
)
for col, value in DELAY_COLS:
ipin_delays[value] = []
ipin_results['computed'][
value] = '{title}!{col}{row}'.format(
title=utils.quote_sheetname(ws.title),
col=col,
row=row + 2)
ipin_results['truth'][value] = '{title}!{col}{row}'.format(
title=utils.quote_sheetname(ws.title),
col=col,
row=row + 4)
rc_delays = []
for model in model.get_delays():
delays = model.get_intrinsic_delays()
if delays is not None:
ipin_delays['FAST_MAX'].append(delays[FAST].max)
ipin_delays['FAST_MIN'].append(delays[FAST].min)
ipin_delays['SLOW_MAX'].append(delays[SLOW].max)
ipin_delays['SLOW_MIN'].append(delays[SLOW].min)
if id(model) in model_rows:
rc_delays.append('J{}'.format(model_rows[id(model)]))
ws['J{}'.format(row + 1)] = self.math.eval(
self.math.sum(rc_delays))
for col, value in DELAY_COLS:
ws['{}{}'.format(col, row + 1)] = self.math.eval(
self.math.sum(ipin_delays[value]))
ws['{}{}'.format(
col, row + 2)] = '=1000*({col}{row} + J{row})'.format(
col=col, row=row + 1)
yield ipin_results
def add_net(wb, net, timing_lookup):
ws = wb.create_sheet(
title="Net {}".format(net['net'].replace('[', '_').replace(']', '_')))
# Header
ws['A1'] = 'Name'
ws['B1'] = 'Type'
ws['C1'] = 'RES'
ws['D1'] = 'CAP'
ws['E1'] = 'FAST_MAX'
ws['F1'] = 'FAST_MIN'
ws['G1'] = 'SLOW_MAX'
ws['H1'] = 'SLOW_MIN'
ws['I1'] = 'Downstream C'
ws['J1'] = 'Delay from cap'
net_obj = Net(net)
yield from net_obj.walk_route(ws, timing_lookup)
def main():
parser = argparse.ArgumentParser(
description="Create timing worksheet for 7-series timing analysis.")
parser.add_argument('--timing_json', required=True)
parser.add_argument('--db_root', required=True)
parser.add_argument('--output_xlsx', required=True)
args = parser.parse_args()
with open(args.timing_json) as f:
timing = json.load(f)
db = Database(args.db_root)
nodes = {}
for net in timing:
for node in net['nodes']:
nodes[node['name']] = node
timing_lookup = TimingLookup(db, nodes)
wb = Workbook()
summary_ws = wb.get_sheet_by_name(wb.sheetnames[0])
summary_ws.title = 'Summary'
summary_ws['A1'] = 'Name'
cols = ['FAST_MAX', 'FAST_MIN', 'SLOW_MAX', 'SLOW_MIN']
cur_col = 'B'
for col in cols:
summary_ws['{}1'.format(cur_col)] = col
cur_col = chr(ord(cur_col) + 1)
summary_ws['{}1'.format(cur_col)] = 'Computed ' + col
cur_col = chr(ord(cur_col) + 3)
summary_row = 2
for net in timing:
if '<' in net['route']:
print(
"WARNING: Skipping net {} because it has complicated route description."
.format(net['net']))
continue
for summary_cells in add_net(wb, net, timing_lookup):
summary_ws['A{}'.format(summary_row)] = summary_cells['Name']
cur_col = 'B'
for col in cols:
truth_col = chr(ord(cur_col) + 0)
computed_col = chr(ord(cur_col) + 1)
error_col = chr(ord(cur_col) + 2)
error_per_col = chr(ord(cur_col) + 3)
summary_ws['{}{}'.format(
truth_col,
summary_row)] = '=' + summary_cells['truth'][col]
summary_ws['{}{}'.format(
computed_col,
summary_row)] = '=' + summary_cells['computed'][col]
summary_ws['{}{}'.format(
error_col,
summary_row)] = '={truth}{row}-{comp}{row}'.format(
truth=truth_col, comp=computed_col, row=summary_row)
summary_ws['{}{}'.format(
error_per_col,
summary_row)] = '={error}{row}/{truth}{row}'.format(
error=error_col, truth=truth_col, row=summary_row)
cur_col = chr(ord(cur_col) + 4)
summary_row += 1
wb.save(filename=args.output_xlsx)
if __name__ == "__main__":
main()

2977
minitests/timing/picorv32.v Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,258 @@
/*
* PicoSoC - A simple example SoC using PicoRV32
*
* This is a modified PicoSoC example which has removed the requirement
* for an external SPI flash. The PicoRV32 program is stored in ROM implemented
* as a number of case statements. The ROM file is generated using an external
* script.
*
*
* Copyright (C) 2017 Clifford Wolf <clifford@clifford.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
`ifndef PICORV32_REGS
`ifdef PICORV32_V
`error "picosoc.v must be read before picorv32.v!"
`endif
`define PICORV32_REGS picosoc_regs
`endif
module picosoc_noflash (
input clk,
input resetn,
output iomem_valid,
input iomem_ready,
output [ 3:0] iomem_wstrb,
output [31:0] iomem_addr,
output [31:0] iomem_wdata,
input [31:0] iomem_rdata,
input irq_5,
input irq_6,
input irq_7,
output ser_tx,
input ser_rx
);
parameter integer MEM_WORDS = 256;
parameter [31:0] STACKADDR = (4*MEM_WORDS); // end of memory
parameter [31:0] PROGADDR_RESET = 32'h 0010_0000; // 1 MB into flash
reg [31:0] irq;
wire irq_stall = 0;
wire irq_uart = 0;
always @* begin
irq = 0;
irq[3] = irq_stall;
irq[4] = irq_uart;
irq[5] = irq_5;
irq[6] = irq_6;
irq[7] = irq_7;
end
wire mem_valid;
wire mem_instr;
wire mem_ready;
wire [31:0] mem_addr;
wire [31:0] mem_wdata;
wire [3:0] mem_wstrb;
wire [31:0] mem_rdata;
wire progmem_ready;
wire [31:0] progmem_rdata;
reg ram_ready;
wire [31:0] ram_rdata;
assign iomem_valid = mem_valid && (mem_addr[31:24] > 8'h 01);
assign iomem_wstrb = mem_wstrb;
assign iomem_addr = mem_addr;
assign iomem_wdata = mem_wdata;
wire spimemio_cfgreg_sel = mem_valid && (mem_addr == 32'h 0200_0000);
wire simpleuart_reg_div_sel = mem_valid && (mem_addr == 32'h 0200_0004);
wire [31:0] simpleuart_reg_div_do;
wire simpleuart_reg_dat_sel = mem_valid && (mem_addr == 32'h 0200_0008);
wire [31:0] simpleuart_reg_dat_do;
wire simpleuart_reg_dat_wait;
assign mem_ready =
(iomem_valid && iomem_ready) || progmem_ready || ram_ready || spimemio_cfgreg_sel ||
simpleuart_reg_div_sel || (simpleuart_reg_dat_sel && !simpleuart_reg_dat_wait);
assign mem_rdata =
(iomem_valid && iomem_ready) ? iomem_rdata :
progmem_ready ? progmem_rdata :
ram_ready ? ram_rdata :
spimemio_cfgreg_sel ? 32'h0000_0000 : // Mockup, will always read 0
simpleuart_reg_div_sel ? simpleuart_reg_div_do :
simpleuart_reg_dat_sel ? simpleuart_reg_dat_do : 32'h 0000_0000;
`ifdef SIMULATION
wire trace_valid;
wire [35:0] trace_data;
integer trace_file;
`endif
picorv32 #(
.STACKADDR(STACKADDR),
.PROGADDR_RESET(PROGADDR_RESET),
.PROGADDR_IRQ(32'h 0000_0000),
.BARREL_SHIFTER(1),
.COMPRESSED_ISA(1),
.ENABLE_MUL(1),
.ENABLE_DIV(1),
.ENABLE_IRQ(1),
`ifdef SIMULATION
.ENABLE_IRQ_QREGS(0),
.ENABLE_TRACE(1)
`else
.ENABLE_IRQ_QREGS(0)
`endif
) cpu (
.clk (clk ),
.resetn (resetn ),
.mem_valid (mem_valid ),
.mem_instr (mem_instr ),
.mem_ready (mem_ready ),
.mem_addr (mem_addr ),
.mem_wdata (mem_wdata ),
.mem_wstrb (mem_wstrb ),
.mem_rdata (mem_rdata ),
`ifdef SIMULATION
.irq (irq ),
.trace_valid (trace_valid),
.trace_data (trace_data )
`else
.irq (irq )
`endif
);
// This it the program ROM memory for the PicoRV32
progmem progmem (
.clk (clk),
.rstn (resetn),
.valid (mem_valid && mem_addr >= 4*MEM_WORDS && mem_addr < 32'h 0200_0000),
.ready (progmem_ready),
.addr (mem_addr),
.rdata (progmem_rdata)
);
simpleuart simpleuart (
.clk (clk ),
.resetn (resetn ),
.ser_tx (ser_tx ),
.ser_rx (ser_rx ),
.reg_div_we (simpleuart_reg_div_sel ? mem_wstrb : 4'b 0000),
.reg_div_di (mem_wdata),
.reg_div_do (simpleuart_reg_div_do),
.reg_dat_we (simpleuart_reg_dat_sel ? mem_wstrb[0] : 1'b 0),
.reg_dat_re (simpleuart_reg_dat_sel && !mem_wstrb),
.reg_dat_di (mem_wdata),
.reg_dat_do (simpleuart_reg_dat_do),
.reg_dat_wait(simpleuart_reg_dat_wait)
);
always @(posedge clk)
ram_ready <= mem_valid && !mem_ready && mem_addr < 4*MEM_WORDS;
picosoc_mem #(.WORDS(MEM_WORDS)) memory (
.clk(clk),
.wen((mem_valid && !mem_ready && mem_addr < 4*MEM_WORDS) ? mem_wstrb : 4'b0),
.addr(mem_addr[23:2]),
.wdata(mem_wdata),
.rdata(ram_rdata)
);
// Simulation debug
`ifdef SIMULATION
always @(posedge clk)
if (resetn) begin
if ( mem_instr && mem_valid && mem_ready)
$display("Inst rd: [0x%08X] = 0x%08X", mem_addr, mem_rdata);
if (!mem_instr && mem_valid && mem_ready)
$display("Data rd: [0x%08X] = 0x%08X", mem_addr, mem_rdata);
end
// Trace
initial begin
trace_file = $fopen("testbench.trace", "w");
repeat (10) @(posedge clk);
while(1) begin
@(posedge clk)
if (resetn && trace_valid)
$fwrite(trace_file, "%x\n", trace_data);
$fflush(trace_file);
//$display("Trace : %09X", trace_data);
end
end
`endif // SIMULATION
endmodule
// Implementation note:
// Replace the following two modules with wrappers for your SRAM cells.
module picosoc_regs (
input clk, wen,
input [5:0] waddr,
input [5:0] raddr1,
input [5:0] raddr2,
input [31:0] wdata,
output [31:0] rdata1,
output [31:0] rdata2
);
(* ram_style = "distributed" *) reg [31:0] regs [0:31];
always @(posedge clk)
if (wen) regs[waddr[4:0]] <= wdata;
assign rdata1 = regs[raddr1[4:0]];
assign rdata2 = regs[raddr2[4:0]];
endmodule
module picosoc_mem #(
parameter integer WORDS = 256
) (
input clk,
input [3:0] wen,
input [21:0] addr,
input [31:0] wdata,
output reg [31:0] rdata
);
(* ram_style = "distributed" *) reg [31:0] mem [0:WORDS-1];
always @(posedge clk) begin
rdata <= mem[addr];
if (wen[0]) mem[addr][ 7: 0] <= wdata[ 7: 0];
if (wen[1]) mem[addr][15: 8] <= wdata[15: 8];
if (wen[2]) mem[addr][23:16] <= wdata[23:16];
if (wen[3]) mem[addr][31:24] <= wdata[31:24];
end
endmodule

807
minitests/timing/progmem.v Normal file
View File

@ -0,0 +1,807 @@
module progmem
(
// Closk & reset
input wire clk,
input wire rstn,
// PicoRV32 bus interface
input wire valid,
output wire ready,
input wire [31:0] addr,
output wire [31:0] rdata
);
// ============================================================================
localparam MEM_SIZE_BITS = 10; // In 32-bit words
localparam MEM_SIZE = 1 << MEM_SIZE_BITS;
localparam MEM_ADDR_MASK = 32'h0010_0000;
// ============================================================================
wire [MEM_SIZE_BITS-1:0] mem_addr;
reg [31:0] mem_data;
reg [31:0] mem[0:MEM_SIZE];
initial begin
mem['h0000] <= 32'h00000093;
mem['h0001] <= 32'h00000193;
mem['h0002] <= 32'h00000213;
mem['h0003] <= 32'h00000293;
mem['h0004] <= 32'h00000313;
mem['h0005] <= 32'h00000393;
mem['h0006] <= 32'h00000413;
mem['h0007] <= 32'h00000493;
mem['h0008] <= 32'h00000513;
mem['h0009] <= 32'h00000593;
mem['h000A] <= 32'h00000613;
mem['h000B] <= 32'h00000693;
mem['h000C] <= 32'h00000713;
mem['h000D] <= 32'h00000793;
mem['h000E] <= 32'h00000813;
mem['h000F] <= 32'h00000893;
mem['h0010] <= 32'h00000913;
mem['h0011] <= 32'h00000993;
mem['h0012] <= 32'h00000A13;
mem['h0013] <= 32'h00000A93;
mem['h0014] <= 32'h00000B13;
mem['h0015] <= 32'h00000B93;
mem['h0016] <= 32'h00000C13;
mem['h0017] <= 32'h00000C93;
mem['h0018] <= 32'h00000D13;
mem['h0019] <= 32'h00000D93;
mem['h001A] <= 32'h00000E13;
mem['h001B] <= 32'h00000E93;
mem['h001C] <= 32'h00000F13;
mem['h001D] <= 32'h00000F93;
mem['h001E] <= 32'h03000537;
mem['h001F] <= 32'h00100593;
mem['h0020] <= 32'h00B52023;
mem['h0021] <= 32'h00000513;
mem['h0022] <= 32'h00A52023;
mem['h0023] <= 32'h00450513;
mem['h0024] <= 32'hFE254CE3;
mem['h0025] <= 32'h03000537;
mem['h0026] <= 32'h00300593;
mem['h0027] <= 32'h00B52023;
mem['h0028] <= 32'h00001517;
mem['h0029] <= 32'hB4050513;
mem['h002A] <= 32'h00000593;
mem['h002B] <= 32'h00000613;
mem['h002C] <= 32'h00C5DC63;
mem['h002D] <= 32'h00052683;
mem['h002E] <= 32'h00D5A023;
mem['h002F] <= 32'h00450513;
mem['h0030] <= 32'h00458593;
mem['h0031] <= 32'hFEC5C8E3;
mem['h0032] <= 32'h03000537;
mem['h0033] <= 32'h00700593;
mem['h0034] <= 32'h00B52023;
mem['h0035] <= 32'h00000513;
mem['h0036] <= 32'h00000593;
mem['h0037] <= 32'h00B55863;
mem['h0038] <= 32'h00052023;
mem['h0039] <= 32'h00450513;
mem['h003A] <= 32'hFEB54CE3;
mem['h003B] <= 32'h03000537;
mem['h003C] <= 32'h00F00593;
mem['h003D] <= 32'h00B52023;
mem['h003E] <= 32'h015000EF;
mem['h003F] <= 32'h0000006F;
mem['h0040] <= 32'h020002B7;
mem['h0041] <= 32'h12000313;
mem['h0042] <= 32'h00629023;
mem['h0043] <= 32'h000281A3;
mem['h0044] <= 32'h02060863;
mem['h0045] <= 32'h00800F13;
mem['h0046] <= 32'h0FF67393;
mem['h0047] <= 32'h0073DE93;
mem['h0048] <= 32'h01D28023;
mem['h0049] <= 32'h010EEE93;
mem['h004A] <= 32'h01D28023;
mem['h004B] <= 32'h00139393;
mem['h004C] <= 32'h0FF3F393;
mem['h004D] <= 32'hFFFF0F13;
mem['h004E] <= 32'hFE0F12E3;
mem['h004F] <= 32'h00628023;
mem['h0050] <= 32'h04058663;
mem['h0051] <= 32'h00800F13;
mem['h0052] <= 32'h00054383;
mem['h0053] <= 32'h0073DE93;
mem['h0054] <= 32'h01D28023;
mem['h0055] <= 32'h010EEE93;
mem['h0056] <= 32'h01D28023;
mem['h0057] <= 32'h0002CE83;
mem['h0058] <= 32'h002EFE93;
mem['h0059] <= 32'h001EDE93;
mem['h005A] <= 32'h00139393;
mem['h005B] <= 32'h01D3E3B3;
mem['h005C] <= 32'h0FF3F393;
mem['h005D] <= 32'hFFFF0F13;
mem['h005E] <= 32'hFC0F1AE3;
mem['h005F] <= 32'h00750023;
mem['h0060] <= 32'h00150513;
mem['h0061] <= 32'hFFF58593;
mem['h0062] <= 32'hFB9FF06F;
mem['h0063] <= 32'h08000313;
mem['h0064] <= 32'h006281A3;
mem['h0065] <= 32'h00008067;
mem['h0066] <= 32'hFE010113;
mem['h0067] <= 32'h00112E23;
mem['h0068] <= 32'h00812C23;
mem['h0069] <= 32'h02010413;
mem['h006A] <= 32'h00050793;
mem['h006B] <= 32'hFEF407A3;
mem['h006C] <= 32'hFEF44703;
mem['h006D] <= 32'h00A00793;
mem['h006E] <= 32'h00F71663;
mem['h006F] <= 32'h00D00513;
mem['h0070] <= 32'hFD9FF0EF;
mem['h0071] <= 32'h020007B7;
mem['h0072] <= 32'h00878793;
mem['h0073] <= 32'hFEF44703;
mem['h0074] <= 32'h00E7A023;
mem['h0075] <= 32'h00000013;
mem['h0076] <= 32'h01C12083;
mem['h0077] <= 32'h01812403;
mem['h0078] <= 32'h02010113;
mem['h0079] <= 32'h00008067;
mem['h007A] <= 32'hFE010113;
mem['h007B] <= 32'h00112E23;
mem['h007C] <= 32'h00812C23;
mem['h007D] <= 32'h02010413;
mem['h007E] <= 32'hFEA42623;
mem['h007F] <= 32'h01C0006F;
mem['h0080] <= 32'hFEC42783;
mem['h0081] <= 32'h00178713;
mem['h0082] <= 32'hFEE42623;
mem['h0083] <= 32'h0007C783;
mem['h0084] <= 32'h00078513;
mem['h0085] <= 32'hF85FF0EF;
mem['h0086] <= 32'hFEC42783;
mem['h0087] <= 32'h0007C783;
mem['h0088] <= 32'hFE0790E3;
mem['h0089] <= 32'h00000013;
mem['h008A] <= 32'h01C12083;
mem['h008B] <= 32'h01812403;
mem['h008C] <= 32'h02010113;
mem['h008D] <= 32'h00008067;
mem['h008E] <= 32'hFD010113;
mem['h008F] <= 32'h02112623;
mem['h0090] <= 32'h02812423;
mem['h0091] <= 32'h03010413;
mem['h0092] <= 32'hFCA42E23;
mem['h0093] <= 32'hFCB42C23;
mem['h0094] <= 32'h00700793;
mem['h0095] <= 32'hFEF42623;
mem['h0096] <= 32'h06C0006F;
mem['h0097] <= 32'hFEC42783;
mem['h0098] <= 32'h00279793;
mem['h0099] <= 32'hFDC42703;
mem['h009A] <= 32'h00F757B3;
mem['h009B] <= 32'h00F7F713;
mem['h009C] <= 32'h001017B7;
mem['h009D] <= 32'hA8078793;
mem['h009E] <= 32'h00F707B3;
mem['h009F] <= 32'h0007C783;
mem['h00A0] <= 32'hFEF405A3;
mem['h00A1] <= 32'hFEB44703;
mem['h00A2] <= 32'h03000793;
mem['h00A3] <= 32'h00F71863;
mem['h00A4] <= 32'hFEC42703;
mem['h00A5] <= 32'hFD842783;
mem['h00A6] <= 32'h00F75E63;
mem['h00A7] <= 32'hFEB44783;
mem['h00A8] <= 32'h00078513;
mem['h00A9] <= 32'hEF5FF0EF;
mem['h00AA] <= 32'hFEC42783;
mem['h00AB] <= 32'hFCF42C23;
mem['h00AC] <= 32'h0080006F;
mem['h00AD] <= 32'h00000013;
mem['h00AE] <= 32'hFEC42783;
mem['h00AF] <= 32'hFFF78793;
mem['h00B0] <= 32'hFEF42623;
mem['h00B1] <= 32'hFEC42783;
mem['h00B2] <= 32'hF807DAE3;
mem['h00B3] <= 32'h00000013;
mem['h00B4] <= 32'h02C12083;
mem['h00B5] <= 32'h02812403;
mem['h00B6] <= 32'h03010113;
mem['h00B7] <= 32'h00008067;
mem['h00B8] <= 32'hFE010113;
mem['h00B9] <= 32'h00112E23;
mem['h00BA] <= 32'h00812C23;
mem['h00BB] <= 32'h02010413;
mem['h00BC] <= 32'hFEA42623;
mem['h00BD] <= 32'hFEC42703;
mem['h00BE] <= 32'h06300793;
mem['h00BF] <= 32'h00E7FA63;
mem['h00C0] <= 32'h001017B7;
mem['h00C1] <= 32'hA9478513;
mem['h00C2] <= 32'hEE1FF0EF;
mem['h00C3] <= 32'h28C0006F;
mem['h00C4] <= 32'hFEC42703;
mem['h00C5] <= 32'h05900793;
mem['h00C6] <= 32'h00E7FE63;
mem['h00C7] <= 32'h03900513;
mem['h00C8] <= 32'hE79FF0EF;
mem['h00C9] <= 32'hFEC42783;
mem['h00CA] <= 32'hFA678793;
mem['h00CB] <= 32'hFEF42623;
mem['h00CC] <= 32'h1200006F;
mem['h00CD] <= 32'hFEC42703;
mem['h00CE] <= 32'h04F00793;
mem['h00CF] <= 32'h00E7FE63;
mem['h00D0] <= 32'h03800513;
mem['h00D1] <= 32'hE55FF0EF;
mem['h00D2] <= 32'hFEC42783;
mem['h00D3] <= 32'hFB078793;
mem['h00D4] <= 32'hFEF42623;
mem['h00D5] <= 32'h0FC0006F;
mem['h00D6] <= 32'hFEC42703;
mem['h00D7] <= 32'h04500793;
mem['h00D8] <= 32'h00E7FE63;
mem['h00D9] <= 32'h03700513;
mem['h00DA] <= 32'hE31FF0EF;
mem['h00DB] <= 32'hFEC42783;
mem['h00DC] <= 32'hFBA78793;
mem['h00DD] <= 32'hFEF42623;
mem['h00DE] <= 32'h0D80006F;
mem['h00DF] <= 32'hFEC42703;
mem['h00E0] <= 32'h03B00793;
mem['h00E1] <= 32'h00E7FE63;
mem['h00E2] <= 32'h03600513;
mem['h00E3] <= 32'hE0DFF0EF;
mem['h00E4] <= 32'hFEC42783;
mem['h00E5] <= 32'hFC478793;
mem['h00E6] <= 32'hFEF42623;
mem['h00E7] <= 32'h0B40006F;
mem['h00E8] <= 32'hFEC42703;
mem['h00E9] <= 32'h03100793;
mem['h00EA] <= 32'h00E7FE63;
mem['h00EB] <= 32'h03500513;
mem['h00EC] <= 32'hDE9FF0EF;
mem['h00ED] <= 32'hFEC42783;
mem['h00EE] <= 32'hFCE78793;
mem['h00EF] <= 32'hFEF42623;
mem['h00F0] <= 32'h0900006F;
mem['h00F1] <= 32'hFEC42703;
mem['h00F2] <= 32'h02700793;
mem['h00F3] <= 32'h00E7FE63;
mem['h00F4] <= 32'h03400513;
mem['h00F5] <= 32'hDC5FF0EF;
mem['h00F6] <= 32'hFEC42783;
mem['h00F7] <= 32'hFD878793;
mem['h00F8] <= 32'hFEF42623;
mem['h00F9] <= 32'h06C0006F;
mem['h00FA] <= 32'hFEC42703;
mem['h00FB] <= 32'h01D00793;
mem['h00FC] <= 32'h00E7FE63;
mem['h00FD] <= 32'h03300513;
mem['h00FE] <= 32'hDA1FF0EF;
mem['h00FF] <= 32'hFEC42783;
mem['h0100] <= 32'hFE278793;
mem['h0101] <= 32'hFEF42623;
mem['h0102] <= 32'h0480006F;
mem['h0103] <= 32'hFEC42703;
mem['h0104] <= 32'h01300793;
mem['h0105] <= 32'h00E7FE63;
mem['h0106] <= 32'h03200513;
mem['h0107] <= 32'hD7DFF0EF;
mem['h0108] <= 32'hFEC42783;
mem['h0109] <= 32'hFEC78793;
mem['h010A] <= 32'hFEF42623;
mem['h010B] <= 32'h0240006F;
mem['h010C] <= 32'hFEC42703;
mem['h010D] <= 32'h00900793;
mem['h010E] <= 32'h00E7FC63;
mem['h010F] <= 32'h03100513;
mem['h0110] <= 32'hD59FF0EF;
mem['h0111] <= 32'hFEC42783;
mem['h0112] <= 32'hFF678793;
mem['h0113] <= 32'hFEF42623;
mem['h0114] <= 32'hFEC42703;
mem['h0115] <= 32'h00800793;
mem['h0116] <= 32'h00E7FE63;
mem['h0117] <= 32'h03900513;
mem['h0118] <= 32'hD39FF0EF;
mem['h0119] <= 32'hFEC42783;
mem['h011A] <= 32'hFF778793;
mem['h011B] <= 32'hFEF42623;
mem['h011C] <= 32'h1280006F;
mem['h011D] <= 32'hFEC42703;
mem['h011E] <= 32'h00700793;
mem['h011F] <= 32'h00E7FE63;
mem['h0120] <= 32'h03800513;
mem['h0121] <= 32'hD15FF0EF;
mem['h0122] <= 32'hFEC42783;
mem['h0123] <= 32'hFF878793;
mem['h0124] <= 32'hFEF42623;
mem['h0125] <= 32'h1040006F;
mem['h0126] <= 32'hFEC42703;
mem['h0127] <= 32'h00600793;
mem['h0128] <= 32'h00E7FE63;
mem['h0129] <= 32'h03700513;
mem['h012A] <= 32'hCF1FF0EF;
mem['h012B] <= 32'hFEC42783;
mem['h012C] <= 32'hFF978793;
mem['h012D] <= 32'hFEF42623;
mem['h012E] <= 32'h0E00006F;
mem['h012F] <= 32'hFEC42703;
mem['h0130] <= 32'h00500793;
mem['h0131] <= 32'h00E7FE63;
mem['h0132] <= 32'h03600513;
mem['h0133] <= 32'hCCDFF0EF;
mem['h0134] <= 32'hFEC42783;
mem['h0135] <= 32'hFFA78793;
mem['h0136] <= 32'hFEF42623;
mem['h0137] <= 32'h0BC0006F;
mem['h0138] <= 32'hFEC42703;
mem['h0139] <= 32'h00400793;
mem['h013A] <= 32'h00E7FE63;
mem['h013B] <= 32'h03500513;
mem['h013C] <= 32'hCA9FF0EF;
mem['h013D] <= 32'hFEC42783;
mem['h013E] <= 32'hFFB78793;
mem['h013F] <= 32'hFEF42623;
mem['h0140] <= 32'h0980006F;
mem['h0141] <= 32'hFEC42703;
mem['h0142] <= 32'h00300793;
mem['h0143] <= 32'h00E7FE63;
mem['h0144] <= 32'h03400513;
mem['h0145] <= 32'hC85FF0EF;
mem['h0146] <= 32'hFEC42783;
mem['h0147] <= 32'hFFC78793;
mem['h0148] <= 32'hFEF42623;
mem['h0149] <= 32'h0740006F;
mem['h014A] <= 32'hFEC42703;
mem['h014B] <= 32'h00200793;
mem['h014C] <= 32'h00E7FE63;
mem['h014D] <= 32'h03300513;
mem['h014E] <= 32'hC61FF0EF;
mem['h014F] <= 32'hFEC42783;
mem['h0150] <= 32'hFFD78793;
mem['h0151] <= 32'hFEF42623;
mem['h0152] <= 32'h0500006F;
mem['h0153] <= 32'hFEC42703;
mem['h0154] <= 32'h00100793;
mem['h0155] <= 32'h00E7FE63;
mem['h0156] <= 32'h03200513;
mem['h0157] <= 32'hC3DFF0EF;
mem['h0158] <= 32'hFEC42783;
mem['h0159] <= 32'hFFE78793;
mem['h015A] <= 32'hFEF42623;
mem['h015B] <= 32'h02C0006F;
mem['h015C] <= 32'hFEC42783;
mem['h015D] <= 32'h00078E63;
mem['h015E] <= 32'h03100513;
mem['h015F] <= 32'hC1DFF0EF;
mem['h0160] <= 32'hFEC42783;
mem['h0161] <= 32'hFFF78793;
mem['h0162] <= 32'hFEF42623;
mem['h0163] <= 32'h00C0006F;
mem['h0164] <= 32'h03000513;
mem['h0165] <= 32'hC05FF0EF;
mem['h0166] <= 32'h01C12083;
mem['h0167] <= 32'h01812403;
mem['h0168] <= 32'h02010113;
mem['h0169] <= 32'h00008067;
mem['h016A] <= 32'hFD010113;
mem['h016B] <= 32'h02112623;
mem['h016C] <= 32'h02812423;
mem['h016D] <= 32'h03010413;
mem['h016E] <= 32'hFCA42E23;
mem['h016F] <= 32'hFFF00793;
mem['h0170] <= 32'hFEF42623;
mem['h0171] <= 32'hC00027F3;
mem['h0172] <= 32'hFEF42423;
mem['h0173] <= 32'h030007B7;
mem['h0174] <= 32'hFFF00713;
mem['h0175] <= 32'h00E7A023;
mem['h0176] <= 32'hFDC42783;
mem['h0177] <= 32'h08078A63;
mem['h0178] <= 32'hFDC42503;
mem['h0179] <= 32'hC05FF0EF;
mem['h017A] <= 32'h0880006F;
mem['h017B] <= 32'hC00027F3;
mem['h017C] <= 32'hFEF42223;
mem['h017D] <= 32'hFE442703;
mem['h017E] <= 32'hFE842783;
mem['h017F] <= 32'h40F707B3;
mem['h0180] <= 32'hFEF42023;
mem['h0181] <= 32'hFE042703;
mem['h0182] <= 32'h00B727B7;
mem['h0183] <= 32'hB0078793;
mem['h0184] <= 32'h04E7F863;
mem['h0185] <= 32'hFDC42783;
mem['h0186] <= 32'h00078663;
mem['h0187] <= 32'hFDC42503;
mem['h0188] <= 32'hBC9FF0EF;
mem['h0189] <= 32'hFE442783;
mem['h018A] <= 32'hFEF42423;
mem['h018B] <= 32'h030007B7;
mem['h018C] <= 32'h0007A783;
mem['h018D] <= 32'h00179713;
mem['h018E] <= 32'h030007B7;
mem['h018F] <= 32'h0007A783;
mem['h0190] <= 32'h0017D793;
mem['h0191] <= 32'h0017F793;
mem['h0192] <= 32'h0017B793;
mem['h0193] <= 32'h0FF7F793;
mem['h0194] <= 32'h00078693;
mem['h0195] <= 32'h030007B7;
mem['h0196] <= 32'h00D76733;
mem['h0197] <= 32'h00E7A023;
mem['h0198] <= 32'h020007B7;
mem['h0199] <= 32'h00878793;
mem['h019A] <= 32'h0007A783;
mem['h019B] <= 32'hFEF42623;
mem['h019C] <= 32'hFEC42703;
mem['h019D] <= 32'hFFF00793;
mem['h019E] <= 32'hF6F70AE3;
mem['h019F] <= 32'h030007B7;
mem['h01A0] <= 32'h0007A023;
mem['h01A1] <= 32'hFEC42783;
mem['h01A2] <= 32'h0FF7F793;
mem['h01A3] <= 32'h00078513;
mem['h01A4] <= 32'h02C12083;
mem['h01A5] <= 32'h02812403;
mem['h01A6] <= 32'h03010113;
mem['h01A7] <= 32'h00008067;
mem['h01A8] <= 32'hFF010113;
mem['h01A9] <= 32'h00112623;
mem['h01AA] <= 32'h00812423;
mem['h01AB] <= 32'h01010413;
mem['h01AC] <= 32'h00000513;
mem['h01AD] <= 32'hEF5FF0EF;
mem['h01AE] <= 32'h00050793;
mem['h01AF] <= 32'h00078513;
mem['h01B0] <= 32'h00C12083;
mem['h01B1] <= 32'h00812403;
mem['h01B2] <= 32'h01010113;
mem['h01B3] <= 32'h00008067;
mem['h01B4] <= 32'hEB010113;
mem['h01B5] <= 32'h14112623;
mem['h01B6] <= 32'h14812423;
mem['h01B7] <= 32'h15010413;
mem['h01B8] <= 32'h00050793;
mem['h01B9] <= 32'hEAB42C23;
mem['h01BA] <= 32'hEAF40FA3;
mem['h01BB] <= 32'hEC040793;
mem['h01BC] <= 32'hFCF42A23;
mem['h01BD] <= 32'h12B9B7B7;
mem['h01BE] <= 32'h0A178793;
mem['h01BF] <= 32'hFEF42623;
mem['h01C0] <= 32'hC00027F3;
mem['h01C1] <= 32'hFCF42823;
mem['h01C2] <= 32'hC02027F3;
mem['h01C3] <= 32'hFCF42623;
mem['h01C4] <= 32'hFE042423;
mem['h01C5] <= 32'h1200006F;
mem['h01C6] <= 32'hFE042223;
mem['h01C7] <= 32'h0640006F;
mem['h01C8] <= 32'hFEC42783;
mem['h01C9] <= 32'h00D79793;
mem['h01CA] <= 32'hFEC42703;
mem['h01CB] <= 32'h00F747B3;
mem['h01CC] <= 32'hFEF42623;
mem['h01CD] <= 32'hFEC42783;
mem['h01CE] <= 32'h0117D793;
mem['h01CF] <= 32'hFEC42703;
mem['h01D0] <= 32'h00F747B3;
mem['h01D1] <= 32'hFEF42623;
mem['h01D2] <= 32'hFEC42783;
mem['h01D3] <= 32'h00579793;
mem['h01D4] <= 32'hFEC42703;
mem['h01D5] <= 32'h00F747B3;
mem['h01D6] <= 32'hFEF42623;
mem['h01D7] <= 32'hFEC42783;
mem['h01D8] <= 32'h0FF7F713;
mem['h01D9] <= 32'hFE442783;
mem['h01DA] <= 32'hFF040693;
mem['h01DB] <= 32'h00F687B3;
mem['h01DC] <= 32'hECE78823;
mem['h01DD] <= 32'hFE442783;
mem['h01DE] <= 32'h00178793;
mem['h01DF] <= 32'hFEF42223;
mem['h01E0] <= 32'hFE442703;
mem['h01E1] <= 32'h0FF00793;
mem['h01E2] <= 32'hF8E7DCE3;
mem['h01E3] <= 32'hFE042023;
mem['h01E4] <= 32'hFC042E23;
mem['h01E5] <= 32'h0440006F;
mem['h01E6] <= 32'hFE042783;
mem['h01E7] <= 32'hFF040713;
mem['h01E8] <= 32'h00F707B3;
mem['h01E9] <= 32'hED07C783;
mem['h01EA] <= 32'h02078263;
mem['h01EB] <= 32'hFDC42783;
mem['h01EC] <= 32'h00178713;
mem['h01ED] <= 32'hFCE42E23;
mem['h01EE] <= 32'hFE042703;
mem['h01EF] <= 32'h0FF77713;
mem['h01F0] <= 32'hFF040693;
mem['h01F1] <= 32'h00F687B3;
mem['h01F2] <= 32'hECE78823;
mem['h01F3] <= 32'hFE042783;
mem['h01F4] <= 32'h00178793;
mem['h01F5] <= 32'hFEF42023;
mem['h01F6] <= 32'hFE042703;
mem['h01F7] <= 32'h0FF00793;
mem['h01F8] <= 32'hFAE7DCE3;
mem['h01F9] <= 32'hFC042C23;
mem['h01FA] <= 32'hFC042023;
mem['h01FB] <= 32'h0300006F;
mem['h01FC] <= 32'hFD842783;
mem['h01FD] <= 32'h00279793;
mem['h01FE] <= 32'hFD442703;
mem['h01FF] <= 32'h00F707B3;
mem['h0200] <= 32'h0007A783;
mem['h0201] <= 32'hFEC42703;
mem['h0202] <= 32'h00F747B3;
mem['h0203] <= 32'hFEF42623;
mem['h0204] <= 32'hFD842783;
mem['h0205] <= 32'h00178793;
mem['h0206] <= 32'hFCF42C23;
mem['h0207] <= 32'hFD842703;
mem['h0208] <= 32'h03F00793;
mem['h0209] <= 32'hFCE7D6E3;
mem['h020A] <= 32'hFE842783;
mem['h020B] <= 32'h00178793;
mem['h020C] <= 32'hFEF42423;
mem['h020D] <= 32'hFE842703;
mem['h020E] <= 32'h01300793;
mem['h020F] <= 32'hECE7DEE3;
mem['h0210] <= 32'hC00027F3;
mem['h0211] <= 32'hFCF42423;
mem['h0212] <= 32'hC02027F3;
mem['h0213] <= 32'hFCF42223;
mem['h0214] <= 32'hEBF44783;
mem['h0215] <= 32'h06078E63;
mem['h0216] <= 32'h001017B7;
mem['h0217] <= 32'hA9C78513;
mem['h0218] <= 32'h989FF0EF;
mem['h0219] <= 32'hFC842703;
mem['h021A] <= 32'hFD042783;
mem['h021B] <= 32'h40F707B3;
mem['h021C] <= 32'h00800593;
mem['h021D] <= 32'h00078513;
mem['h021E] <= 32'h9C1FF0EF;
mem['h021F] <= 32'h00A00513;
mem['h0220] <= 32'h919FF0EF;
mem['h0221] <= 32'h001017B7;
mem['h0222] <= 32'hAA878513;
mem['h0223] <= 32'h95DFF0EF;
mem['h0224] <= 32'hFC442703;
mem['h0225] <= 32'hFCC42783;
mem['h0226] <= 32'h40F707B3;
mem['h0227] <= 32'h00800593;
mem['h0228] <= 32'h00078513;
mem['h0229] <= 32'h995FF0EF;
mem['h022A] <= 32'h00A00513;
mem['h022B] <= 32'h8EDFF0EF;
mem['h022C] <= 32'h001017B7;
mem['h022D] <= 32'hAB478513;
mem['h022E] <= 32'h931FF0EF;
mem['h022F] <= 32'h00800593;
mem['h0230] <= 32'hFEC42503;
mem['h0231] <= 32'h975FF0EF;
mem['h0232] <= 32'h00A00513;
mem['h0233] <= 32'h8CDFF0EF;
mem['h0234] <= 32'hEB842783;
mem['h0235] <= 32'h00078C63;
mem['h0236] <= 32'hFC442703;
mem['h0237] <= 32'hFCC42783;
mem['h0238] <= 32'h40F70733;
mem['h0239] <= 32'hEB842783;
mem['h023A] <= 32'h00E7A023;
mem['h023B] <= 32'hFC842703;
mem['h023C] <= 32'hFD042783;
mem['h023D] <= 32'h40F707B3;
mem['h023E] <= 32'h00078513;
mem['h023F] <= 32'h14C12083;
mem['h0240] <= 32'h14812403;
mem['h0241] <= 32'h15010113;
mem['h0242] <= 32'h00008067;
mem['h0243] <= 32'hFE010113;
mem['h0244] <= 32'h00112E23;
mem['h0245] <= 32'h00812C23;
mem['h0246] <= 32'h02010413;
mem['h0247] <= 32'h030007B7;
mem['h0248] <= 32'h01F00713;
mem['h0249] <= 32'h00E7A023;
mem['h024A] <= 32'h020007B7;
mem['h024B] <= 32'h00478793;
mem['h024C] <= 32'h0D900713;
mem['h024D] <= 32'h00E7A023;
mem['h024E] <= 32'h001017B7;
mem['h024F] <= 32'hAC078513;
mem['h0250] <= 32'h8A9FF0EF;
mem['h0251] <= 32'h030007B7;
mem['h0252] <= 32'h03F00713;
mem['h0253] <= 32'h00E7A023;
mem['h0254] <= 32'h030007B7;
mem['h0255] <= 32'h07F00713;
mem['h0256] <= 32'h00E7A023;
mem['h0257] <= 32'h00000013;
mem['h0258] <= 32'h001017B7;
mem['h0259] <= 32'hACC78513;
mem['h025A] <= 32'hC41FF0EF;
mem['h025B] <= 32'h00050793;
mem['h025C] <= 32'h00078713;
mem['h025D] <= 32'h00D00793;
mem['h025E] <= 32'hFEF714E3;
mem['h025F] <= 32'h001017B7;
mem['h0260] <= 32'hAE878513;
mem['h0261] <= 32'h865FF0EF;
mem['h0262] <= 32'h001017B7;
mem['h0263] <= 32'hAEC78513;
mem['h0264] <= 32'h859FF0EF;
mem['h0265] <= 32'h001017B7;
mem['h0266] <= 32'hB1478513;
mem['h0267] <= 32'h84DFF0EF;
mem['h0268] <= 32'h001017B7;
mem['h0269] <= 32'hB3C78513;
mem['h026A] <= 32'h841FF0EF;
mem['h026B] <= 32'h001017B7;
mem['h026C] <= 32'hB6078513;
mem['h026D] <= 32'h835FF0EF;
mem['h026E] <= 32'h001017B7;
mem['h026F] <= 32'hB8878513;
mem['h0270] <= 32'h829FF0EF;
mem['h0271] <= 32'h001017B7;
mem['h0272] <= 32'hAE878513;
mem['h0273] <= 32'h81DFF0EF;
mem['h0274] <= 32'h001017B7;
mem['h0275] <= 32'hAE878513;
mem['h0276] <= 32'h811FF0EF;
mem['h0277] <= 32'h001017B7;
mem['h0278] <= 32'hBB078513;
mem['h0279] <= 32'h805FF0EF;
mem['h027A] <= 32'h001017B7;
mem['h027B] <= 32'hAE878513;
mem['h027C] <= 32'hFF8FF0EF;
mem['h027D] <= 32'h00A00793;
mem['h027E] <= 32'hFEF42623;
mem['h027F] <= 32'h0780006F;
mem['h0280] <= 32'h001017B7;
mem['h0281] <= 32'hBD478513;
mem['h0282] <= 32'hFE0FF0EF;
mem['h0283] <= 32'hC95FF0EF;
mem['h0284] <= 32'h00050793;
mem['h0285] <= 32'hFEF405A3;
mem['h0286] <= 32'hFEB44703;
mem['h0287] <= 32'h02000793;
mem['h0288] <= 32'h00E7FE63;
mem['h0289] <= 32'hFEB44703;
mem['h028A] <= 32'h07E00793;
mem['h028B] <= 32'h00E7E863;
mem['h028C] <= 32'hFEB44783;
mem['h028D] <= 32'h00078513;
mem['h028E] <= 32'hF60FF0EF;
mem['h028F] <= 32'h001017B7;
mem['h0290] <= 32'hAE878513;
mem['h0291] <= 32'hFA4FF0EF;
mem['h0292] <= 32'hFEB44703;
mem['h0293] <= 32'h03900793;
mem['h0294] <= 32'h00F71C63;
mem['h0295] <= 32'h00000593;
mem['h0296] <= 32'h00100513;
mem['h0297] <= 32'hC75FF0EF;
mem['h0298] <= 32'h00000013;
mem['h0299] <= 32'h0180006F;
mem['h029A] <= 32'hFEC42783;
mem['h029B] <= 32'hFFF78793;
mem['h029C] <= 32'hFEF42623;
mem['h029D] <= 32'hFEC42783;
mem['h029E] <= 32'hF8F044E3;
mem['h029F] <= 32'hF49FF06F;
mem['h02A0] <= 32'h33323130;
mem['h02A1] <= 32'h37363534;
mem['h02A2] <= 32'h62613938;
mem['h02A3] <= 32'h66656463;
mem['h02A4] <= 32'h00000000;
mem['h02A5] <= 32'h30313D3E;
mem['h02A6] <= 32'h00000030;
mem['h02A7] <= 32'h6C637943;
mem['h02A8] <= 32'h203A7365;
mem['h02A9] <= 32'h00007830;
mem['h02AA] <= 32'h74736E49;
mem['h02AB] <= 32'h203A736E;
mem['h02AC] <= 32'h00007830;
mem['h02AD] <= 32'h736B6843;
mem['h02AE] <= 32'h203A6D75;
mem['h02AF] <= 32'h00007830;
mem['h02B0] <= 32'h746F6F42;
mem['h02B1] <= 32'h2E676E69;
mem['h02B2] <= 32'h00000A2E;
mem['h02B3] <= 32'h73657250;
mem['h02B4] <= 32'h4E452073;
mem['h02B5] <= 32'h20524554;
mem['h02B6] <= 32'h63206F74;
mem['h02B7] <= 32'h69746E6F;
mem['h02B8] <= 32'h2E65756E;
mem['h02B9] <= 32'h00000A2E;
mem['h02BA] <= 32'h0000000A;
mem['h02BB] <= 32'h5F5F2020;
mem['h02BC] <= 32'h20205F5F;
mem['h02BD] <= 32'h2020205F;
mem['h02BE] <= 32'h20202020;
mem['h02BF] <= 32'h5F202020;
mem['h02C0] <= 32'h205F5F5F;
mem['h02C1] <= 32'h20202020;
mem['h02C2] <= 32'h20202020;
mem['h02C3] <= 32'h5F5F5F5F;
mem['h02C4] <= 32'h0000000A;
mem['h02C5] <= 32'h20207C20;
mem['h02C6] <= 32'h285C205F;
mem['h02C7] <= 32'h5F20295F;
mem['h02C8] <= 32'h5F205F5F;
mem['h02C9] <= 32'h202F5F5F;
mem['h02CA] <= 32'h7C5F5F5F;
mem['h02CB] <= 32'h5F5F2020;
mem['h02CC] <= 32'h2F20205F;
mem['h02CD] <= 32'h5F5F5F20;
mem['h02CE] <= 32'h00000A7C;
mem['h02CF] <= 32'h7C207C20;
mem['h02D0] <= 32'h7C20295F;
mem['h02D1] <= 32'h202F7C20;
mem['h02D2] <= 32'h202F5F5F;
mem['h02D3] <= 32'h5F5C205F;
mem['h02D4] <= 32'h5C205F5F;
mem['h02D5] <= 32'h5F202F20;
mem['h02D6] <= 32'h207C5C20;
mem['h02D7] <= 32'h00000A7C;
mem['h02D8] <= 32'h20207C20;
mem['h02D9] <= 32'h7C2F5F5F;
mem['h02DA] <= 32'h28207C20;
mem['h02DB] <= 32'h28207C5F;
mem['h02DC] <= 32'h7C20295F;
mem['h02DD] <= 32'h20295F5F;
mem['h02DE] <= 32'h5F28207C;
mem['h02DF] <= 32'h207C2029;
mem['h02E0] <= 32'h5F5F5F7C;
mem['h02E1] <= 32'h0000000A;
mem['h02E2] <= 32'h7C5F7C20;
mem['h02E3] <= 32'h7C202020;
mem['h02E4] <= 32'h5F5C7C5F;
mem['h02E5] <= 32'h5F5C5F5F;
mem['h02E6] <= 32'h5F2F5F5F;
mem['h02E7] <= 32'h2F5F5F5F;
mem['h02E8] <= 32'h5F5F5C20;
mem['h02E9] <= 32'h5C202F5F;
mem['h02EA] <= 32'h5F5F5F5F;
mem['h02EB] <= 32'h00000A7C;
mem['h02EC] <= 32'h5B202020;
mem['h02ED] <= 32'h52205D39;
mem['h02EE] <= 32'h73206E75;
mem['h02EF] <= 32'h6C706D69;
mem['h02F0] <= 32'h69747369;
mem['h02F1] <= 32'h65622063;
mem['h02F2] <= 32'h6D68636E;
mem['h02F3] <= 32'h0A6B7261;
mem['h02F4] <= 32'h00000000;
mem['h02F5] <= 32'h6D6D6F43;
mem['h02F6] <= 32'h3E646E61;
mem['h02F7] <= 32'h00000020;
end
always @(posedge clk)
mem_data <= mem[mem_addr];
// ============================================================================
reg o_ready;
always @(posedge clk or negedge rstn)
if (!rstn) o_ready <= 1'd0;
else o_ready <= valid && ((addr & MEM_ADDR_MASK) != 0);
// Output connectins
assign ready = o_ready;
assign rdata = mem_data;
assign mem_addr = addr[MEM_SIZE_BITS+1:2];
endmodule

131
minitests/timing/runme.tcl Normal file
View File

@ -0,0 +1,131 @@
proc write_timing_info {filename} {
set fp [open $filename w]
puts $fp "\["
set nets [get_nets]
foreach net $nets {
if { $net == "<const0>" || $net == "<const1>" } {
continue
}
if { [get_property ROUTE_STATUS [get_nets $net]] == "INTRASITE" } {
continue
}
if { [get_property ROUTE_STATUS [get_nets $net]] == "NOLOADS" } {
continue
}
puts $fp "{"
puts $fp "\"net\":\"$net\","
set route [get_property ROUTE $net]
puts $fp "\"route\":\"$route\","
set pips [get_pips -of_objects $net]
puts $fp "\"pips\":\["
foreach pip $pips {
puts $fp "{"
puts $fp "\"name\":\"$pip\","
puts $fp "\"src_wire\":\"[get_wires -uphill -of_objects $pip]\","
puts $fp "\"dst_wire\":\"[get_wires -downhill -of_objects $pip]\","
puts $fp "\"speed_index\":\"[get_property SPEED_INDEX $pip]\","
puts $fp "\"is_directional\":\"[get_property IS_DIRECTIONAL $pip]\","
puts $fp "},"
}
puts $fp "\],"
puts $fp "\"nodes\":\["
set nodes [get_nodes -of_objects $net]
foreach node $nodes {
puts $fp "{"
puts $fp "\"name\":\"$node\","
puts $fp "\"cost_code\":\"[get_property COST_CODE $node]\","
puts $fp "\"cost_code_name\":\"[get_property COST_CODE_NAME $node]\","
puts $fp "\"speed_class\":\"[get_property SPEED_CLASS $node]\","
puts $fp "\"wires\":\["
set wires [get_wires -of_objects $node]
foreach wire $wires {
puts $fp "{"
puts $fp "\"name\":\"$wire\","
puts $fp "\"cost_code\":\"[get_property COST_CODE $wire]\","
puts $fp "\"speed_index\":\"[get_property SPEED_INDEX $wire]\","
puts $fp "},"
}
puts $fp "\],"
puts $fp "},"
}
puts $fp "\],"
set opin [get_pins -leaf -of_objects [get_nets $net] -filter {DIRECTION == OUT}]
puts $fp "\"opin\": {"
puts $fp "\"name\":\"$opin\","
set opin_site_pin [get_site_pins -of_objects $opin]
puts $fp "\"site_pin\":\"$opin_site_pin\","
puts $fp "\"site_pin_speed_index\":\"[get_property SPEED_INDEX $opin_site_pin]\","
puts $fp "\"node\":\"[get_nodes -of_objects $opin_site_pin]\","
puts $fp "\"wire\":\"[get_wires -of_objects [get_nodes -of_objects $opin_site_pin]]\","
puts $fp "},"
set ipins [get_pins -of_objects [get_nets $net] -filter {DIRECTION == IN} -leaf]
puts $fp "\"ipins\":\["
foreach ipin $ipins {
puts $fp "{"
set delay [get_net_delays -interconnect_only -of_objects $net -to $ipin]
puts $fp "\"name\":\"$ipin\","
puts $fp "\"ic_delays\":{"
foreach prop {"FAST_MAX" "FAST_MIN" "SLOW_MAX" "SLOW_MIN"} {
puts $fp "\"$prop\":\"[get_property $prop $delay]\","
}
puts $fp "},"
set ipin_site_pin [get_site_pin -of_objects $ipin]
puts $fp "\"site_pin\":\"$ipin_site_pin\","
puts $fp "\"site_pin_speed_index\":\"[get_property SPEED_INDEX $ipin_site_pin]\","
puts $fp "\"node\":\"[get_nodes -of_objects $ipin_site_pin]\","
puts $fp "\"wire\":\"[get_wires -of_objects [get_nodes -of_objects $ipin_site_pin]]\","
puts $fp "},"
}
puts $fp "\],"
puts $fp "},"
}
puts $fp "\]"
close $fp
}
proc create_design {design_name sig_mask verilogs} {
create_project -part $::env(XRAY_PART) -force design_$design_name \
design_$design_name
foreach src $verilogs {
read_verilog $src
}
synth_design -verilog_define SIG_MASK=$sig_mask -top top
create_clock -period 10.000 -name clk -waveform {0.000 5.000} [get_ports clk]
set_property -dict "PACKAGE_PIN W5 IOSTANDARD LVCMOS33" [get_ports clk]
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_01) IOSTANDARD LVCMOS33" [get_ports stb]
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_02) IOSTANDARD LVCMOS33" [get_ports di]
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_03) IOSTANDARD LVCMOS33" [get_ports do]
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
if { $design_name == "fanout_ex_0" } {
set_property FIXED_ROUTE "{ CLBLL_LL_D CLBLL_LL_DMUX }" [get_nets the_net]
}
place_design
route_design
write_checkpoint -force design_$design_name.dcp
write_bitstream -force design_$design_name.bit
save_project_as -force design_$design_name.xpr
}
proc run_timing {design_name sig_mask verilogs} {
set name ${design_name}_${sig_mask}
create_design $name $sig_mask $verilogs
write_timing_info timing_$name.json5
}
run_timing $::env(DESIGN_NAME) $::env(ITER) $::env(VERILOGS)

View File

@ -0,0 +1,137 @@
/*
* PicoSoC - A simple example SoC using PicoRV32
*
* Copyright (C) 2017 Clifford Wolf <clifford@clifford.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
module simpleuart (
input clk,
input resetn,
output ser_tx,
input ser_rx,
input [3:0] reg_div_we,
input [31:0] reg_div_di,
output [31:0] reg_div_do,
input reg_dat_we,
input reg_dat_re,
input [31:0] reg_dat_di,
output [31:0] reg_dat_do,
output reg_dat_wait
);
reg [31:0] cfg_divider;
reg [3:0] recv_state;
reg [31:0] recv_divcnt;
reg [7:0] recv_pattern;
reg [7:0] recv_buf_data;
reg recv_buf_valid;
reg [9:0] send_pattern;
reg [3:0] send_bitcnt;
reg [31:0] send_divcnt;
reg send_dummy;
assign reg_div_do = cfg_divider;
assign reg_dat_wait = reg_dat_we && (send_bitcnt || send_dummy);
assign reg_dat_do = recv_buf_valid ? recv_buf_data : ~0;
always @(posedge clk) begin
if (!resetn) begin
cfg_divider <= 1;
end else begin
if (reg_div_we[0]) cfg_divider[ 7: 0] <= reg_div_di[ 7: 0];
if (reg_div_we[1]) cfg_divider[15: 8] <= reg_div_di[15: 8];
if (reg_div_we[2]) cfg_divider[23:16] <= reg_div_di[23:16];
if (reg_div_we[3]) cfg_divider[31:24] <= reg_div_di[31:24];
end
end
always @(posedge clk) begin
if (!resetn) begin
recv_state <= 0;
recv_divcnt <= 0;
recv_pattern <= 0;
recv_buf_data <= 0;
recv_buf_valid <= 0;
end else begin
recv_divcnt <= recv_divcnt + 1;
if (reg_dat_re)
recv_buf_valid <= 0;
case (recv_state)
0: begin
if (!ser_rx)
recv_state <= 1;
recv_divcnt <= 0;
end
1: begin
if (2*recv_divcnt > cfg_divider) begin
recv_state <= 2;
recv_divcnt <= 0;
end
end
10: begin
if (recv_divcnt > cfg_divider) begin
recv_buf_data <= recv_pattern;
recv_buf_valid <= 1;
recv_state <= 0;
end
end
default: begin
if (recv_divcnt > cfg_divider) begin
recv_pattern <= {ser_rx, recv_pattern[7:1]};
recv_state <= recv_state + 1;
recv_divcnt <= 0;
end
end
endcase
end
end
assign ser_tx = send_pattern[0];
always @(posedge clk) begin
if (reg_div_we)
send_dummy <= 1;
send_divcnt <= send_divcnt + 1;
if (!resetn) begin
send_pattern <= ~0;
send_bitcnt <= 0;
send_divcnt <= 0;
send_dummy <= 1;
end else begin
if (send_dummy && !send_bitcnt) begin
send_pattern <= ~0;
send_bitcnt <= 15;
send_divcnt <= 0;
send_dummy <= 0;
end else
if (reg_dat_we && !send_bitcnt) begin
send_pattern <= {1'b1, reg_dat_di[7:0], 1'b0};
send_bitcnt <= 10;
send_divcnt <= 0;
end else
if (send_divcnt > cfg_divider && send_bitcnt) begin
send_pattern <= {1'b1, send_pattern[9:1]};
send_bitcnt <= send_bitcnt - 1;
send_divcnt <= 0;
end
end
end
endmodule

View File

@ -0,0 +1,38 @@
module top(input clk, stb, di, output do);
wire [5:0] I;
wire LUT_O;
wire FF_Q;
localparam SIG_MASK = `SIG_MASK;
genvar i;
generate for(i = 0; i < 6; i = i + 1) begin : loop
if(((1 << i) & SIG_MASK) != 0) begin
assign I[i] = FF_Q;
end else begin
assign I[i] = 1;
end
end endgenerate
(* LOC="SLICE_X37Y74", BEL="A6LUT", KEEP, DONT_TOUCH *)
LUT6 lut(
.I0(I[0]),
.I1(I[1]),
.I2(I[2]),
.I3(I[3]),
.I4(I[4]),
.I5(I[5]),
.O(LUT_O)
);
(* LOC="SLICE_X37Y74", BEL="AFF", KEEP, DONT_TOUCH *)
FDRE ff(
.C(clk),
.R(0),
.CE(1),
.D(LUT_O),
.Q(FF_Q)
);
endmodule

View File

@ -0,0 +1,38 @@
module top(input clk, stb, di, output do);
wire [5:0] I;
wire LUT_O;
wire FF_Q;
localparam SIG_MASK = `SIG_MASK;
genvar i;
generate for(i = 0; i < 6; i = i + 1) begin : loop
if(((1 << i) & SIG_MASK) != 0) begin
assign I[i] = FF_Q;
end else begin
assign I[i] = 1;
end
end endgenerate
(* LOC="SLICE_X37Y74", BEL="B6LUT", KEEP, DONT_TOUCH *)
LUT6 lut(
.I0(I[0]),
.I1(I[1]),
.I2(I[2]),
.I3(I[3]),
.I4(I[4]),
.I5(I[5]),
.O(LUT_O)
);
(* LOC="SLICE_X37Y74", BEL="BFF", KEEP, DONT_TOUCH *)
FDRE ff(
.C(clk),
.R(0),
.CE(1),
.D(LUT_O),
.Q(FF_Q)
);
endmodule

View File

@ -0,0 +1,38 @@
module top(input clk, stb, di, output do);
wire [5:0] I;
wire LUT_O;
wire FF_Q;
localparam SIG_MASK = `SIG_MASK;
genvar i;
generate for(i = 0; i < 6; i = i + 1) begin : loop
if(((1 << i) & SIG_MASK) != 0) begin
assign I[i] = FF_Q;
end else begin
assign I[i] = 1;
end
end endgenerate
(* LOC="SLICE_X37Y74", BEL="C6LUT", KEEP, DONT_TOUCH *)
LUT6 lut(
.I0(I[0]),
.I1(I[1]),
.I2(I[2]),
.I3(I[3]),
.I4(I[4]),
.I5(I[5]),
.O(LUT_O)
);
(* LOC="SLICE_X37Y74", BEL="CFF", KEEP, DONT_TOUCH *)
FDRE ff(
.C(clk),
.R(0),
.CE(1),
.D(LUT_O),
.Q(FF_Q)
);
endmodule

View File

@ -0,0 +1,11 @@
module top(input clk, stb, di, output do);
reg [31:0] counter = 0;
assign do = &counter;
always @(posedge clk) begin
counter <= counter + 1;
end
endmodule

View File

@ -0,0 +1,38 @@
module top(input clk, stb, di, output do);
wire [5:0] I;
wire LUT_O;
wire FF_Q;
localparam SIG_MASK = `SIG_MASK;
genvar i;
generate for(i = 0; i < 6; i = i + 1) begin : loop
if(((1 << i) & SIG_MASK) != 0) begin
assign I[i] = FF_Q;
end else begin
assign I[i] = 1;
end
end endgenerate
(* LOC="SLICE_X37Y74", BEL="D6LUT", KEEP, DONT_TOUCH *)
LUT6 lut(
.I0(I[0]),
.I1(I[1]),
.I2(I[2]),
.I3(I[3]),
.I4(I[4]),
.I5(I[5]),
.O(LUT_O)
);
(* LOC="SLICE_X37Y74", BEL="DFF", KEEP, DONT_TOUCH *)
FDRE ff(
.C(clk),
.R(0),
.CE(1),
.D(LUT_O),
.Q(FF_Q)
);
endmodule

View File

@ -0,0 +1,38 @@
module top(input clk, stb, di, output do);
wire [5:0] I;
wire LUT_O;
wire FF_Q;
localparam SIG_MASK = `SIG_MASK;
genvar i;
generate for(i = 0; i < 6; i = i + 1) begin : loop
if(((1 << i) & SIG_MASK) != 0) begin
assign I[i] = FF_Q;
end else begin
assign I[i] = 1;
end
end endgenerate
(* LOC="SLICE_X36Y74", BEL="D6LUT", KEEP, DONT_TOUCH *)
LUT6 lut(
.I0(I[0]),
.I1(I[1]),
.I2(I[2]),
.I3(I[3]),
.I4(I[4]),
.I5(I[5]),
.O(LUT_O)
);
(* LOC="SLICE_X36Y74", BEL="DFF", KEEP, DONT_TOUCH *)
FDRE ff(
.C(clk),
.R(0),
.CE(1),
.D(LUT_O),
.Q(FF_Q)
);
endmodule

View File

@ -0,0 +1,38 @@
module top(input clk, stb, di, output do);
wire [5:0] I;
wire LUT_O;
wire FF_Q;
localparam SIG_MASK = `SIG_MASK;
genvar i;
generate for(i = 0; i < 6; i = i + 1) begin : loop
if(((1 << i) & SIG_MASK) != 0) begin
assign I[i] = FF_Q;
end else begin
assign I[i] = 1;
end
end endgenerate
(* LOC="SLICE_X43Y73", BEL="D6LUT", KEEP, DONT_TOUCH *)
LUT6 lut(
.I0(I[0]),
.I1(I[1]),
.I2(I[2]),
.I3(I[3]),
.I4(I[4]),
.I5(I[5]),
.O(LUT_O)
);
(* LOC="SLICE_X44Y74", BEL="DFF", KEEP, DONT_TOUCH *)
FDRE ff(
.C(clk),
.R(0),
.CE(1),
.D(LUT_O),
.Q(FF_Q)
);
endmodule

View File

@ -0,0 +1,38 @@
module top(input clk, stb, di, output do);
wire [5:0] I;
wire LUT_O;
wire FF_Q;
localparam SIG_MASK = `SIG_MASK;
genvar i;
generate for(i = 0; i < 6; i = i + 1) begin : loop
if(((1 << i) & SIG_MASK) != 0) begin
assign I[i] = FF_Q;
end else begin
assign I[i] = 1;
end
end endgenerate
(* LOC="SLICE_X34Y74", BEL="D6LUT", KEEP, DONT_TOUCH *)
LUT6 lut(
.I0(I[0]),
.I1(I[1]),
.I2(I[2]),
.I3(I[3]),
.I4(I[4]),
.I5(I[5]),
.O(LUT_O)
);
(* LOC="SLICE_X34Y74", BEL="DFF", KEEP, DONT_TOUCH *)
FDRE ff(
.C(clk),
.R(0),
.CE(1),
.D(LUT_O),
.Q(FF_Q)
);
endmodule