diff --git a/examples/nexys_a7/logic_analyzer/lab-bc.py b/examples/nexys_a7/logic_analyzer/lab-bc.py new file mode 100644 index 0000000..d651852 --- /dev/null +++ b/examples/nexys_a7/logic_analyzer/lab-bc.py @@ -0,0 +1,301 @@ +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/nexys_a7/logic_analyzer/run_logic_analyzer.py b/examples/nexys_a7/logic_analyzer/run_logic_analyzer.py new file mode 100644 index 0000000..594b196 --- /dev/null +++ b/examples/nexys_a7/logic_analyzer/run_logic_analyzer.py @@ -0,0 +1,22 @@ +from manta import Manta + +m = Manta('manta.yaml') + +# setup trigger to trigger when moe = 1: +m.my_logic_analyzer.interface.write_register(0, 0) # set state to IDLE +m.my_logic_analyzer.interface.write_register(6, 8) # set operation to eq +m.my_logic_analyzer.interface.write_register(7, 1) # set argument to 1 + +# read that back +print(m.my_logic_analyzer.interface.read_register(0)) +print(m.my_logic_analyzer.interface.read_register(6)) +print(m.my_logic_analyzer.interface.read_register(7)) + +# start the capture +m.my_logic_analyzer.interface.write_register(0, 1) # set state to START_CAPTURE +print(m.my_logic_analyzer.interface.read_register(0)) + +# display sample data +for i in range(128): + data = m.my_logic_analyzer.interface.read_register(i) + print(f"addr: {i} data: {data}") \ No newline at end of file diff --git a/examples/nexys_a7/logic_analyzer/src/manta.v b/examples/nexys_a7/logic_analyzer/src/manta.v index eda13af..8e1648d 100644 --- a/examples/nexys_a7/logic_analyzer/src/manta.v +++ b/examples/nexys_a7/logic_analyzer/src/manta.v @@ -2,12 +2,27 @@ `timescale 1ns/1ps /* -This manta definition was generated on 14 Mar 2023 at 13:06:49 by fischerm +This manta definition was generated on 02 Apr 2023 at 22:05:41 by fischerm If this breaks or if you've got dank formal verification memes, please contact fischerm [at] mit.edu Provided under a GNU GPLv3 license. Go wild. + +Here's an example instantiation of the Manta module you configured, +feel free to copy-paste this into your source! + +manta manta_inst ( + .clk(clk), + + .rx(rx), + .tx(tx), + + .larry(larry), + .curly(curly), + .moe(moe), + .shemp(shemp)); + */ module manta ( @@ -46,7 +61,7 @@ module manta ( reg brx_my_logic_analyzer_rw; reg brx_my_logic_analyzer_valid; - la_core my_logic_analyzer ( + logic_analyzer #(.BASE_ADDR(0), .SAMPLE_DEPTH(128)) my_logic_analyzer ( .clk(clk), .addr_i(brx_my_logic_analyzer_addr), @@ -59,7 +74,7 @@ module manta ( .curly(curly), .moe(moe), .shemp(shemp), - + .addr_o(), .wdata_o(), .rdata_o(my_logic_analyzer_btx_rdata), @@ -72,7 +87,7 @@ module manta ( bridge_tx btx ( .clk(clk), - + .rdata_i(my_logic_analyzer_btx_rdata), .rw_i(my_logic_analyzer_btx_rw), .valid_i(my_logic_analyzer_btx_valid), @@ -84,7 +99,7 @@ module manta ( logic utx_btx_ready; logic btx_utx_valid; logic [7:0] btx_utx_data; - + uart_tx #(.CLOCKS_PER_BAUD(868)) utx ( .clk(clk), @@ -350,6 +365,672 @@ endmodule +module logic_analyzer( + input wire clk, + + // probes + input wire larry, + input wire curly, + input wire moe, + input wire [3:0] shemp, + + // input port + input wire [15:0] addr_i, + input wire [15:0] wdata_i, + input wire [15:0] rdata_i, + input wire rw_i, + input wire valid_i, + + // output port + output reg [15:0] addr_o, + output reg [15:0] wdata_o, + output reg [15:0] rdata_o, + output reg rw_o, + output reg valid_o + ); + + parameter BASE_ADDR = 0; + parameter SAMPLE_DEPTH = 0; + + // fsm + la_fsm #(.BASE_ADDR(BASE_ADDR), .SAMPLE_DEPTH(SAMPLE_DEPTH)) fsm ( + .clk(clk), + + .trig(trig), + .fifo_size(fifo_size), + .fifo_acquire(fifo_acquire), + .fifo_pop(fifo_pop), + .fifo_clear(fifo_clear), + + .addr_i(addr_i), + .wdata_i(wdata_i), + .rdata_i(rdata_i), + .rw_i(rw_i), + .valid_i(valid_i), + + .addr_o(fsm_trig_blk_addr), + .wdata_o(fsm_trig_blk_wdata), + .rdata_o(fsm_trig_blk_rdata), + .rw_o(fsm_trig_blk_rw), + .valid_o(fsm_trig_blk_valid)); + + reg [15:0] fsm_trig_blk_addr; + reg [15:0] fsm_trig_blk_wdata; + reg [15:0] fsm_trig_blk_rdata; + reg fsm_trig_blk_rw; + reg fsm_trig_blk_valid; + + reg trig; + reg [$clog2(SAMPLE_DEPTH):0] fifo_size; + reg fifo_acquire; + reg fifo_pop; + reg fifo_clear; + + + // trigger block + trigger_block #(.BASE_ADDR(BASE_ADDR + 2)) trig_blk( + .clk(clk), + + .larry(larry), + .curly(curly), + .moe(moe), + .shemp(shemp), + + .trig(trig), + + .addr_i(fsm_trig_blk_addr), + .wdata_i(fsm_trig_blk_wdata), + .rdata_i(fsm_trig_blk_rdata), + .rw_i(fsm_trig_blk_rw), + .valid_i(fsm_trig_blk_valid), + + .addr_o(trig_blk_sample_mem_addr), + .wdata_o(trig_blk_sample_mem_wdata), + .rdata_o(trig_blk_sample_mem_rdata), + .rw_o(trig_blk_sample_mem_rw), + .valid_o(trig_blk_sample_mem_valid)); + + reg [15:0] trig_blk_sample_mem_addr; + reg [15:0] trig_blk_sample_mem_wdata; + reg [15:0] trig_blk_sample_mem_rdata; + reg trig_blk_sample_mem_rw; + reg trig_blk_sample_mem_valid; + + // sample memory + sample_mem #(.BASE_ADDR(BASE_ADDR + 10), .SAMPLE_DEPTH(SAMPLE_DEPTH)) sample_mem( + .clk(clk), + + // fifo + .acquire(fifo_acquire), + .pop(fifo_pop), + .size(fifo_size), + .clear(fifo_clear), + + // probes + .larry(larry), + .curly(curly), + .moe(moe), + .shemp(shemp), + + // input port + .addr_i(trig_blk_sample_mem_addr), + .wdata_i(trig_blk_sample_mem_wdata), + .rdata_i(trig_blk_sample_mem_rdata), + .rw_i(trig_blk_sample_mem_rw), + .valid_i(trig_blk_sample_mem_valid), + + // output port + .addr_o(addr_o), + .wdata_o(wdata_o), + .rdata_o(rdata_o), + .rw_o(rw_o), + .valid_o(valid_o)); +endmodule + + + + +module la_fsm( + input wire clk, + + input wire trig, + input wire [$clog2(SAMPLE_DEPTH):0] fifo_size, + output reg fifo_acquire, + output reg fifo_pop, + output reg fifo_clear, + + // input port + input wire [15:0] addr_i, + input wire [15:0] wdata_i, + input wire [15:0] rdata_i, + input wire rw_i, + input wire valid_i, + + // output port + output reg [15:0] addr_o, + output reg [15:0] wdata_o, + output reg [15:0] rdata_o, + output reg rw_o, + output reg valid_o); + + parameter BASE_ADDR = 0; + parameter SAMPLE_DEPTH = 0; + + // state machine + localparam IDLE = 0; + localparam START_CAPTURE = 1; + localparam MOVE_TO_POSITION = 2; + localparam IN_POSITION = 3; + localparam FILLING_BUFFER = 4; + localparam FILLED = 5; + + reg [3:0] state; + reg signed [15:0] trigger_loc; + reg signed [15:0] present_loc; + + initial state = IDLE; + initial trigger_loc = 0; + initial present_loc = 0; + + // perform register operations + always @(posedge clk) begin + addr_o <= addr_i; + wdata_o <= wdata_i; + rdata_o <= rdata_i; + rw_o <= rw_i; + valid_o <= valid_i; + + // check if address is valid + if( (valid_i) && (addr_i >= BASE_ADDR) && (addr_i <= BASE_ADDR + 2)) begin + + if(!rw_i) begin // reads + case (addr_i) + BASE_ADDR + 0: rdata_o <= state; + BASE_ADDR + 1: rdata_o <= trigger_loc; + BASE_ADDR + 2: rdata_o <= present_loc; + endcase + end + + else begin // writes + case (addr_i) + BASE_ADDR + 0: state <= wdata_i; + BASE_ADDR + 1: trigger_loc <= wdata_i; + BASE_ADDR + 2: present_loc <= wdata_i; + endcase + end + end +// end + + // run state machine +// always @(posedge clk) begin + if(state == IDLE) begin + present_loc <= (trigger_loc < 0) ? trigger_loc : 0; + end + + else if(state == START_CAPTURE) begin + // perform whatever setup is needed before starting the next capture + fifo_clear <= 1; + state <= MOVE_TO_POSITION; + end + + else if(state == MOVE_TO_POSITION) begin + fifo_clear <= 0; + // if trigger location is negative or zero, + // then we're already in position + if(trigger_loc <= 0) state <= IN_POSITION; + + // otherwise we'll need to wait a little, + // but we'll need to buffer along the way + else begin + present_loc <= present_loc + 1; + // add code to add samples to word FIFO + fifo_acquire <= 1; + if (present_loc == trigger_loc) state <= IN_POSITION; + end + end + + else if(state == IN_POSITION) begin + // pop stuff out of the word FIFO in addition to pulling it in + fifo_acquire <= 1; + fifo_pop <= 1; + + if(trig) state <= FILLING_BUFFER; + end + + else if(state == FILLING_BUFFER) begin + fifo_acquire <= 1; + fifo_pop <= 0; + if(fifo_size == SAMPLE_DEPTH) state <= FILLED; + end + + else if(state == FILLED) begin + // don't automatically go back to IDLE, the host will move + // the state to MOVE_TO_POSITION + + present_loc <= (trigger_loc < 0) ? trigger_loc : 0; + end + end +endmodule + + + + +module sample_mem( + input wire clk, + + // fifo + input wire acquire, + input wire pop, + output logic [BRAM_ADDR_WIDTH:0] size, + input wire clear, + + // probes + input wire larry, + input wire curly, + input wire moe, + input wire [3:0] shemp, + + // input port + input wire [15:0] addr_i, + input wire [15:0] wdata_i, + input wire [15:0] rdata_i, + input wire rw_i, + input wire valid_i, + + // output port + output reg [15:0] addr_o, + output reg [15:0] wdata_o, + output reg [15:0] rdata_o, + output reg rw_o, + output reg valid_o); + + parameter BASE_ADDR = 0; + parameter SAMPLE_DEPTH = 0; + localparam BRAM_ADDR_WIDTH = $clog2(SAMPLE_DEPTH); + + // bus controller + reg [BRAM_ADDR_WIDTH-1:0] bram_read_addr; + reg [15:0] bram_read_data; + + always @(*) begin + // if address is valid + if ( (addr_i >= BASE_ADDR) && (addr_i <= BASE_ADDR + SAMPLE_DEPTH) ) begin + + // figure out proper place to read from + // want to read from the read pointer, and then loop back around + if(read_pointer + (addr_i - BASE_ADDR) > SAMPLE_DEPTH) + bram_read_addr = read_pointer + (addr_i - BASE_ADDR) - SAMPLE_DEPTH; + + else + bram_read_addr = read_pointer + (addr_i - BASE_ADDR); + end + + else bram_read_addr = 0; + end + + + // pipeline bus to compensate for 2-cycles of delay in BRAM + reg [15:0] addr_pip; + reg [15:0] wdata_pip; + reg [15:0] rdata_pip; + reg rw_pip; + reg valid_pip; + + always @(posedge clk) begin + addr_pip <= addr_i; + wdata_pip <= wdata_i; + rdata_pip <= rdata_i; + rw_pip <= rw_i; + valid_pip <= valid_i; + + addr_o <= addr_pip; + wdata_o <= wdata_pip; + rdata_o <= rdata_pip; + rw_o <= rw_pip; + valid_o <= valid_pip; + + if( valid_pip && !rw_pip && (addr_pip >= BASE_ADDR) && (addr_pip <= BASE_ADDR + SAMPLE_DEPTH) ) + rdata_o <= bram_read_data; + end + + + // bram + xilinx_true_dual_port_read_first_2_clock_ram #( + .RAM_WIDTH(16), + .RAM_DEPTH(SAMPLE_DEPTH), + .RAM_PERFORMANCE("HIGH_PERFORMANCE") + + ) bram ( + + // read port (controlled by bus) + .clka(clk), + .rsta(1'b0), + .ena(1'b1), + .addra(bram_read_addr), + .dina(16'b0), + .wea(1'b0), + .regcea(1'b1), + .douta(bram_read_data), + + // write port (controlled by FIFO) + .clkb(clk), + .rstb(1'b0), + .enb(1'b1), + .addrb(write_pointer[BRAM_ADDR_WIDTH-1:0]), + .dinb({9'b0, larry, curly, moe, shemp}), + .web(acquire), + .regceb(1'b1), + .doutb()); + + + // fifo + reg [BRAM_ADDR_WIDTH:0] write_pointer = 0; + reg [BRAM_ADDR_WIDTH:0] read_pointer = 0; + + assign size = write_pointer - read_pointer; + + always @(posedge clk) begin + if (clear) read_pointer <= write_pointer; + if (acquire && size < SAMPLE_DEPTH) write_pointer <= write_pointer + 1'd1; + if (pop && size > 0) read_pointer <= read_pointer + 1'd1; + end +endmodule + + +// 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. + +`default_nettype wire + +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 + + +`default_nettype none + + +module trigger_block( + input wire clk, + + // probes + input wire larry, + input wire curly, + input wire moe, + input wire [3:0] shemp, + + // trigger + output reg trig, + + // input port + input wire [15:0] addr_i, + input wire [15:0] wdata_i, + input wire [15:0] rdata_i, + input wire rw_i, + input wire valid_i, + + // output port + output reg [15:0] addr_o, + output reg [15:0] wdata_o, + output reg [15:0] rdata_o, + output reg rw_o, + output reg valid_o); + + parameter BASE_ADDR = 0; + + // trigger configuration registers + // - each probe gets an operation and a compare register + // - at the end we OR them all together. along with any custom probes the user specs + + reg [3:0] larry_trigger_op = 0; + reg larry_trigger_arg = 0; + reg larry_trig; + trigger #(.INPUT_WIDTH(1)) larry_trigger( + .clk(clk), + + .probe(larry), + .op(larry_trigger_op), + .arg(larry_trigger_arg), + .trig(larry_trig)); + + reg [3:0] curly_trigger_op = 0; + reg curly_trigger_arg = 0; + reg curly_trig; + trigger #(.INPUT_WIDTH(1)) curly_trigger( + .clk(clk), + + .probe(curly), + .op(curly_trigger_op), + .arg(curly_trigger_arg), + .trig(curly_trig)); + + + reg [3:0] moe_trigger_op = 0; + reg moe_trigger_arg = 0; + reg moe_trig; + trigger #(.INPUT_WIDTH(1)) moe_trigger( + .clk(clk), + + .probe(moe), + .op(moe_trigger_op), + .arg(moe_trigger_arg), + .trig(moe_trig)); + + reg [3:0] shemp_trigger_op = 0; + reg [3:0] shemp_trigger_arg = 0; + reg shemp_trig; + trigger #(.INPUT_WIDTH(4)) shemp_trigger( + .clk(clk), + + .probe(shemp), + .op(shemp_trigger_op), + .arg(shemp_trigger_arg), + .trig(shemp_trig)); + + assign trig = larry_trig || curly_trig || moe_trig || shemp_trig; + + // perform register operations + always @(posedge clk) begin + addr_o <= addr_i; + wdata_o <= wdata_i; + rdata_o <= rdata_i; + rw_o <= rw_i; + valid_o <= valid_i; + rdata_o <= rdata_i; + + if( (addr_i >= BASE_ADDR) && (addr_i <= BASE_ADDR + 9) ) begin + + // reads + if(valid_i && !rw_i) begin + case (addr_i) + BASE_ADDR + 0: rdata_o <= larry_trigger_op; + BASE_ADDR + 1: rdata_o <= larry_trigger_arg; + BASE_ADDR + 2: rdata_o <= curly_trigger_op; + BASE_ADDR + 3: rdata_o <= curly_trigger_arg; + BASE_ADDR + 4: rdata_o <= moe_trigger_op; + BASE_ADDR + 5: rdata_o <= moe_trigger_arg; + BASE_ADDR + 6: rdata_o <= shemp_trigger_op; + BASE_ADDR + 7: rdata_o <= shemp_trigger_arg; + endcase + end + + // writes + else if(valid_i && rw_i) begin + case (addr_i) + BASE_ADDR + 0: larry_trigger_op <= wdata_i; + BASE_ADDR + 1: larry_trigger_arg <= wdata_i; + BASE_ADDR + 2: curly_trigger_op <= wdata_i; + BASE_ADDR + 3: curly_trigger_arg <= wdata_i; + BASE_ADDR + 4: moe_trigger_op <= wdata_i; + BASE_ADDR + 5: moe_trigger_arg <= wdata_i; + BASE_ADDR + 6: shemp_trigger_op <= wdata_i; + BASE_ADDR + 7: shemp_trigger_arg <= wdata_i; + endcase + end + end + end +endmodule + + + + +module trigger( + input wire clk, + + input wire [INPUT_WIDTH-1:0] probe, + input wire [3:0] op, + input wire [INPUT_WIDTH-1:0] arg, + + output reg trig + ); + + parameter INPUT_WIDTH = 0; + + localparam DISABLE = 0; + localparam RISING = 1; + localparam FALLING = 2; + localparam CHANGING = 3; + localparam GT = 4; + localparam LT = 5; + localparam GEQ = 6; + localparam LEQ = 7; + localparam EQ = 8; + localparam NEQ = 9; + + reg [INPUT_WIDTH-1:0] probe_prev = 0; + always @(posedge clk) probe_prev <= probe; + + always @(*) begin + case (op) + RISING : trig = (probe > probe_prev); + FALLING : trig = (probe < probe_prev); + CHANGING : trig = (probe != probe_prev); + GT: trig = (probe > arg); + LT: trig = (probe < arg); + GEQ: trig = (probe >= arg); + LEQ: trig = (probe <= arg); + EQ: trig = (probe == arg); + NEQ: trig = (probe != arg); + default: trig = 0; + endcase + end +endmodule + + + + module bridge_tx( input wire clk, diff --git a/examples/nexys_a7/logic_analyzer/src/top_level.sv b/examples/nexys_a7/logic_analyzer/src/top_level.sv new file mode 100644 index 0000000..7ba8879 --- /dev/null +++ b/examples/nexys_a7/logic_analyzer/src/top_level.sv @@ -0,0 +1,33 @@ +`default_nettype none +`timescale 1ns / 1ps + +module top_level ( + input wire clk, + + input wire uart_txd_in, + output logic uart_rxd_out + ); + + logic larry = 0; + logic curly = 0; + logic moe = 0; + logic [3:0] shemp = 0; + + always_ff @(posedge clk) begin + {larry, curly, moe, shemp} <= {larry, curly, moe, shemp} + 1; + end + + manta manta_inst ( + .clk(clk), + + .rx(uart_txd_in), + .tx(uart_rxd_out), + + .larry(larry), + .curly(curly), + .moe(moe), + .shemp(shemp)); + +endmodule + +`default_nettype wire \ No newline at end of file diff --git a/examples/nexys_a7/logic_analyzer/xdc/top_level.xdc b/examples/nexys_a7/logic_analyzer/xdc/top_level.xdc new file mode 100644 index 0000000..3beee16 --- /dev/null +++ b/examples/nexys_a7/logic_analyzer/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/src/manta/__init__.py b/src/manta/__init__.py index c3fba5e..6aad6a6 100644 --- a/src/manta/__init__.py +++ b/src/manta/__init__.py @@ -448,7 +448,7 @@ class LogicAnalyzerCore: ports = "\n\t\t".join(ports) hdl = f""" - la_core {self.name} ( + logic_analyzer #(.BASE_ADDR(0), .SAMPLE_DEPTH(128)) {self.name} ( .clk(clk), .addr_i(), @@ -541,38 +541,14 @@ class LogicAnalyzerCore: def hdl_def(self): # Return an autogenerated verilog module definition for the core. # load source files - tmpl = pkgutil.get_data(__name__, "la_template.v").decode() + logic_analyzer_hdl = pkgutil.get_data(__name__, "logic_analyzer.v").decode() + la_fsm_hdl = pkgutil.get_data(__name__, "la_fsm.v").decode() + sample_mem_hdl = pkgutil.get_data(__name__, "sample_mem.v").decode() + xilinx_bram_hdl = pkgutil.get_data(__name__, "xilinx_true_dual_port_read_first_2_clock_ram.v").decode() + trigger_block_hdl= pkgutil.get_data(__name__, "trigger_block.v").decode() + trigger_hdl = pkgutil.get_data(__name__, "trigger.v").decode() - # add triggers - trigger = [f"({trigger})" for trigger in self.triggers] - trigger = " || ".join(trigger) - tmpl = tmpl.replace("@TRIGGER", trigger) - - # add concat - concat = [name for name in self.probes] - concat = ", ".join(concat) - concat = "{" + concat + "}" - tmpl = tmpl.replace("@CONCAT", concat) - - # add probes - probe_verilog = [] - for name, width in self.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\t".join(probe_verilog) - tmpl = tmpl.replace("@PROBES", probe_verilog) - - # add sample width - sample_width = sum([width for name, width in self.probes.items()]) - tmpl = tmpl.replace("@SAMPLE_WIDTH", str(sample_width)) - - # add sample depth - tmpl = tmpl.replace("@SAMPLE_DEPTH", str(self.sample_depth)) - return tmpl + return logic_analyzer_hdl + la_fsm_hdl + sample_mem_hdl + xilinx_bram_hdl + trigger_block_hdl + trigger_hdl def hdl_top_level_ports(self): # this should return the probes that we want to connect to top-level, but as a list of verilog ports @@ -736,7 +712,6 @@ If this breaks or if you've got dank formal verification memes, please contact fischerm [at] mit.edu Provided under a GNU GPLv3 license. Go wild. -*/ """ return header @@ -778,10 +753,8 @@ Provided under a GNU GPLv3 license. Go wild. ports = ports[:-1] return f""" -/* - -// Here's an example instantiation of the Manta module you configured, -// feel free to copy-paste this into your source! +Here's an example instantiation of the Manta module you configured, +feel free to copy-paste this into your source! manta manta_inst ( .clk(clk), diff --git a/src/manta/la_fsm.v b/src/manta/la_fsm.v index d2fc558..d4a6bab 100644 --- a/src/manta/la_fsm.v +++ b/src/manta/la_fsm.v @@ -70,10 +70,10 @@ module la_fsm( endcase end end - end +// end // run state machine - always @(posedge clk) begin +// always @(posedge clk) begin if(state == IDLE) begin present_loc <= (trigger_loc < 0) ? trigger_loc : 0; end diff --git a/src/manta/sample_mem.v b/src/manta/sample_mem.v index 3ac317b..d2bcee0 100644 --- a/src/manta/sample_mem.v +++ b/src/manta/sample_mem.v @@ -7,7 +7,7 @@ module sample_mem( // fifo input wire acquire, input wire pop, - output wire [BRAM_ADDR_WIDTH:0] size, + output logic [BRAM_ADDR_WIDTH:0] size, input wire clear, // probes @@ -45,13 +45,13 @@ module sample_mem( // figure out proper place to read from // want to read from the read pointer, and then loop back around if(read_pointer + (addr_i - BASE_ADDR) > SAMPLE_DEPTH) - bram_read_addr <= read_pointer + (addr_i - BASE_ADDR) - SAMPLE_DEPTH; + bram_read_addr = read_pointer + (addr_i - BASE_ADDR) - SAMPLE_DEPTH; else bram_read_addr = read_pointer + (addr_i - BASE_ADDR); end - else bram_read_addr <= 0; + else bram_read_addr = 0; end diff --git a/src/manta/trigger.v b/src/manta/trigger.v index 5c12cab..ed60b5b 100644 --- a/src/manta/trigger.v +++ b/src/manta/trigger.v @@ -24,8 +24,7 @@ module trigger( localparam EQ = 8; localparam NEQ = 9; - reg [INPUT_WIDTH-1:0] probe_prev; - initial probe_prev = probe; + reg [INPUT_WIDTH-1:0] probe_prev = 0; always @(posedge clk) probe_prev <= probe; always @(*) begin diff --git a/src/manta/xilinx_true_dual_port_read_first_2_clock_ram.v b/src/manta/xilinx_true_dual_port_read_first_2_clock_ram.v index 7e975e5..6203ee3 100644 --- a/src/manta/xilinx_true_dual_port_read_first_2_clock_ram.v +++ b/src/manta/xilinx_true_dual_port_read_first_2_clock_ram.v @@ -117,33 +117,3 @@ module xilinx_true_dual_port_read_first_2_clock_ram #( 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 - ); -*/ - -