add write/readback tests, seems to pass

This commit is contained in:
Fischer Moseley 2023-09-04 21:48:27 -04:00
parent 0bbdf4faa6
commit b4fb79bc8e
6 changed files with 135 additions and 123 deletions

View File

@ -5,23 +5,12 @@ module top_level (
input wire clk,
input wire uart_txd_in,
output logic uart_rxd_out,
output logic uart_rxd_out);
input wire btnu,
input wire btnd,
input wire btnl,
input wire btnr,
input wire btnc,
input wire [15:0] sw,
output logic [15:0] led,
output logic led16_b,
output logic led16_g,
output logic led16_r,
output logic led17_b,
output logic led17_g,
output logic led17_r);
logic probe0;
logic [1:0] probe1;
logic [7:0] probe2;
logic [19:0] probe3;
manta manta_inst (
.clk(clk),
@ -29,19 +18,14 @@ module top_level (
.rx(uart_txd_in),
.tx(uart_rxd_out),
.btnu(btnu),
.btnd(btnd),
.btnl(btnl),
.btnr(btnr),
.btnc(btnc),
.sw(sw),
.led(led),
.led16_b(led16_b),
.led16_g(led16_g),
.led16_r(led16_r),
.led17_b(led17_b),
.led17_g(led17_g),
.led17_r(led17_r));
.probe0(probe0),
.probe1(probe1),
.probe2(probe2),
.probe3(probe3),
.probe4(probe0),
.probe5(probe1),
.probe6(probe2),
.probe7(probe3));
endmodule

View File

@ -0,0 +1,22 @@
from manta import Manta
from random import randint
m = Manta('manta.yaml')
n_tests = 100
for i in range(n_tests):
print(f"-> Beginning test {i} of {n_tests}")
probe4 = randint(0, 1)
m.io_core.probe4.set(probe4)
assert m.io_core.probe0.get() == probe4
probe5 = randint(0, 3)
m.io_core.probe5.set(probe5)
assert m.io_core.probe1.get() == probe5
probe6 = randint(0, 255)
m.io_core.probe6.set(probe6)
assert m.io_core.probe2.get() == probe6
probe7 = randint(0, (2**20)-1)
m.io_core.probe7.set(probe7)
assert m.io_core.probe3.get() == probe7

View File

@ -11,49 +11,49 @@ create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {cl
##Switches
set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { sw[0] }]; #IO_L24N_T3_RS0_15 Sch=sw[0]
set_property -dict { PACKAGE_PIN L16 IOSTANDARD LVCMOS33 } [get_ports { sw[1] }]; #IO_L3N_T0_DQS_EMCCLK_14 Sch=sw[1]
set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports { sw[2] }]; #IO_L6N_T0_D08_VREF_14 Sch=sw[2]
set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 } [get_ports { sw[3] }]; #IO_L13N_T2_MRCC_14 Sch=sw[3]
set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { sw[4] }]; #IO_L12N_T1_MRCC_14 Sch=sw[4]
set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 } [get_ports { sw[5] }]; #IO_L7N_T1_D10_14 Sch=sw[5]
set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { sw[6] }]; #IO_L17N_T2_A13_D29_14 Sch=sw[6]
set_property -dict { PACKAGE_PIN R13 IOSTANDARD LVCMOS33 } [get_ports { sw[7] }]; #IO_L5N_T0_D07_14 Sch=sw[7]
set_property -dict { PACKAGE_PIN T8 IOSTANDARD LVCMOS18 } [get_ports { sw[8] }]; #IO_L24N_T3_34 Sch=sw[8]
set_property -dict { PACKAGE_PIN U8 IOSTANDARD LVCMOS18 } [get_ports { sw[9] }]; #IO_25_34 Sch=sw[9]
set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { sw[10] }]; #IO_L15P_T2_DQS_RDWR_B_14 Sch=sw[10]
set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { sw[11] }]; #IO_L23P_T3_A03_D19_14 Sch=sw[11]
set_property -dict { PACKAGE_PIN H6 IOSTANDARD LVCMOS33 } [get_ports { sw[12] }]; #IO_L24P_T3_35 Sch=sw[12]
set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 } [get_ports { sw[13] }]; #IO_L20P_T3_A08_D24_14 Sch=sw[13]
set_property -dict { PACKAGE_PIN U11 IOSTANDARD LVCMOS33 } [get_ports { sw[14] }]; #IO_L19N_T3_A09_D25_VREF_14 Sch=sw[14]
set_property -dict { PACKAGE_PIN V10 IOSTANDARD LVCMOS33 } [get_ports { sw[15] }]; #IO_L21P_T3_DQS_14 Sch=sw[15]
#set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { sw[0] }]; #IO_L24N_T3_RS0_15 Sch=sw[0]
#set_property -dict { PACKAGE_PIN L16 IOSTANDARD LVCMOS33 } [get_ports { sw[1] }]; #IO_L3N_T0_DQS_EMCCLK_14 Sch=sw[1]
#set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports { sw[2] }]; #IO_L6N_T0_D08_VREF_14 Sch=sw[2]
#set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 } [get_ports { sw[3] }]; #IO_L13N_T2_MRCC_14 Sch=sw[3]
#set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { sw[4] }]; #IO_L12N_T1_MRCC_14 Sch=sw[4]
#set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 } [get_ports { sw[5] }]; #IO_L7N_T1_D10_14 Sch=sw[5]
#set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { sw[6] }]; #IO_L17N_T2_A13_D29_14 Sch=sw[6]
#set_property -dict { PACKAGE_PIN R13 IOSTANDARD LVCMOS33 } [get_ports { sw[7] }]; #IO_L5N_T0_D07_14 Sch=sw[7]
#set_property -dict { PACKAGE_PIN T8 IOSTANDARD LVCMOS18 } [get_ports { sw[8] }]; #IO_L24N_T3_34 Sch=sw[8]
#set_property -dict { PACKAGE_PIN U8 IOSTANDARD LVCMOS18 } [get_ports { sw[9] }]; #IO_25_34 Sch=sw[9]
#set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { sw[10] }]; #IO_L15P_T2_DQS_RDWR_B_14 Sch=sw[10]
#set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { sw[11] }]; #IO_L23P_T3_A03_D19_14 Sch=sw[11]
#set_property -dict { PACKAGE_PIN H6 IOSTANDARD LVCMOS33 } [get_ports { sw[12] }]; #IO_L24P_T3_35 Sch=sw[12]
#set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 } [get_ports { sw[13] }]; #IO_L20P_T3_A08_D24_14 Sch=sw[13]
#set_property -dict { PACKAGE_PIN U11 IOSTANDARD LVCMOS33 } [get_ports { sw[14] }]; #IO_L19N_T3_A09_D25_VREF_14 Sch=sw[14]
#set_property -dict { PACKAGE_PIN V10 IOSTANDARD LVCMOS33 } [get_ports { sw[15] }]; #IO_L21P_T3_DQS_14 Sch=sw[15]
## LEDs
set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { led[0] }]; #IO_L18P_T2_A24_15 Sch=led[0]
set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { led[1] }]; #IO_L24P_T3_RS1_15 Sch=led[1]
set_property -dict { PACKAGE_PIN J13 IOSTANDARD LVCMOS33 } [get_ports { led[2] }]; #IO_L17N_T2_A25_15 Sch=led[2]
set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { led[3] }]; #IO_L8P_T1_D11_14 Sch=led[3]
set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { led[4] }]; #IO_L7P_T1_D09_14 Sch=led[4]
set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { led[5] }]; #IO_L18N_T2_A11_D27_14 Sch=led[5]
set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { led[6] }]; #IO_L17P_T2_A14_D30_14 Sch=led[6]
set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { led[7] }]; #IO_L18P_T2_A12_D28_14 Sch=led[7]
set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { led[8] }]; #IO_L16N_T2_A15_D31_14 Sch=led[8]
set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { led[9] }]; #IO_L14N_T2_SRCC_14 Sch=led[9]
set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { led[10] }]; #IO_L22P_T3_A05_D21_14 Sch=led[10]
set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { led[11] }]; #IO_L15N_T2_DQS_DOUT_CSO_B_14 Sch=led[11]
set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { led[12] }]; #IO_L16P_T2_CSI_B_14 Sch=led[12]
set_property -dict { PACKAGE_PIN V14 IOSTANDARD LVCMOS33 } [get_ports { led[13] }]; #IO_L22N_T3_A04_D20_14 Sch=led[13]
set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 } [get_ports { led[14] }]; #IO_L20N_T3_A07_D23_14 Sch=led[14]
set_property -dict { PACKAGE_PIN V11 IOSTANDARD LVCMOS33 } [get_ports { led[15] }]; #IO_L21N_T3_DQS_A06_D22_14 Sch=led[15]
set_property -dict { PACKAGE_PIN R12 IOSTANDARD LVCMOS33 } [get_ports { led16_b }]; #IO_L5P_T0_D06_14 Sch=led16_b
set_property -dict { PACKAGE_PIN M16 IOSTANDARD LVCMOS33 } [get_ports { led16_g }]; #IO_L10P_T1_D14_14 Sch=led16_g
set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 } [get_ports { led16_r }]; #IO_L11P_T1_SRCC_14 Sch=led16_r
set_property -dict { PACKAGE_PIN G14 IOSTANDARD LVCMOS33 } [get_ports { led17_b }]; #IO_L15N_T2_DQS_ADV_B_15 Sch=led17_b
set_property -dict { PACKAGE_PIN R11 IOSTANDARD LVCMOS33 } [get_ports { led17_g }]; #IO_0_14 Sch=led17_g
set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 } [get_ports { led17_r }]; #IO_L11N_T1_SRCC_14 Sch=led17_r
#set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { led[0] }]; #IO_L18P_T2_A24_15 Sch=led[0]
#set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { led[1] }]; #IO_L24P_T3_RS1_15 Sch=led[1]
#set_property -dict { PACKAGE_PIN J13 IOSTANDARD LVCMOS33 } [get_ports { led[2] }]; #IO_L17N_T2_A25_15 Sch=led[2]
#set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { led[3] }]; #IO_L8P_T1_D11_14 Sch=led[3]
#set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { led[4] }]; #IO_L7P_T1_D09_14 Sch=led[4]
#set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { led[5] }]; #IO_L18N_T2_A11_D27_14 Sch=led[5]
#set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { led[6] }]; #IO_L17P_T2_A14_D30_14 Sch=led[6]
#set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { led[7] }]; #IO_L18P_T2_A12_D28_14 Sch=led[7]
#set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { led[8] }]; #IO_L16N_T2_A15_D31_14 Sch=led[8]
#set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { led[9] }]; #IO_L14N_T2_SRCC_14 Sch=led[9]
#set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { led[10] }]; #IO_L22P_T3_A05_D21_14 Sch=led[10]
#set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { led[11] }]; #IO_L15N_T2_DQS_DOUT_CSO_B_14 Sch=led[11]
#set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { led[12] }]; #IO_L16P_T2_CSI_B_14 Sch=led[12]
#set_property -dict { PACKAGE_PIN V14 IOSTANDARD LVCMOS33 } [get_ports { led[13] }]; #IO_L22N_T3_A04_D20_14 Sch=led[13]
#set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 } [get_ports { led[14] }]; #IO_L20N_T3_A07_D23_14 Sch=led[14]
#set_property -dict { PACKAGE_PIN V11 IOSTANDARD LVCMOS33 } [get_ports { led[15] }]; #IO_L21N_T3_DQS_A06_D22_14 Sch=led[15]
#
#set_property -dict { PACKAGE_PIN R12 IOSTANDARD LVCMOS33 } [get_ports { led16_b }]; #IO_L5P_T0_D06_14 Sch=led16_b
#set_property -dict { PACKAGE_PIN M16 IOSTANDARD LVCMOS33 } [get_ports { led16_g }]; #IO_L10P_T1_D14_14 Sch=led16_g
#set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 } [get_ports { led16_r }]; #IO_L11P_T1_SRCC_14 Sch=led16_r
#set_property -dict { PACKAGE_PIN G14 IOSTANDARD LVCMOS33 } [get_ports { led17_b }]; #IO_L15N_T2_DQS_ADV_B_15 Sch=led17_b
#set_property -dict { PACKAGE_PIN R11 IOSTANDARD LVCMOS33 } [get_ports { led17_g }]; #IO_0_14 Sch=led17_g
#set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 } [get_ports { led17_r }]; #IO_L11N_T1_SRCC_14 Sch=led17_r
##7 segment display
@ -82,11 +82,11 @@ set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 } [get_ports { led17_
#set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports { cpu_resetn }]; #IO_L3P_T0_DQS_AD1P_15 Sch=cpu_resetn
set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { btnc }]; #IO_L9P_T1_DQS_14 Sch=btnc
set_property -dict { PACKAGE_PIN M18 IOSTANDARD LVCMOS33 } [get_ports { btnu }]; #IO_L4N_T0_D05_14 Sch=btnu
set_property -dict { PACKAGE_PIN P17 IOSTANDARD LVCMOS33 } [get_ports { btnl }]; #IO_L12P_T1_MRCC_14 Sch=btnl
set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 } [get_ports { btnr }]; #IO_L10N_T1_D15_14 Sch=btnr
set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { btnd }]; #IO_L9N_T1_DQS_D13_14 Sch=btnd
#set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { btnc }]; #IO_L9P_T1_DQS_14 Sch=btnc
#set_property -dict { PACKAGE_PIN M18 IOSTANDARD LVCMOS33 } [get_ports { btnu }]; #IO_L4N_T0_D05_14 Sch=btnu
#set_property -dict { PACKAGE_PIN P17 IOSTANDARD LVCMOS33 } [get_ports { btnl }]; #IO_L12P_T1_MRCC_14 Sch=btnl
#set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 } [get_ports { btnr }]; #IO_L10N_T1_D15_14 Sch=btnr
#set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { btnd }]; #IO_L9N_T1_DQS_D13_14 Sch=btnd
##Pmod Headers

View File

@ -1,23 +1,56 @@
from ..utils import *
from math import ceil
class IOCoreProbe:
def __init__(self, name, width, base_addr, initial_value = None):
class InputProbe:
def __init__(self, name, width, base_addr, strobe_addr, interface):
assert isinstance(width, int), f"Probe {name} must have integer width."
assert width > 0, f"Probe {name} must have positive width."
self.name = name
self.width = width
self.initial_value = initial_value
self.strobe_addr = strobe_addr
self.interface = interface
n_addrs = ceil(self.width / 16)
self.addrs = list(range(base_addr, base_addr + n_addrs))
self.brackets = "" if self.width == 1 else f"[{self.width-1}:0] "
def pulse_strobe_register(self):
# pulse the strobe register
self.interface.write(self.strobe_addr, 1)
self.interface.write(self.strobe_addr, 0)
strobe = self.interface.read(self.strobe_addr)
if strobe != 0:
raise ValueError("Unable to set strobe register to zero!")
def get(self):
self.pulse_strobe_register()
return pack_16bit_words(self.interface.read(self.addrs))
class OutputProbe(InputProbe):
def __init__(self, name, width, base_addr, strobe_addr, interface, initial_value):
super().__init__(name, width, base_addr, strobe_addr, interface)
self.initial_value = initial_value
def set(self, value):
# check that value is an integer
assert isinstance(value, int), "Value must be an integer."
# check that value is within range for the width of the probe
if value > 0:
assert value <= (2**self.width) - 1, f"Unsigned value too large for probe of width {self.width}"
elif value < 0:
assert abs(value) <= (2**(self.width-1))-1, f"Signed value too large for probe of width {self.width}"
self.interface.write(self.addrs, unpack_16bit_words(value, len(self.addrs)))
self.pulse_strobe_register()
class IOCore:
def __init__(self, config, name, base_addr, interface):
self.name = name
self.base_addr = base_addr
self.interface = interface
# make sure we have ports defined
assert ('inputs' in config) or ('outputs' in config), "No input or output ports specified."
@ -38,7 +71,7 @@ class IOCore:
last_used_addr = self.base_addr # start at one since strobe register is at BASE_ADDR
if 'inputs' in config:
for name, width in config["inputs"].items():
probe = IOCoreProbe(name, width, last_used_addr + 1)
probe = InputProbe(name, width, last_used_addr + 1, self.base_addr, interface)
last_used_addr = probe.addrs[-1]
self.input_probes.append(probe)
@ -59,7 +92,7 @@ class IOCore:
raise ValueError(f"Unable to determine probe width and initial value for {name}")
# add probe to core
probe = IOCoreProbe(name, width, last_used_addr + 1, initial_value)
probe = OutputProbe(name, width, last_used_addr + 1, self.base_addr, interface, initial_value)
last_used_addr = probe.addrs[-1]
self.output_probes.append(probe)
@ -67,43 +100,9 @@ class IOCore:
# add friendly names to each probe
# (so users can do io_core.probe.set() and get() for instance)
for probe in self.input_probes:
setattr(probe, "set", lambda value: self.set(probe, value) )
for probe in self.input_probes + self.output_probes:
setattr(self, probe.name, probe)
for probe in self.input_probes:
setattr(probe, "set", lambda value: self.set(probe, value) )
setattr(probe, "get", self.get(probe) )
setattr(self, probe.name, probe)
def get(self, probe):
self.pulse_strobe_register()
return pack_16bit_words(self.interface.read(probe.addrs))
def set(self, probe, value):
# check that value is an integer
assert isinstance(value, int), "Value must be an integer."
# check that value is within range for the width of the probe
if value > 0:
assert data <= (2**self.width) - 1, f"Unsigned value too large for probe of width {self.width}"
elif value < 0:
assert abs(data) <= (2**(self.width-1))-1, f"Signed value too large for probe of width {self.width}"
self.pulse_strobe_register()
data = unpack_16_bit_words(value)
self.interface.write(probe.addrs, data)
def pulse_strobe_register(self):
# pulse the strobe register
self.interface.write(self.base_addr, 1)
self.interface.write(self.base_addr, 0)
strobe = self.interface.read(self.base_addr)
if strobe != 0:
raise ValueError("Unable to set strobe register to zero!")
def hdl_top_level_ports(self):
ports = []
@ -113,7 +112,7 @@ class IOCore:
for probe in self.input_probes:
ports.append(f"input wire {probe.brackets}{probe.name}")
for probe in self.input_probes:
for probe in self.output_probes:
ports.append(f"output reg {probe.brackets}{probe.name}")
return ports
@ -202,7 +201,7 @@ class IOCore:
return '\n'.join(lines)
def gen_output_probe_initial_values(self):
lines = [f"{p.name} = {p.initial_value}" for p in self.output_probes]
lines = [f"{p.name} = {p.initial_value};" for p in self.output_probes]
return '\n'.join(lines)
def gen_update_input_buffers(self):

View File

@ -116,7 +116,7 @@ class UARTInterface:
response = inbound_bytes[i:i+7]
data.append(self.decode_response(response))
if len(data) == 1:
if isinstance(addr, int):
return data[0]
else:

View File

@ -1,19 +1,26 @@
import pkgutil
from math import ceil
def pack_16bit_words(data):
"""Takes a list of integers, interprets them as 16-bit integers, and
concatenates them together in little-endian order."""
for d in data:
if d > 0:
assert d < 2**16-1, "Unsigned integer too large."
if d < 0:
assert d < 2**15-1, "Signed integer too large."
for d in data:
if d > 0: assert d < 2**16-1, "Unsigned integer too large."
if d < 0: assert d < 2**15-1, "Signed integer too large."
return int(''.join([f'{i:016b}' for i in data[::-1]]), 2)
def unpack_16bit_words(data):
pass
def unpack_16bit_words(data, n_words):
"""Takes a integer, interprets it as a set of 16-bit integers
concatenated together, and splits it into a list of 16-bit numbers"""
assert isinstance(data, int), "Behavior is only defined for nonnegative integers."
assert data >= 0, "Behavior is only defined for nonnegative integers."
# convert to binary, split into 16-bit chunks, and then convert back to list of int
binary = f'{data:0b}'.zfill(n_words * 16)
return [int(binary[i:i+16], 2) for i in range(0, 16 * n_words, 16)][::-1]
class VerilogManipulator:
def __init__(self, filepath=None):