From d2bcbe2418a84aea96543560c7d4cf862a06d017 Mon Sep 17 00:00:00 2001 From: Fischer Moseley Date: Sat, 4 Feb 2023 12:43:00 -0500 Subject: [PATCH] import from openILA --- .gitignore | 2 + build.py | 0 config_template.json | 0 examples/counter/ila.json | 25 ++ examples/counter/lab-bc.py | 243 ++++++++++++++++ examples/counter/src/ila.sv | 227 +++++++++++++++ examples/counter/src/top_level.sv | 34 +++ examples/counter/xdc/top_level.xdc | 260 ++++++++++++++++++ gen_ila.py | 72 +++++ logo.py | 16 ++ run_ila.py | 159 +++++++++++ src/fifo.sv | 84 ++++++ src/ila_template.sv | 224 +++++++++++++++ src/uart_rx.sv | 72 +++++ src/uart_tx.sv | 81 ++++++ ...nx_true_dual_port_read_first_2_clock_ram.v | 149 ++++++++++ test/fifo_tb.sv | 71 +++++ test/ila_tb.sv | 69 +++++ test/uart_tb.sv | 72 +++++ test/uart_tx_tb.sv | 50 ++++ 20 files changed, 1910 insertions(+) create mode 100644 .gitignore create mode 100644 build.py create mode 100644 config_template.json create mode 100644 examples/counter/ila.json create mode 100644 examples/counter/lab-bc.py create mode 100644 examples/counter/src/ila.sv create mode 100644 examples/counter/src/top_level.sv create mode 100644 examples/counter/xdc/top_level.xdc create mode 100644 gen_ila.py create mode 100644 logo.py create mode 100644 run_ila.py create mode 100644 src/fifo.sv create mode 100644 src/ila_template.sv create mode 100644 src/uart_rx.sv create mode 100644 src/uart_tx.sv create mode 100644 src/xilinx_true_dual_port_read_first_2_clock_ram.v create mode 100644 test/fifo_tb.sv create mode 100644 test/ila_tb.sv create mode 100644 test/uart_tb.sv create mode 100644 test/uart_tx_tb.sv diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ce383cb --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.vcd +*.out diff --git a/build.py b/build.py new file mode 100644 index 0000000..e69de29 diff --git a/config_template.json b/config_template.json new file mode 100644 index 0000000..e69de29 diff --git a/examples/counter/ila.json b/examples/counter/ila.json new file mode 100644 index 0000000..8bfd5a7 --- /dev/null +++ b/examples/counter/ila.json @@ -0,0 +1,25 @@ +{ + "probes": { + "larry" : 1, + "curly" : 1, + "moe" : 1, + "shemp" : 3 + }, + + "triggers": [ + "larry && curly && ~moe" + ], + + "uart": { + "baudrate" : 115200, + "data" : 8, + "parity" : "none", + "stop" : 1, + "port" : "/dev/tty.usbserial-2102926963071", + "timeout" : 1 + }, + + "sample_depth": 4096, + "output_dir" : "src/ila.svh", + "clock_freq" : 100e6 + } \ No newline at end of file diff --git a/examples/counter/lab-bc.py b/examples/counter/lab-bc.py new file mode 100644 index 0000000..63458a7 --- /dev/null +++ b/examples/counter/lab-bc.py @@ -0,0 +1,243 @@ +import atexit +import getopt +import os +import subprocess +import signal +import sys +import time +import pathlib +import platform + +progname = sys.argv[0] + +diagnostics = False +quiet = False +verbose = False + +port = 80 +machine = "eecs-digital-56.mit.edu" +projectdir = "." +of = "obj" + +p = False + +user = "builder" +outfile = f"{of}/out.bit" +logfile = f"{of}/build.log" + +synthrpt = [ + "report_timing", + "report_timing_summary", + "report_utilization", + ] + +placerpt = synthrpt.copy() +placerpt.extend(['report_clock_utilization']) + +routerpt = [ + 'report_drc', + 'report_power', + 'report_route_status', + 'report_timing', + 'report_timing_summary', + ] + +usagestr = f""" +{progname}: build SystemVerilog code remotely for 2022 6.205 labs +usage: {progname} [-dqv] [-m machine] [-p projectdir] [-o dir] +options: + -d: emit additional diagnostics during synthesis/implementation + -q: quiet: do not generate any vivado logs except for errors. + -v: be verbose (for debugging stuffs / if you see a bug) + -m: override the DNS name queried to perform the build. use with care. + -p: build the project located in projectdir (default is '.') + -o: set the output products directory (default is {of}) +""" + +def debuglog(s): + if verbose: print(s) + +def usage(): + print(usagestr) + sys.exit(1) + +def getargs(): + global diagnostics + global quiet + global machine + global logfile + global outfile + global projectdir + global of + global verbose + + try: + opts, args = getopt.getopt(sys.argv[1:], "dm:o:p:qv") + except getopt.GetoptError as err: + print(err) + usage() + + if args: usage() + for o, v in opts: + if o == '-d': diagnostics = True + elif o == '-q': quiet = True + elif o == '-m': machine = v + elif o == '-p': projectdir = v + elif o == '-o': of = v + elif o == '-v': verbose = True + else: + print(f"unrecognized option {o}") + usage() + + outfile = f"{of}/out.bit" + logfile = f"{of}/build.log" + +def make_posix(path): + return str(pathlib.Path(path).as_posix()) + +def regfiles(): + ftt = {} + debuglog(f"projectdir is {projectdir}") + for dirpath, subdirs, files in os.walk(projectdir): + if 'src' not in dirpath and 'xdc' not in dirpath and 'data' not in dirpath and 'ip' not in dirpath: + continue + if dirpath.startswith("./"): dirpath = dirpath[2:] + for file in files: + fpath = os.path.join(dirpath, file) + debuglog(f"considering {fpath}") + fpath = make_posix(fpath) + + if file.lower().endswith('.v'): ftt[fpath] = 'source' + elif file.lower().endswith('.sv'): ftt[fpath] = 'source' + elif file.lower().endswith('.vh'): ftt[fpath] = 'source' + elif file.lower().endswith('.svh'): ftt[fpath] = 'source' + elif file.lower().endswith('.xdc'): ftt[fpath] = 'xdc' + elif file.lower().endswith('.mem'): ftt[fpath] = 'mem' + elif file.lower().endswith('.xci'): ftt[fpath] = 'ip' + elif file.lower().endswith('.prj'): ftt[fpath] = 'mig' + + debuglog(f"elaborated file list {ftt}") + return ftt + +# messages are newline delineated per lab-bs.1 +# utilize this to cheat a little bit +def spqsend(p, msg): + debuglog(f"writing {len(msg)} bytes over the wire") + debuglog(f"full message: {msg}") + p.stdin.write(msg + b'\n') + p.stdin.flush() + +def spsend(p, msg): + debuglog(f"running {msg}") + p.stdin.write((msg + '\n').encode()) + p.stdin.flush() + +def sprecv(p): + l = p.stdout.readline().decode() + debuglog(f"got {l}") + return l + +def xsprecv(p): + l = sprecv(p) + if (l.startswith("ERR")): + print("received unexpected server error!") + print(l) + sys.exit(1) + return l + +def spstart(xargv): + debuglog(f"spawning {xargv}") + p = subprocess.PIPE + return subprocess.Popen(xargv, stdin=p, stdout=p, stderr=p) + +def copyfiles(p, ftt): + for f, t in ftt.items(): + fsize = os.path.getsize(f) + with open(f, 'rb') as fd: + spsend(p, f"write {f} {fsize}") + time.sleep(0.1) #? + spqsend(p, fd.read()) + xsprecv(p) + + spsend(p, f"type {f} {t}") + xsprecv(p) + +# size message returns ... %zu bytes +def readfile(p, file, targetfile): + spsend(p, f"size {file}") + size = int(xsprecv(p).split()[-2]) + spsend(p, f"read {file}") + + with open(targetfile, 'wb+') as fd: + fd.write(p.stdout.read(size)) + + xsprecv(p) + +def build(p): + cmd = "build" + if diagnostics: cmd += " -d" + if quiet: cmd += " -q" + cmd += f" obj" + + print(f"Output target will be {outfile}") + + spsend(p, cmd) + print("Building your code ... (this may take a while, be patient)") + result = sprecv(p) + + if result.startswith("ERR"): print("Something went wrong!") + else: + readfile(p, "obj/out.bit", outfile) + print(f"Build succeeded, output at {outfile}") + + readfile(p, "obj/build.log", logfile) + print(f"Log file available at {logfile}") + + if (diagnostics): + for rpt in synthrpt: + readfile(p, f"obj/synthrpt_{rpt}.rpt", f"{of}/synthrpt_{rpt}.rpt") + for rpt in placerpt: + readfile(p, f"obj/placerpt_{rpt}.rpt", f"{of}/placerpt_{rpt}.rpt") + for rpt in routerpt: + readfile(p, f"obj/routerpt_{rpt}.rpt", f"{of}/routerpt_{rpt}.rpt") + print(f"Diagnostics available in {of}") + +def main(): + global p + getargs() + ftt = regfiles() + + if not os.path.isdir(of): + print(f"output path {of} does not exist! create it or use -o?") + usage() + + if platform.system() == 'Darwin' or platform.system() == 'Linux': + xargv = ['ssh', '-p', f"{port}", '-o', "StrictHostKeyChecking=no", '-o', 'UserKnownHostsFile=/dev/null'] + + elif platform.system() == 'Windows': + xargv = ['ssh', '-p', f"{port}", '-o', "StrictHostKeyChecking=no", '-o', 'UserKnownHostsFile=nul'] + + else: + raise RuntimeError('Your OS is not recognized, unsure of how to format SSH command.') + + + xargv.append(f"{user}@{machine}") + p = spstart(xargv) + + spsend(p, "help") + result = xsprecv(p) + debuglog(result) + + copyfiles(p, ftt) + build(p) + spsend(p, "exit") + p.wait() + +if __name__ == "__main__": + try: main() + except (Exception, KeyboardInterrupt) as e: + if p: + debuglog("killing ssh") + os.kill(p.pid, signal.SIGINT) + p.wait() + raise e diff --git a/examples/counter/src/ila.sv b/examples/counter/src/ila.sv new file mode 100644 index 0000000..f1babbf --- /dev/null +++ b/examples/counter/src/ila.sv @@ -0,0 +1,227 @@ +`default_nettype none +`timescale 1ns / 1ps + +/* +This ILA was autogenerated on 03/02/2023 23:13:51 by fischerm + +If this breaks or if you've got dank formal verification memes, +please contact fischerm [at] mit.edu. +*/ + +`define IDLE 0 +`define ARM 1 +`define FILL 2 +`define DOWNLINK 3 + +`define ARM_BYTE 8'b00110000 + +module ila ( + input wire clk, + input wire rst, + + /* Begin autogenerated probe definitions */ + input wire larry, + input wire curly, + input wire moe, + input wire [2:0] shemp, + /* End autogenerated probe definitions */ + + input wire rxd, + output logic txd); + + /* Begin autogenerated parameters */ + localparam SAMPLE_WIDTH = 6; + localparam SAMPLE_DEPTH = 4096; + + localparam DATA_WIDTH = 8; + localparam BAUDRATE = 115200; + localparam CLK_FREQ_HZ = 100000000; + + logic trigger; + assign trigger = (larry && curly && ~moe); + + logic [SAMPLE_WIDTH - 1 : 0] concat; + assign concat = {larry, curly, moe, shemp};; + /* End autogenerated parameters */ + + + // FIFO + logic [7:0] fifo_data_in; + logic fifo_input_ready; + + logic fifo_request_output; + logic [7:0] fifo_data_out; + logic fifo_output_valid; + + logic [11:0] fifo_size; + logic fifo_empty; + logic fifo_full; + + fifo #( + .WIDTH(SAMPLE_WIDTH), + .DEPTH(SAMPLE_DEPTH) + ) fifo ( + .clk(clk), + .rst(rst), + + .data_in(fifo_data_in), + .input_ready(fifo_input_ready), + + .request_output(fifo_request_output), + .data_out(fifo_data_out), + .output_valid(fifo_output_valid), + + .size(fifo_size), + .empty(fifo_empty), + .full(fifo_full)); + + // Serial interface + logic tx_start; + logic [7:0] tx_data; + logic tx_busy; + + logic [7:0] rx_data; + logic rx_ready; + logic rx_busy; + + + uart_tx #( + .DATA_WIDTH(DATA_WIDTH), + .CLK_FREQ_HZ(CLK_FREQ_HZ), + .BAUDRATE(BAUDRATE)) + tx ( + .clk(clk), + .rst(rst), + .start(tx_start), + .data(tx_data), + + .busy(tx_busy), + .txd(txd)); + + uart_rx #( + .DATA_WIDTH(DATA_WIDTH), + .CLK_FREQ_HZ(CLK_FREQ_HZ), + .BAUDRATE(BAUDRATE)) + rx ( + .clk(clk), + .rst(rst), + .rxd(rxd), + + .data(rx_data), + .ready(rx_ready), + .busy(rx_busy)); + + + /* State Machine */ + /* + + IDLE: + - literally nothing is happening. the FIFO isn't being written to or read from. it should be empty. + - an arm command over serial is what brings us into the ARM state + + ARM: + - popping things onto FIFO. if the fifo is halfway full, we pop them off too. + - meeting the trigger condition is what moves us into the filing state + + FILL: + - popping things onto FIFO, until it's full. once it is full, we move into the downlinking state + + DOWNLINK: + - popping thing off of the FIFO until it's empty. once it's empty, we move back into the IDLE state + */ + + /* Downlink State Machine Controller */ + /* + + - ila enters the downlink state + - set fifo_output_request high for a clock cycle + - when fifo_output_valid goes high, send fifo_data_out across the line + - do nothing until tx_busy goes low + - goto step 2 + + */ + + logic [1:0] state; + logic [2:0] downlink_fsm_state; + + always_ff @(posedge clk) begin + if(rst) begin + state <= `IDLE; + downlink_fsm_state <= 0; + tx_data <= 0; + tx_start <= 0; + end + else begin + + case (state) + `IDLE : begin + fifo_input_ready <= 0; + fifo_request_output <= 0; + + if (rx_ready && rx_data == `ARM_BYTE) state <= `ARM; + + end + + `ARM : begin + // place samples into FIFO + fifo_input_ready <= 1; + fifo_data_in <= concat; + + // remove old samples if we're more than halfway full + fifo_request_output <= (fifo_size >= SAMPLE_DEPTH / 2); + + if(trigger) state <= `FILL; + end + + `FILL : begin + // place samples into FIFO + fifo_input_ready <= 1; + fifo_data_in <= concat; + + // don't pop anything out the FIFO + fifo_request_output <= 0; + + if(fifo_size == SAMPLE_DEPTH - 1) state <= `DOWNLINK; + end + + `DOWNLINK : begin + // place no samples into FIFO + fifo_input_ready <= 0; + + + case (downlink_fsm_state) + 0 : begin + if (~fifo_empty) begin + fifo_request_output <= 1; + downlink_fsm_state <= 1; + end + + else state <= `IDLE; + end + + 1 : begin + fifo_request_output <= 0; + + if (fifo_output_valid) begin + tx_data <= fifo_data_out; + tx_start <= 1; + downlink_fsm_state <= 2; + end + end + + 2 : begin + tx_start <= 0; + + if (~tx_busy && ~tx_start) downlink_fsm_state <= 0; + end + endcase + + end + endcase + end + end + +endmodule + + +`default_nettype wire \ No newline at end of file diff --git a/examples/counter/src/top_level.sv b/examples/counter/src/top_level.sv new file mode 100644 index 0000000..d9be0b8 --- /dev/null +++ b/examples/counter/src/top_level.sv @@ -0,0 +1,34 @@ +`default_nettype none +`timescale 1ns / 1ps + +module top_level ( + input wire clk, + input wire btnc, + input wire btnu, + input wire [15:0] sw, + + output logic [15:0] led, + input wire uart_txd_in, + output logic uart_rxd_out + ); + + // Signal Generator + logic [7:0] count; + always_ff @(posedge clk) count <= count + 1; + + // ILA + // later make this a #ILA that gets loaded from a svh file that the python script generates + ila ila( + .clk(clk), + .rst(btnc), + .larry(count[0]), + .curly(count[1]), + .moe(count[2]), + .shemp(count[5:3]), + + .rxd(uart_txd_in), + .txd(uart_rxd_out)); + +endmodule + +`default_nettype wire \ No newline at end of file diff --git a/examples/counter/xdc/top_level.xdc b/examples/counter/xdc/top_level.xdc new file mode 100644 index 0000000..48fefa3 --- /dev/null +++ b/examples/counter/xdc/top_level.xdc @@ -0,0 +1,260 @@ +## R1.0 2019-08-27 +## Updated by jodalyst in 2020-2022 +## all inputs/outputs changed to lowercase; arrays start with zero. +## system clock renamed to clk +## ja, jb, jc, jd renamed to 0-7 +## xa port renamed 0-3 +## seven segments renamed to a,b,c,d,e,f,dp + +## This file is a general .xdc for the Nexys4 DDR Rev. C +## To use it in a project: +## - uncomment the lines corresponding to used pins +## - rename the used ports (in each line, after get_ports) according to the top level signal names in the project + +## Clock signal - uncomment _both_ of these lines to create clk_100mhz +set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { clk }]; #IO_L12P_T1_MRCC_35 Sch=clk +create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {clk}]; + +##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] + + +## 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 + + +##7 segment display + +#set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { ca }]; #IO_L24N_T3_A00_D16_14 Sch=ca +#set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33 } [get_ports { cb }]; #IO_25_14 Sch=cb +#set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { cc }]; #IO_25_15 Sch=cc +#set_property -dict { PACKAGE_PIN K13 IOSTANDARD LVCMOS33 } [get_ports { cd }]; #IO_L17P_T2_A26_15 Sch=cd +#set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { ce }]; #IO_L13P_T2_MRCC_14 Sch=ce +#set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { cf }]; #IO_L19P_T3_A10_D26_14 Sch=cf +#set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 } [get_ports { cg }]; #IO_L4P_T0_D04_14 Sch=cg + +#set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { dp }]; #IO_L19N_T3_A21_VREF_15 Sch=dp + +#set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { an[0] }]; #IO_L23P_T3_FOE_B_15 Sch=an[0] +#set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { an[1] }]; #IO_L23N_T3_FWE_B_15 Sch=an[1] +#set_property -dict { PACKAGE_PIN T9 IOSTANDARD LVCMOS33 } [get_ports { an[2] }]; #IO_L24P_T3_A01_D17_14 Sch=an[2] +#set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { an[3] }]; #IO_L19P_T3_A22_15 Sch=an[3] +#set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { an[4] }]; #IO_L8N_T1_D12_14 Sch=an[4] +#set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { an[5] }]; #IO_L14P_T2_SRCC_14 Sch=an[5] +#set_property -dict { PACKAGE_PIN K2 IOSTANDARD LVCMOS33 } [get_ports { an[6] }]; #IO_L23P_T3_35 Sch=an[6] +#set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { an[7] }]; #IO_L23N_T3_A02_D18_14 Sch=an[7] + + +##Buttons + +#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 + + +##Pmod Headers + + +##Pmod Header JA + +#set_property -dict { PACKAGE_PIN C17 IOSTANDARD LVCMOS33 } [get_ports { ja[0] }]; #IO_L20N_T3_A19_15 Sch=ja[1] +#set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { ja[1] }]; #IO_L21N_T3_DQS_A18_15 Sch=ja[2] +#set_property -dict { PACKAGE_PIN E18 IOSTANDARD LVCMOS33 } [get_ports { ja[2] }]; #IO_L21P_T3_DQS_15 Sch=ja[3] +#set_property -dict { PACKAGE_PIN G17 IOSTANDARD LVCMOS33 } [get_ports { ja[3] }]; #IO_L18N_T2_A23_15 Sch=ja[4] +#set_property -dict { PACKAGE_PIN D17 IOSTANDARD LVCMOS33 } [get_ports { ja[4] }]; #IO_L16N_T2_A27_15 Sch=ja[7] +#set_property -dict { PACKAGE_PIN E17 IOSTANDARD LVCMOS33 } [get_ports { ja[5] }]; #IO_L16P_T2_A28_15 Sch=ja[8] +#set_property -dict { PACKAGE_PIN F18 IOSTANDARD LVCMOS33 } [get_ports { ja[6] }]; #IO_L22N_T3_A16_15 Sch=ja[9] +#set_property -dict { PACKAGE_PIN G18 IOSTANDARD LVCMOS33 } [get_ports { ja[7] }]; #IO_L22P_T3_A17_15 Sch=ja[10] + + +##Pmod Header JB + +#set_property -dict { PACKAGE_PIN D14 IOSTANDARD LVCMOS33 } [get_ports { jb[0] }]; #IO_L1P_T0_AD0P_15 Sch=jb[1] +#set_property -dict { PACKAGE_PIN F16 IOSTANDARD LVCMOS33 } [get_ports { jb[1] }]; #IO_L14N_T2_SRCC_15 Sch=jb[2] +#set_property -dict { PACKAGE_PIN G16 IOSTANDARD LVCMOS33 } [get_ports { jb[2] }]; #IO_L13N_T2_MRCC_15 Sch=jb[3] +#set_property -dict { PACKAGE_PIN H14 IOSTANDARD LVCMOS33 } [get_ports { jb[3] }]; #IO_L15P_T2_DQS_15 Sch=jb[4] +#set_property -dict { PACKAGE_PIN E16 IOSTANDARD LVCMOS33 } [get_ports { jb[4] }]; #IO_L11N_T1_SRCC_15 Sch=jb[7] +#set_property -dict { PACKAGE_PIN F13 IOSTANDARD LVCMOS33 } [get_ports { jb[5] }]; #IO_L5P_T0_AD9P_15 Sch=jb[8] +#set_property -dict { PACKAGE_PIN G13 IOSTANDARD LVCMOS33 } [get_ports { jb[6] }]; #IO_0_15 Sch=jb[9] +#set_property -dict { PACKAGE_PIN H16 IOSTANDARD LVCMOS33 } [get_ports { jb[7] }]; #IO_L13P_T2_MRCC_15 Sch=jb[10] + + +##Pmod Header JC + +#set_property -dict { PACKAGE_PIN K1 IOSTANDARD LVCMOS33 } [get_ports { jc[0] }]; #IO_L23N_T3_35 Sch=jc[1] +#set_property -dict { PACKAGE_PIN F6 IOSTANDARD LVCMOS33 } [get_ports { jc[1] }]; #IO_L19N_T3_VREF_35 Sch=jc[2] +#set_property -dict { PACKAGE_PIN J2 IOSTANDARD LVCMOS33 } [get_ports { jc[2] }]; #IO_L22N_T3_35 Sch=jc[3] +#set_property -dict { PACKAGE_PIN G6 IOSTANDARD LVCMOS33 } [get_ports { jc[3] }]; #IO_L19P_T3_35 Sch=jc[4] +#set_property -dict { PACKAGE_PIN E7 IOSTANDARD LVCMOS33 } [get_ports { jc[4] }]; #IO_L6P_T0_35 Sch=jc[7] +#set_property -dict { PACKAGE_PIN J3 IOSTANDARD LVCMOS33 } [get_ports { jc[5] }]; #IO_L22P_T3_35 Sch=jc[8] +#set_property -dict { PACKAGE_PIN J4 IOSTANDARD LVCMOS33 } [get_ports { jc[6] }]; #IO_L21P_T3_DQS_35 Sch=jc[9] +#set_property -dict { PACKAGE_PIN E6 IOSTANDARD LVCMOS33 } [get_ports { jc[7] }]; #IO_L5P_T0_AD13P_35 Sch=jc[10] + + +##Pmod Header JD + +#set_property -dict { PACKAGE_PIN H4 IOSTANDARD LVCMOS33 } [get_ports { jd[0] }]; #IO_L21N_T3_DQS_35 Sch=jd[1] +#set_property -dict { PACKAGE_PIN H1 IOSTANDARD LVCMOS33 } [get_ports { jd[1] }]; #IO_L17P_T2_35 Sch=jd[2] +#set_property -dict { PACKAGE_PIN G1 IOSTANDARD LVCMOS33 } [get_ports { jd[2] }]; #IO_L17N_T2_35 Sch=jd[3] +#set_property -dict { PACKAGE_PIN G3 IOSTANDARD LVCMOS33 } [get_ports { jd[3] }]; #IO_L20N_T3_35 Sch=jd[4] +#set_property -dict { PACKAGE_PIN H2 IOSTANDARD LVCMOS33 } [get_ports { jd[4] }]; #IO_L15P_T2_DQS_35 Sch=jd[7] +#set_property -dict { PACKAGE_PIN G4 IOSTANDARD LVCMOS33 } [get_ports { jd[5] }]; #IO_L20P_T3_35 Sch=jd[8] +#set_property -dict { PACKAGE_PIN G2 IOSTANDARD LVCMOS33 } [get_ports { jd[6] }]; #IO_L15N_T2_DQS_35 Sch=jd[9] +#set_property -dict { PACKAGE_PIN F3 IOSTANDARD LVCMOS33 } [get_ports { jd[7] }]; #IO_L13N_T2_MRCC_35 Sch=jd[10] + + +##Pmod Header JXADC + +#set_property -dict { PACKAGE_PIN A14 IOSTANDARD LVDS } [get_ports { xa_n[0] }]; #IO_L9N_T1_DQS_AD3N_15 Sch=xa_n[1] +#set_property -dict { PACKAGE_PIN A13 IOSTANDARD LVDS } [get_ports { xa_p[0] }]; #IO_L9P_T1_DQS_AD3P_15 Sch=xa_p[1] +#set_property -dict { PACKAGE_PIN A16 IOSTANDARD LVDS } [get_ports { xa_n[1] }]; #IO_L8N_T1_AD10N_15 Sch=xa_n[2] +#set_property -dict { PACKAGE_PIN A15 IOSTANDARD LVDS } [get_ports { xa_p[1] }]; #IO_L8P_T1_AD10P_15 Sch=xa_p[2] +#set_property -dict { PACKAGE_PIN B17 IOSTANDARD LVDS } [get_ports { xa_n[2] }]; #IO_L7N_T1_AD2N_15 Sch=xa_n[3] +#set_property -dict { PACKAGE_PIN B16 IOSTANDARD LVDS } [get_ports { xa_p[2] }]; #IO_L7P_T1_AD2P_15 Sch=xa_p[3] +#set_property -dict { PACKAGE_PIN A18 IOSTANDARD LVDS } [get_ports { xa_n[3] }]; #IO_L10N_T1_AD11N_15 Sch=xa_n[4] +#set_property -dict { PACKAGE_PIN B18 IOSTANDARD LVDS } [get_ports { xa_p[3] }]; #IO_L10P_T1_AD11P_15 Sch=xa_p[4] + + +##VGA Connector + +#set_property -dict { PACKAGE_PIN A3 IOSTANDARD LVCMOS33 } [get_ports { vga_r[0] }]; #IO_L8N_T1_AD14N_35 Sch=vga_r[0] +#set_property -dict { PACKAGE_PIN B4 IOSTANDARD LVCMOS33 } [get_ports { vga_r[1] }]; #IO_L7N_T1_AD6N_35 Sch=vga_r[1] +#set_property -dict { PACKAGE_PIN C5 IOSTANDARD LVCMOS33 } [get_ports { vga_r[2] }]; #IO_L1N_T0_AD4N_35 Sch=vga_r[2] +#set_property -dict { PACKAGE_PIN A4 IOSTANDARD LVCMOS33 } [get_ports { vga_r[3] }]; #IO_L8P_T1_AD14P_35 Sch=vga_r[3] +# +#set_property -dict { PACKAGE_PIN C6 IOSTANDARD LVCMOS33 } [get_ports { vga_g[0] }]; #IO_L1P_T0_AD4P_35 Sch=vga_g[0] +#set_property -dict { PACKAGE_PIN A5 IOSTANDARD LVCMOS33 } [get_ports { vga_g[1] }]; #IO_L3N_T0_DQS_AD5N_35 Sch=vga_g[1] +#set_property -dict { PACKAGE_PIN B6 IOSTANDARD LVCMOS33 } [get_ports { vga_g[2] }]; #IO_L2N_T0_AD12N_35 Sch=vga_g[2] +#set_property -dict { PACKAGE_PIN A6 IOSTANDARD LVCMOS33 } [get_ports { vga_g[3] }]; #IO_L3P_T0_DQS_AD5P_35 Sch=vga_g[3] +# +#set_property -dict { PACKAGE_PIN B7 IOSTANDARD LVCMOS33 } [get_ports { vga_b[0] }]; #IO_L2P_T0_AD12P_35 Sch=vga_b[0] +#set_property -dict { PACKAGE_PIN C7 IOSTANDARD LVCMOS33 } [get_ports { vga_b[1] }]; #IO_L4N_T0_35 Sch=vga_b[1] +#set_property -dict { PACKAGE_PIN D7 IOSTANDARD LVCMOS33 } [get_ports { vga_b[2] }]; #IO_L6N_T0_VREF_35 Sch=vga_b[2] +#set_property -dict { PACKAGE_PIN D8 IOSTANDARD LVCMOS33 } [get_ports { vga_b[3] }]; #IO_L4P_T0_35 Sch=vga_b[3] + +#set_property -dict { PACKAGE_PIN B11 IOSTANDARD LVCMOS33 } [get_ports { vga_hs }]; #IO_L4P_T0_15 Sch=vga_hs +#set_property -dict { PACKAGE_PIN B12 IOSTANDARD LVCMOS33 } [get_ports { vga_vs }]; #IO_L3N_T0_DQS_AD1N_15 Sch=vga_vs + +##Micro SD Connector + +#set_property -dict { PACKAGE_PIN E2 IOSTANDARD LVCMOS33 } [get_ports { sd_reset }]; #IO_L14P_T2_SRCC_35 Sch=sd_reset +#set_property -dict { PACKAGE_PIN A1 IOSTANDARD LVCMOS33 } [get_ports { sd_cd }]; #IO_L9N_T1_DQS_AD7N_35 Sch=sd_cd +#set_property -dict { PACKAGE_PIN B1 IOSTANDARD LVCMOS33 } [get_ports { sd_sck }]; #IO_L9P_T1_DQS_AD7P_35 Sch=sd_sck +#set_property -dict { PACKAGE_PIN C1 IOSTANDARD LVCMOS33 } [get_ports { sd_cmd }]; #IO_L16N_T2_35 Sch=sd_cmd +#set_property -dict { PACKAGE_PIN C2 IOSTANDARD LVCMOS33 } [get_ports { sd_dat[0] }]; #IO_L16P_T2_35 Sch=sd_dat[0] +#set_property -dict { PACKAGE_PIN E1 IOSTANDARD LVCMOS33 } [get_ports { sd_dat[1] }]; #IO_L18N_T2_35 Sch=sd_dat[1] +#set_property -dict { PACKAGE_PIN F1 IOSTANDARD LVCMOS33 } [get_ports { sd_dat[2] }]; #IO_L18P_T2_35 Sch=sd_dat[2] +#set_property -dict { PACKAGE_PIN D2 IOSTANDARD LVCMOS33 } [get_ports { sd_dat[3] }]; #IO_L14N_T2_SRCC_35 Sch=sd_dat[3] + + +##Accelerometer + +#set_property -dict { PACKAGE_PIN E15 IOSTANDARD LVCMOS33 } [get_ports { acl_miso }]; #IO_L11P_T1_SRCC_15 Sch=acl_miso +#set_property -dict { PACKAGE_PIN F14 IOSTANDARD LVCMOS33 } [get_ports { acl_mosi }]; #IO_L5N_T0_AD9N_15 Sch=acl_mosi +#set_property -dict { PACKAGE_PIN F15 IOSTANDARD LVCMOS33 } [get_ports { acl_sclk }]; #IO_L14P_T2_SRCC_15 Sch=acl_sclk +#set_property -dict { PACKAGE_PIN D15 IOSTANDARD LVCMOS33 } [get_ports { acl_csn }]; #IO_L12P_T1_MRCC_15 Sch=acl_csn +#set_property -dict { PACKAGE_PIN B13 IOSTANDARD LVCMOS33 } [get_ports { acl_int[1] }]; #IO_L2P_T0_AD8P_15 Sch=acl_int[1] +#set_property -dict { PACKAGE_PIN C16 IOSTANDARD LVCMOS33 } [get_ports { acl_int[2] }]; #IO_L20P_T3_A20_15 Sch=acl_int[2] + + +##Temperature Sensor + +#set_property -dict { PACKAGE_PIN C14 IOSTANDARD LVCMOS33 } [get_ports { tmp_scl }]; #IO_L1N_T0_AD0N_15 Sch=tmp_scl +#set_property -dict { PACKAGE_PIN C15 IOSTANDARD LVCMOS33 } [get_ports { tmp_sda }]; #IO_L12N_T1_MRCC_15 Sch=tmp_sda +#set_property -dict { PACKAGE_PIN D13 IOSTANDARD LVCMOS33 } [get_ports { tmp_int }]; #IO_L6N_T0_VREF_15 Sch=tmp_int +#set_property -dict { PACKAGE_PIN B14 IOSTANDARD LVCMOS33 } [get_ports { tmp_ct }]; #IO_L2N_T0_AD8N_15 Sch=tmp_ct + +##Omnidirectional Microphone + +#set_property -dict { PACKAGE_PIN J5 IOSTANDARD LVCMOS33 } [get_ports { m_clk }]; #IO_25_35 Sch=m_clk +#set_property -dict { PACKAGE_PIN H5 IOSTANDARD LVCMOS33 } [get_ports { m_data }]; #IO_L24N_T3_35 Sch=m_data +#set_property -dict { PACKAGE_PIN F5 IOSTANDARD LVCMOS33 } [get_ports { m_lrsel }]; #IO_0_35 Sch=m_lrsel + + +##PWM Audio Amplifier + +#set_property -dict { PACKAGE_PIN A11 IOSTANDARD LVCMOS33 } [get_ports { aud_pwm }]; #IO_L4N_T0_15 Sch=aud_pwm +#set_property -dict { PACKAGE_PIN D12 IOSTANDARD LVCMOS33 } [get_ports { aud_sd }]; #IO_L6P_T0_15 Sch=aud_sd + + +##USB-RS232 Interface + +set_property -dict { PACKAGE_PIN C4 IOSTANDARD LVCMOS33 } [get_ports { uart_txd_in }]; #IO_L7P_T1_AD6P_35 Sch=uart_txd_in +set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { uart_rxd_out }]; #IO_L11N_T1_SRCC_35 Sch=uart_rxd_out +#set_property -dict { PACKAGE_PIN D3 IOSTANDARD LVCMOS33 } [get_ports { uart_cts }]; #IO_L12N_T1_MRCC_35 Sch=uart_cts +#set_property -dict { PACKAGE_PIN E5 IOSTANDARD LVCMOS33 } [get_ports { uart_rts }]; #IO_L5N_T0_AD13N_35 Sch=uart_rts + +##USB HID (PS/2) + +#set_property -dict { PACKAGE_PIN F4 IOSTANDARD LVCMOS33 } [get_ports { ps2_clk }]; #IO_L13P_T2_MRCC_35 Sch=ps2_clk +#set_property -dict { PACKAGE_PIN B2 IOSTANDARD LVCMOS33 } [get_ports { ps2_data }]; #IO_L10N_T1_AD15N_35 Sch=ps2_data + + +##SMSC Ethernet PHY + +#set_property -dict { PACKAGE_PIN C9 IOSTANDARD LVCMOS33 } [get_ports { eth_mdc }]; #IO_L11P_T1_SRCC_16 Sch=eth_mdc +#set_property -dict { PACKAGE_PIN A9 IOSTANDARD LVCMOS33 } [get_ports { eth_mdio }]; #IO_L14N_T2_SRCC_16 Sch=eth_mdio +#set_property -dict { PACKAGE_PIN B3 IOSTANDARD LVCMOS33 } [get_ports { eth_rstn }]; #IO_L10P_T1_AD15P_35 Sch=eth_rstn +#set_property -dict { PACKAGE_PIN D9 IOSTANDARD LVCMOS33 } [get_ports { eth_crsdv }]; #IO_L6N_T0_VREF_16 Sch=eth_crs/udv +#set_property -dict { PACKAGE_PIN C10 IOSTANDARD LVCMOS33 } [get_ports { eth_rxerr }]; #IO_L13N_T2_MRCC_16 Sch=eth_rxerr +#set_property -dict { PACKAGE_PIN C11 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd[0] }]; #IO_L13P_T2_MRCC_16 Sch=eth_rxd[0] +#set_property -dict { PACKAGE_PIN D10 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd[1] }]; #IO_L19N_T3_VREF_16 Sch=eth_rxd[1] +#set_property -dict { PACKAGE_PIN B9 IOSTANDARD LVCMOS33 } [get_ports { eth_txen }]; #IO_L11N_T1_SRCC_16 Sch=eth_txen +#set_property -dict { PACKAGE_PIN A10 IOSTANDARD LVCMOS33 } [get_ports { eth_txd[0] }]; #IO_L14P_T2_SRCC_16 Sch=eth_txd[0] +#set_property -dict { PACKAGE_PIN A8 IOSTANDARD LVCMOS33 } [get_ports { eth_txd[1] }]; #IO_L12N_T1_MRCC_16 Sch=eth_txd[1] +#set_property -dict { PACKAGE_PIN D5 IOSTANDARD LVCMOS33 } [get_ports { eth_refclk }]; #IO_L11P_T1_SRCC_35 Sch=eth_refclk +#set_property -dict { PACKAGE_PIN B8 IOSTANDARD LVCMOS33 } [get_ports { eth_intn }]; #IO_L12P_T1_MRCC_16 Sch=eth_intn + + +##Quad SPI Flash + +#set_property -dict { PACKAGE_PIN K17 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[0] }]; #IO_L1P_T0_D00_MOSI_14 Sch=qspi_dq[0] +#set_property -dict { PACKAGE_PIN K18 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[1] }]; #IO_L1N_T0_D01_DIN_14 Sch=qspi_dq[1] +#set_property -dict { PACKAGE_PIN L14 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[2] }]; #IO_L2P_T0_D02_14 Sch=qspi_dq[2] +#set_property -dict { PACKAGE_PIN M14 IOSTANDARD LVCMOS33 } [get_ports { qspi_dq[3] }]; #IO_L2N_T0_D03_14 Sch=qspi_dq[3] +#set_property -dict { PACKAGE_PIN L13 IOSTANDARD LVCMOS33 } [get_ports { qspi_csn }]; #IO_L6P_T0_FCS_B_14 Sch=qspi_csn + + diff --git a/gen_ila.py b/gen_ila.py new file mode 100644 index 0000000..dc9a33c --- /dev/null +++ b/gen_ila.py @@ -0,0 +1,72 @@ +import json +from datetime import datetime +import os + +# this works by taking a template file, parsing it for hooks, and then dropping in our spicy bits of verilog in those hooks. +# might update this later to just properly instantiate an ILA for us and we do this with parameters, but +# the fundamental thing i care about is that systemverilog does not live in this file. + +fpath = 'ila.json' # will update for argv soon! + +with open(fpath, 'r') as f: + config = json.load(f) + +# make sure file is okay +assert config["probes"] +assert config["triggers"] +assert config["uart"] or config["ethernet"] # <- i have ideas hehe + +def splice(source, find, replace): + # find all instances of find in the source, and replace with replace + #assert source.count(find) == 1 + return source.replace(find, replace) + + +with open('src/ila_template.sv', 'r') as t: + ila_template = t.read() + +# add timestamp and user +timestamp = datetime.now().strftime("%d/%m/%Y %H:%M:%S") +ila_template = splice(ila_template, '@TIMESTAMP', timestamp); + +user = os.environ.get('USER', os.environ.get('USERNAME')) +ila_template = splice(ila_template, '@USER', user); + +# add trigger +trigger = [f'({trigger})' for trigger in config['triggers']] +trigger = ' || '.join(trigger) +ila_template = splice(ila_template, '@TRIGGER', trigger); + +# add concat +concat = [name for name in config['probes']] +concat = ', '.join(concat) +concat = '{' + concat + '};' +ila_template = splice(ila_template, '@CONCAT', concat); + + + +# add probes to ila module definition +probe_verilog = [] +for name, width in config['probes'].items(): + if width == 1: + probe_verilog.append(f'input wire {name},') + + else: + probe_verilog.append(f'input wire [{width-1}:0] {name},') + +probe_verilog = '\n\t'.join(probe_verilog) +ila_template = splice(ila_template, '@PROBES', probe_verilog); + +# add sample width and depth +sample_width = sum([width for name, width in config['probes'].items()]) +ila_template = splice(ila_template, '@SAMPLE_WIDTH', str(sample_width)) +ila_template = splice(ila_template, '@SAMPLE_DEPTH', str(config['sample_depth'])); + +# add UART configuration +ila_template = splice(ila_template, '@DATA_WIDTH', str(int(config['uart']['data']))); +ila_template = splice(ila_template, '@BAUDRATE', str(config['uart']['baudrate'])); +ila_template = splice(ila_template, '@CLK_FREQ_HZ', str(int(config['clock_freq']))); + +# write output file +with open('src/ila.sv', 'w') as i: + i.write(ila_template) \ No newline at end of file diff --git a/logo.py b/logo.py new file mode 100644 index 0000000..20128b1 --- /dev/null +++ b/logo.py @@ -0,0 +1,16 @@ +logo = """ + (\.-./) + / \\ + .' : '. + _.-'` ' `'-._ | Manta 0.0.1 + .-' : '-. | An In-Situ Debugging Tool for Programmable Hardware + ,'_.._ . _.._', | https://github.com/fischermoseley/manta + '` `'-. ' .-'` `' + '. : .' | fischerm@mit.edu + \_. ._/ + \ |^| + | | ; + \'.___.' / + '-....-' """ + +print(logo) \ No newline at end of file diff --git a/run_ila.py b/run_ila.py new file mode 100644 index 0000000..e342e93 --- /dev/null +++ b/run_ila.py @@ -0,0 +1,159 @@ +from sys import argv +import json +import serial +from vcd import VCDWriter +from datetime import datetime + +def check_config(config): + """Check that configuration is okay""" + assert config["probes"] + assert config["triggers"] + assert config["uart"] + +def setup_serial(ser, config): + ser.baudrate = config['uart']['baudrate'] + ser.port = config['uart']['port'] + ser.timeout = config['uart']['timeout'] + + # setup number of data bits + if config['uart']['data'] == 8: + ser.bytesize = serial.EIGHTBITS + + elif config['uart']['data'] == 7: + ser.bytesize = serial.SEVENBITS + + elif config['uart']['data'] == 6: + ser.bytesize = serial.SIXBITS + + elif config['uart']['data'] == 5: + ser.bytesize = serial.FIVEBITS + + else: + raise ValueError("Invalid number of data bits in UART configuration.") + + # setup number of stop bits + if config['uart']['stop'] == 1: + ser.stopbits = serial.STOPBITS_ONE + + elif config['uart']['stop'] == 1.5: + ser.stopbits = serial.STOPBITS_ONE_POINT_FIVE + + elif config['uart']['stop'] == 2: + ser.stopbits = serial.STOPBITS_TWO + + else: + raise ValueError("Invalid number of stop bits in UART configuration.") + + # setup parity + if config['uart']['parity'] == 'none': + ser.parity = serial.PARITY_NONE + + elif config['uart']['parity'] == 'even': + ser.parity = serial.PARITY_EVEN + + elif config['uart']['parity'] == 'odd': + ser.parity = serial.PARITY_ODD + + elif config['uart']['parity'] == 'mark': + ser.parity = serial.PARITY_MARK + + elif config['uart']['parity'] == 'space': + ser.parity = serial.PARITY_SPACE + + else: + raise ValueError("Invalid parity setting in UART configuration.") + +def part_select(data, width): + top, bottom = width + + assert top >= bottom + + mask = 2**(top - bottom + 1) - 1 + return (data >> bottom) & mask + +def make_widths(config): + # {probe0, probe1, probe2} + # [12, 1, 3] should produce + # [ (11,0) , (12, 12), (15,13) ] + + widths = list(config['probes'].values()) + + parts = [] + for i, width in enumerate(widths): + if (i == 0): + parts.append( (width - 1, 0) ) + + else: + parts.append( ((parts[i-1][1] + width) , (parts[i-1][1] + 1)) ) + + # reversing this list is a little bit of a hack, should fix/document + return parts[::-1] + + +## Main Program + +# parse args +if len(argv) == 1 or argv[1] == '-h': + print(""" + run_ila.py: interface with the ILA on the FPGA, setting triggers and downlinking waveform data. + usage: python3 run_ila.py [config input file] [vcd output file] + options: + -h: print this help menu + -l: list all available serial devices + + example: python3 run_ila.py ila.json ila.vcd + """) + exit() + +elif argv[1] == '-l': + import serial.tools.list_ports + + for info in serial.tools.list_ports.comports(): + print(info) + +elif len(argv) == 2: + config_fpath = argv[1] + vcd_fpath = 'ila.vcd' + + +elif len(argv) == 3: + config_fpath = argv[1] + vcd_fpath = argv[2] + +else: + exit() + +# read config +with open(config_fpath, 'r') as f: + config = json.load(f) + +# obtain bytestream from FPGA +with serial.Serial() as ser: + setup_serial(ser, config) + ser.open() + ser.flushInput() + ser.write(b'\x30') + data = ser.read(4096) + +# export VCD +vcd_file = open(vcd_fpath, 'w') +timestamp = datetime.now().strftime("%d/%m/%Y %H:%M:%S") + +with VCDWriter(vcd_file, timescale='10 ns', date=timestamp, version = 'openILA') as writer: + + # add probes to vcd file + vcd_probes = [] + for name, width in config['probes'].items(): + probe = writer.register_var('ila', name, 'wire', size = width) + vcd_probes.append(probe) + + # calculate bit widths for part selecting + widths = make_widths(config) + + # slice data, and dump to vcd file + for timestamp, value in enumerate(data): + for probe_num, probe in enumerate(vcd_probes): + val = part_select(value, widths[probe_num]) + writer.change(probe, timestamp, val) + +vcd_file.close() \ No newline at end of file diff --git a/src/fifo.sv b/src/fifo.sv new file mode 100644 index 0000000..2cd3ceb --- /dev/null +++ b/src/fifo.sv @@ -0,0 +1,84 @@ +`default_nettype none +`timescale 1ns / 1ps + +module fifo ( + input wire clk, + input wire rst, + + input wire [WIDTH - 1:0] data_in, + input wire input_ready, + + input wire request_output, + output logic [WIDTH - 1:0] data_out, + output logic output_valid, + + output logic [AW:0] size, + output logic empty, + output logic full + ); + + parameter WIDTH = 8; + parameter DEPTH = 4096; + localparam AW = $clog2(DEPTH); + + logic [AW:0] write_pointer; + logic [AW:0] read_pointer; + + logic empty_int; + assign empty_int = (write_pointer[AW] == read_pointer[AW]); + + logic full_or_empty; + assign full_or_empty = (write_pointer[AW-1:0] == read_pointer[AW-1:0]); + + assign full = full_or_empty & !empty_int; + assign empty = full_or_empty & empty_int; + assign size = write_pointer - read_pointer; + + logic output_valid_pip_0; + logic output_valid_pip_1; + + always @(posedge clk) begin + if (input_ready && ~full) + write_pointer <= write_pointer + 1'd1; + + if (request_output && ~empty) + read_pointer <= read_pointer + 1'd1; + output_valid_pip_0 <= request_output; + output_valid_pip_1 <= output_valid_pip_0; + output_valid <= output_valid_pip_1; + + if (rst) begin + read_pointer <= 0; + write_pointer <= 0; + end + end + + xilinx_true_dual_port_read_first_2_clock_ram #( + .RAM_WIDTH(WIDTH), + .RAM_DEPTH(DEPTH), + .RAM_PERFORMANCE("HIGH_PERFORMANCE") + + ) buffer ( + + // write port + .clka(clk), + .rsta(rst), + .ena(1), + .addra(write_pointer), + .dina(data_in), + .wea(input_ready), + .regcea(1), + .douta(), + + // read port + .clkb(clk), + .rstb(rst), + .enb(1), + .addrb(read_pointer), + .dinb(), + .web(0), + .regceb(1), + .doutb(data_out)); + endmodule + +`default_nettype wire diff --git a/src/ila_template.sv b/src/ila_template.sv new file mode 100644 index 0000000..ee3b701 --- /dev/null +++ b/src/ila_template.sv @@ -0,0 +1,224 @@ +`default_nettype none +`timescale 1ns / 1ps + +/* +This ILA was autogenerated on @TIMESTAMP by @USER + +If this breaks or if you've got dank formal verification memes, +please contact fischerm [at] mit.edu. +*/ + +`define IDLE 0 +`define ARM 1 +`define FILL 2 +`define DOWNLINK 3 + +`define ARM_BYTE 8'b00110000 + +module ila ( + input wire clk, + input wire rst, + + /* Begin autogenerated probe definitions */ + @PROBES + /* End autogenerated probe definitions */ + + input wire rxd, + output logic txd); + + /* Begin autogenerated parameters */ + localparam SAMPLE_WIDTH = @SAMPLE_WIDTH; + localparam SAMPLE_DEPTH = @SAMPLE_DEPTH; + + localparam DATA_WIDTH = @DATA_WIDTH; + localparam BAUDRATE = @BAUDRATE; + localparam CLK_FREQ_HZ = @CLK_FREQ_HZ; + + logic trigger; + assign trigger = @TRIGGER; + + logic [SAMPLE_WIDTH - 1 : 0] concat; + assign concat = @CONCAT; + /* End autogenerated parameters */ + + + // FIFO + logic [7:0] fifo_data_in; + logic fifo_input_ready; + + logic fifo_request_output; + logic [7:0] fifo_data_out; + logic fifo_output_valid; + + logic [11:0] fifo_size; + logic fifo_empty; + logic fifo_full; + + fifo #( + .WIDTH(SAMPLE_WIDTH), + .DEPTH(SAMPLE_DEPTH) + ) fifo ( + .clk(clk), + .rst(rst), + + .data_in(fifo_data_in), + .input_ready(fifo_input_ready), + + .request_output(fifo_request_output), + .data_out(fifo_data_out), + .output_valid(fifo_output_valid), + + .size(fifo_size), + .empty(fifo_empty), + .full(fifo_full)); + + // Serial interface + logic tx_start; + logic [7:0] tx_data; + logic tx_busy; + + logic [7:0] rx_data; + logic rx_ready; + logic rx_busy; + + + uart_tx #( + .DATA_WIDTH(DATA_WIDTH), + .CLK_FREQ_HZ(CLK_FREQ_HZ), + .BAUDRATE(BAUDRATE)) + tx ( + .clk(clk), + .rst(rst), + .start(tx_start), + .data(tx_data), + + .busy(tx_busy), + .txd(txd)); + + uart_rx #( + .DATA_WIDTH(DATA_WIDTH), + .CLK_FREQ_HZ(CLK_FREQ_HZ), + .BAUDRATE(BAUDRATE)) + rx ( + .clk(clk), + .rst(rst), + .rxd(rxd), + + .data(rx_data), + .ready(rx_ready), + .busy(rx_busy)); + + + /* State Machine */ + /* + + IDLE: + - literally nothing is happening. the FIFO isn't being written to or read from. it should be empty. + - an arm command over serial is what brings us into the ARM state + + ARM: + - popping things onto FIFO. if the fifo is halfway full, we pop them off too. + - meeting the trigger condition is what moves us into the filing state + + FILL: + - popping things onto FIFO, until it's full. once it is full, we move into the downlinking state + + DOWNLINK: + - popping thing off of the FIFO until it's empty. once it's empty, we move back into the IDLE state + */ + + /* Downlink State Machine Controller */ + /* + + - ila enters the downlink state + - set fifo_output_request high for a clock cycle + - when fifo_output_valid goes high, send fifo_data_out across the line + - do nothing until tx_busy goes low + - goto step 2 + + */ + + logic [1:0] state; + logic [2:0] downlink_fsm_state; + + always_ff @(posedge clk) begin + if(rst) begin + state <= `IDLE; + downlink_fsm_state <= 0; + tx_data <= 0; + tx_start <= 0; + end + else begin + + case (state) + `IDLE : begin + fifo_input_ready <= 0; + fifo_request_output <= 0; + + if (rx_ready && rx_data == `ARM_BYTE) state <= `ARM; + + end + + `ARM : begin + // place samples into FIFO + fifo_input_ready <= 1; + fifo_data_in <= concat; + + // remove old samples if we're more than halfway full + fifo_request_output <= (fifo_size >= SAMPLE_DEPTH / 2); + + if(trigger) state <= `FILL; + end + + `FILL : begin + // place samples into FIFO + fifo_input_ready <= 1; + fifo_data_in <= concat; + + // don't pop anything out the FIFO + fifo_request_output <= 0; + + if(fifo_size == SAMPLE_DEPTH - 1) state <= `DOWNLINK; + end + + `DOWNLINK : begin + // place no samples into FIFO + fifo_input_ready <= 0; + + + case (downlink_fsm_state) + 0 : begin + if (~fifo_empty) begin + fifo_request_output <= 1; + downlink_fsm_state <= 1; + end + + else state <= `IDLE; + end + + 1 : begin + fifo_request_output <= 0; + + if (fifo_output_valid) begin + tx_data <= fifo_data_out; + tx_start <= 1; + downlink_fsm_state <= 2; + end + end + + 2 : begin + tx_start <= 0; + + if (~tx_busy && ~tx_start) downlink_fsm_state <= 0; + end + endcase + + end + endcase + end + end + +endmodule + + +`default_nettype wire \ No newline at end of file diff --git a/src/uart_rx.sv b/src/uart_rx.sv new file mode 100644 index 0000000..420959f --- /dev/null +++ b/src/uart_rx.sv @@ -0,0 +1,72 @@ +`default_nettype none +`timescale 1ns / 1ps + +module uart_rx( + input wire clk, + input wire rst, + input wire rxd, + + output logic [DATA_WIDTH - 1:0] data, + output logic ready, + output logic busy + ); + + // Just going to stick to 8N1 for now, we'll come back and + // parameterize this later. + + parameter DATA_WIDTH = 8; + parameter CLK_FREQ_HZ = 100_000_000; + parameter BAUDRATE = 115200; + + localparam PRESCALER = CLK_FREQ_HZ / BAUDRATE; + + logic [$clog2(PRESCALER) - 1:0] baud_counter; + logic [$clog2(DATA_WIDTH + 2):0] bit_index; + logic [DATA_WIDTH + 2 : 0] data_buf; + + logic prev_rxd; + + always_ff @(posedge clk) begin + prev_rxd <= rxd; + ready <= 0; + baud_counter <= (baud_counter == PRESCALER - 1) ? 0 : baud_counter + 1; + + // reset logic + if(rst) begin + bit_index <= 0; + data <= 0; + busy <= 0; + baud_counter <= 0; + end + + // start receiving if we see a falling edge, and not already busy + else if (prev_rxd && ~rxd && ~busy) begin + busy <= 1; + data_buf <= 0; + baud_counter <= 0; + end + + // if we're actually receiving + else if (busy) begin + if (baud_counter == PRESCALER / 2) begin + data_buf[bit_index] <= rxd; + bit_index <= bit_index + 1; + + if (bit_index == DATA_WIDTH + 1) begin + busy <= 0; + bit_index <= 0; + + + if (rxd && ~data_buf[0]) begin + data <= data_buf[DATA_WIDTH : 1]; + ready <= 1; + end + end + end + end + end + + +endmodule + +`default_nettype wire \ No newline at end of file diff --git a/src/uart_tx.sv b/src/uart_tx.sv new file mode 100644 index 0000000..cdc921f --- /dev/null +++ b/src/uart_tx.sv @@ -0,0 +1,81 @@ +`default_nettype none +`timescale 1ns / 1ps + + +module uart_tx( + input wire clk, + input wire rst, + input wire [DATA_WIDTH-1:0] data, + input wire start, + + output logic busy, + output logic txd + ); + + // Just going to stick to 8N1 for now, we'll come back and + // parameterize this later. + + parameter DATA_WIDTH = 8; + parameter CLK_FREQ_HZ = 100_000_000; + parameter BAUDRATE = 115200; + + localparam PRESCALER = CLK_FREQ_HZ / BAUDRATE; + + logic [$clog2(PRESCALER) - 1:0] baud_counter; + logic [$clog2(DATA_WIDTH + 2):0] bit_index; + logic [DATA_WIDTH - 1:0] data_buf; + + // make secondary logic for baudrate + always_ff @(posedge clk) begin + if(rst) baud_counter <= 0; + else begin + baud_counter <= (baud_counter == PRESCALER - 1) ? 0 : baud_counter + 1; + end + end + + always_ff @(posedge clk) begin + + // reset logic + if(rst) begin + bit_index <= 0; + busy <= 0; + txd <= 1; // idle high + end + + // enter transmitting state logic + // don't allow new requests to interrupt current + // transfers + if(start && ~busy) begin + busy <= 1; + data_buf <= data; + end + + + // transmitting state logic + else if(baud_counter == 0 && busy) begin + + if (bit_index == 0) begin + txd <= 0; + bit_index <= bit_index + 1; + end + + else if ((bit_index < DATA_WIDTH + 1) && (bit_index > 0)) begin + txd <= data_buf[bit_index - 1]; + bit_index <= bit_index + 1; + end + + else if (bit_index == DATA_WIDTH + 1) begin + txd <= 1; + bit_index <= bit_index + 1; + end + + else if (bit_index >= DATA_WIDTH + 1) begin + busy <= 0; + bit_index <= 0; + end + end + end +endmodule + + +`default_nettype wire diff --git a/src/xilinx_true_dual_port_read_first_2_clock_ram.v b/src/xilinx_true_dual_port_read_first_2_clock_ram.v new file mode 100644 index 0000000..7e975e5 --- /dev/null +++ b/src/xilinx_true_dual_port_read_first_2_clock_ram.v @@ -0,0 +1,149 @@ + +// Xilinx True Dual Port RAM, Read First, Dual Clock +// This code implements a parameterizable true dual port memory (both ports can read and write). +// The behavior of this RAM is when data is written, the prior memory contents at the write +// address are presented on the output port. If the output data is +// not needed during writes or the last read value is desired to be retained, +// it is suggested to use a no change RAM as it is more power efficient. +// If a reset or enable is not necessary, it may be tied off or removed from the code. + +module xilinx_true_dual_port_read_first_2_clock_ram #( + parameter RAM_WIDTH = 18, // Specify RAM data width + parameter RAM_DEPTH = 1024, // Specify RAM depth (number of entries) + parameter RAM_PERFORMANCE = "HIGH_PERFORMANCE", // Select "HIGH_PERFORMANCE" or "LOW_LATENCY" + parameter INIT_FILE = "" // Specify name/location of RAM initialization file if using one (leave blank if not) +) ( + input [clogb2(RAM_DEPTH-1)-1:0] addra, // Port A address bus, width determined from RAM_DEPTH + input [clogb2(RAM_DEPTH-1)-1:0] addrb, // Port B address bus, width determined from RAM_DEPTH + input [RAM_WIDTH-1:0] dina, // Port A RAM input data + input [RAM_WIDTH-1:0] dinb, // Port B RAM input data + input clka, // Port A clock + input clkb, // Port B clock + input wea, // Port A write enable + input web, // Port B write enable + input ena, // Port A RAM Enable, for additional power savings, disable port when not in use + input enb, // Port B RAM Enable, for additional power savings, disable port when not in use + input rsta, // Port A output reset (does not affect memory contents) + input rstb, // Port B output reset (does not affect memory contents) + input regcea, // Port A output register enable + input regceb, // Port B output register enable + output [RAM_WIDTH-1:0] douta, // Port A RAM output data + output [RAM_WIDTH-1:0] doutb // Port B RAM output data +); + + reg [RAM_WIDTH-1:0] BRAM [RAM_DEPTH-1:0]; + reg [RAM_WIDTH-1:0] ram_data_a = {RAM_WIDTH{1'b0}}; + reg [RAM_WIDTH-1:0] ram_data_b = {RAM_WIDTH{1'b0}}; + + //this loop below allows for rendering with iverilog simulations! + /* + integer idx; + for(idx = 0; idx < RAM_DEPTH; idx = idx+1) begin: cats + wire [RAM_WIDTH-1:0] tmp; + assign tmp = BRAM[idx]; + end + */ + + // The following code either initializes the memory values to a specified file or to all zeros to match hardware + generate + if (INIT_FILE != "") begin: use_init_file + initial + $readmemh(INIT_FILE, BRAM, 0, RAM_DEPTH-1); + end else begin: init_bram_to_zero + integer ram_index; + initial + for (ram_index = 0; ram_index < RAM_DEPTH; ram_index = ram_index + 1) + BRAM[ram_index] = {RAM_WIDTH{1'b0}}; + end + endgenerate + integer idx; + // initial begin + // for (idx = 0; idx < RAM_DEPTH; idx = idx + 1) begin + // $dumpvars(0, BRAM[idx]); + // end + // end + always @(posedge clka) + if (ena) begin + if (wea) + BRAM[addra] <= dina; + ram_data_a <= BRAM[addra]; + end + + always @(posedge clkb) + if (enb) begin + if (web) + BRAM[addrb] <= dinb; + ram_data_b <= BRAM[addrb]; + end + + // The following code generates HIGH_PERFORMANCE (use output register) or LOW_LATENCY (no output register) + generate + if (RAM_PERFORMANCE == "LOW_LATENCY") begin: no_output_register + + // The following is a 1 clock cycle read latency at the cost of a longer clock-to-out timing + assign douta = ram_data_a; + assign doutb = ram_data_b; + + end else begin: output_register + + // The following is a 2 clock cycle read latency with improve clock-to-out timing + + reg [RAM_WIDTH-1:0] douta_reg = {RAM_WIDTH{1'b0}}; + reg [RAM_WIDTH-1:0] doutb_reg = {RAM_WIDTH{1'b0}}; + + always @(posedge clka) + if (rsta) + douta_reg <= {RAM_WIDTH{1'b0}}; + else if (regcea) + douta_reg <= ram_data_a; + + always @(posedge clkb) + if (rstb) + doutb_reg <= {RAM_WIDTH{1'b0}}; + else if (regceb) + doutb_reg <= ram_data_b; + + assign douta = douta_reg; + assign doutb = doutb_reg; + + end + endgenerate + + // The following function calculates the address width based on specified RAM depth + function integer clogb2; + input integer depth; + for (clogb2=0; depth>0; clogb2=clogb2+1) + depth = depth >> 1; + endfunction + +endmodule + +// The following is an instantiation template for xilinx_true_dual_port_read_first_2_clock_ram +/* + // Xilinx True Dual Port RAM, Read First, Dual Clock + xilinx_true_dual_port_read_first_2_clock_ram #( + .RAM_WIDTH(18), // Specify RAM data width + .RAM_DEPTH(1024), // Specify RAM depth (number of entries) + .RAM_PERFORMANCE("HIGH_PERFORMANCE"), // Select "HIGH_PERFORMANCE" or "LOW_LATENCY" + .INIT_FILE("") // Specify name/location of RAM initialization file if using one (leave blank if not) + ) your_instance_name ( + .addra(addra), // Port A address bus, width determined from RAM_DEPTH + .addrb(addrb), // Port B address bus, width determined from RAM_DEPTH + .dina(dina), // Port A RAM input data, width determined from RAM_WIDTH + .dinb(dinb), // Port B RAM input data, width determined from RAM_WIDTH + .clka(clka), // Port A clock + .clkb(clkb), // Port B clock + .wea(wea), // Port A write enable + .web(web), // Port B write enable + .ena(ena), // Port A RAM Enable, for additional power savings, disable port when not in use + .enb(enb), // Port B RAM Enable, for additional power savings, disable port when not in use + .rsta(rsta), // Port A output reset (does not affect memory contents) + .rstb(rstb), // Port B output reset (does not affect memory contents) + .regcea(regcea), // Port A output register enable + .regceb(regceb), // Port B output register enable + .douta(douta), // Port A RAM output data, width determined from RAM_WIDTH + .doutb(doutb) // Port B RAM output data, width determined from RAM_WIDTH + ); +*/ + + diff --git a/test/fifo_tb.sv b/test/fifo_tb.sv new file mode 100644 index 0000000..18f74f0 --- /dev/null +++ b/test/fifo_tb.sv @@ -0,0 +1,71 @@ +`default_nettype none + +`timescale 1ns / 1ps + +module fifo_tb(); + logic clk; + logic rst; + + logic [7:0] data_in; + logic input_ready; + + logic request_output; + logic [7:0] data_out; + + logic [11:0] size; + logic empty; + logic full; + + fifo uut ( + .clk(clk), + .rst(rst), + + .data_in(data_in), + .input_ready(input_ready), + + .request_output(request_output), + .data_out(data_out), + + .size(size), + .empty(empty), + .full(full)); + + always begin + #5; + clk = !clk; + end + + initial begin + $dumpfile("fifo.vcd"); + $dumpvars(0, fifo_tb); + clk = 0; + rst = 1; + data_in = 0; + input_ready = 0; + request_output = 0; + #10; + rst = 0; + #10; + + // try and load some data, make sure counter increases + input_ready = 1; + + for(int i=0; i < 4097; i++) begin + data_in = i; + #10; + end + + input_ready = 0; + + // try and read out said data + request_output = 1; + for(int i=0; i < 4097; i++) begin + $display("%h", data_out); + #10; + end + + $finish(); + end +endmodule + +`default_nettype wire diff --git a/test/ila_tb.sv b/test/ila_tb.sv new file mode 100644 index 0000000..6d55862 --- /dev/null +++ b/test/ila_tb.sv @@ -0,0 +1,69 @@ +`default_nettype none +`timescale 1ns / 1ps + +module ila_tb(); + logic clk; + logic rst; + logic rxd; + logic txd; + + + logic probe0, probe1, probe2; + assign probe0 = count[0]; + assign probe1 = count[1]; + assign probe2 = count[2]; + + // ILA + // later make this a `ILA that gets loaded from a svh file that the python script generates + ila #(.FIFO_DEPTH(64)) ila( + .clk(clk), + .rst(rst), + .probe0(probe0), + .probe1(probe1), + .probe2(probe2), + + .rxd(rxd), + .txd(txd)); + + /* Signal Generator */ + logic [7:0] count = 0; + always begin + count = count + 1; + #10; + end + + always begin + #5; + clk = !clk; + end + + logic [9:0] uart_data; + + initial begin + $dumpfile("ila.vcd"); + $dumpvars(0, ila_tb); + clk = 0; + rst = 1; + rxd = 1; + uart_data = 0; + #10; + rst = 0; + + // Wait a little bit to make sure that it doesn't like, explode or something + #1000; + + // send arm byte! + uart_data = {1'b1, 8'b00110000, 1'b0}; + for (int i=0; i < 10; i++) begin + rxd = uart_data[i]; + #8680; + end + + // see what happens lmao + #15000000; + + $finish(); + end +endmodule + +`default_nettype wire diff --git a/test/uart_tb.sv b/test/uart_tb.sv new file mode 100644 index 0000000..d0329df --- /dev/null +++ b/test/uart_tb.sv @@ -0,0 +1,72 @@ +`default_nettype none + +`timescale 1ns / 1ps + +module uart_tb(); + logic clk; + logic rst; + logic [7:0] tx_data, rx_data; + logic tx_start, rx_ready; + logic tx_busy, rx_busy; + logic txd; + + + uart_tx #( + .DATA_WIDTH(8), + .CLK_FREQ_HZ(100_000_000), + .BAUDRATE(115200)) + tx ( + .clk(clk), + .rst(rst), + .data(tx_data), + .start(tx_start), + + .busy(tx_busy), + .txd(txd)); + + + uart_rx #( + .DATA_WIDTH(8), + .CLK_FREQ_HZ(100_000_000), + .BAUDRATE(115200)) + rx ( + .clk(clk), + .rst(rst), + .rxd(txd), + + .data(rx_data), + .ready(rx_ready), + .busy(rx_busy)); + + always begin + #5; + clk = !clk; + end + + initial begin + $dumpfile("uart.vcd"); + $dumpvars(0, uart_tb); + clk = 0; + rst = 1; + tx_data = 'h0F; + tx_start = 0; + #10; + rst = 0; + #10; + tx_start = 1; + #10; + tx_start = 0; + #150000; + + // send another byte! + tx_data = 'hBE; + tx_start = 1; + #10; + tx_start = 0; + #150000; + + $finish(); + end +endmodule + +`default_nettype wire diff --git a/test/uart_tx_tb.sv b/test/uart_tx_tb.sv new file mode 100644 index 0000000..f81cb2b --- /dev/null +++ b/test/uart_tx_tb.sv @@ -0,0 +1,50 @@ +`default_nettype none + +`timescale 1ns / 1ps + +module uart_tx_tb(); + logic clk; + logic rst; + logic [7:0] data; + logic start; + logic busy; + logic txd; + + + uart_tx #( + .DATA_WIDTH(8), + .CLK_FREQ_HZ(100_000_000), + .BAUDRATE(115200)) + uut ( + .clk(clk), + .rst(rst), + .data(data), + .start(start), + + .busy(busy), + .txd(txd)); + + always begin + #5; + clk = !clk; + end + + initial begin + $dumpfile("uart_tx.vcd"); + $dumpvars(0, uart_tx_tb); + clk = 0; + rst = 1; + start = 0; + #10; + rst = 0; + data = 'h0F; + #10; + start = 1; + #10; + start = 0; + #150000; + $finish(); + end +endmodule + +`default_nettype wire