From aa2ba43e8fe6ebb732183095c8efda7cbc31a8d4 Mon Sep 17 00:00:00 2001 From: Fischer Moseley <42497969+fischermoseley@users.noreply.github.com> Date: Tue, 14 Mar 2023 13:10:34 -0400 Subject: [PATCH] rename lut mem to lut ram, add to manta generator --- Makefile | 6 +- .../manta.yaml | 0 examples/nexys_a7/logic_analyzer/src/manta.v | 498 ++++++++++++++++++ .../block_verify.py | 0 .../{single_lut_ram => lut_ram}/lab-bc.py | 0 examples/nexys_a7/lut_ram/manta.yaml | 10 + .../{single_lut_ram => lut_ram}/src/manta.v | 144 +++-- .../{single_lut_ram => lut_ram}/src/ssd.v | 0 .../src/top_level.sv | 9 +- .../xdc/top_level.xdc | 0 src/manta/__init__.py | 88 +++- src/manta/{lut_mem.v => lut_ram.v} | 2 +- test/bus_fix_tb.sv | 4 +- test/{lut_mem_tb.sv => lut_ram_tb.sv} | 12 +- 14 files changed, 660 insertions(+), 113 deletions(-) rename examples/nexys_a7/{single_lut_ram => logic_analyzer}/manta.yaml (100%) create mode 100644 examples/nexys_a7/logic_analyzer/src/manta.v rename examples/nexys_a7/{single_lut_ram => lut_ram}/block_verify.py (100%) rename examples/nexys_a7/{single_lut_ram => lut_ram}/lab-bc.py (100%) create mode 100644 examples/nexys_a7/lut_ram/manta.yaml rename examples/nexys_a7/{single_lut_ram => lut_ram}/src/manta.v (91%) rename examples/nexys_a7/{single_lut_ram => lut_ram}/src/ssd.v (100%) rename examples/nexys_a7/{single_lut_ram => lut_ram}/src/top_level.sv (65%) rename examples/nexys_a7/{single_lut_ram => lut_ram}/xdc/top_level.xdc (100%) rename src/manta/{lut_mem.v => lut_ram.v} (96%) rename test/{lut_mem_tb.sv => lut_ram_tb.sv} (97%) diff --git a/Makefile b/Makefile index 93fd1aa..858bb10 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ lint: python3 -m black src/manta/__init__.py python3 -m black src/manta/__main__.py -sim: sim_bit_fifo sim_bridge_rx sim_bridge_tx fifo_tb lut_mem_tb uart_tx_tb +sim: sim_bit_fifo sim_bridge_rx sim_bridge_tx fifo_tb lut_ram_tb uart_tx_tb sim_bit_fifo: iverilog -g2012 -o sim.out test/bit_fifo_tb.sv src/manta/bit_fifo.v @@ -30,8 +30,8 @@ fifo_tb: vvp sim.out >> /dev/null # this one is noisy right now rm sim.out -lut_mem_tb: - iverilog -g2012 -o sim.out test/lut_mem_tb.sv src/manta/lut_mem.v +lut_ram_tb: + iverilog -g2012 -o sim.out test/lut_ram_tb.sv src/manta/lut_ram.v vvp sim.out rm sim.out diff --git a/examples/nexys_a7/single_lut_ram/manta.yaml b/examples/nexys_a7/logic_analyzer/manta.yaml similarity index 100% rename from examples/nexys_a7/single_lut_ram/manta.yaml rename to examples/nexys_a7/logic_analyzer/manta.yaml diff --git a/examples/nexys_a7/logic_analyzer/src/manta.v b/examples/nexys_a7/logic_analyzer/src/manta.v new file mode 100644 index 0000000..eda13af --- /dev/null +++ b/examples/nexys_a7/logic_analyzer/src/manta.v @@ -0,0 +1,498 @@ +`default_nettype none +`timescale 1ns/1ps + +/* +This manta definition was generated on 14 Mar 2023 at 13:06:49 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. +*/ + +module manta ( + input wire clk, + + input wire rx, + output reg tx, + + input wire larry, + input wire curly, + input wire moe, + input wire [3:0] shemp); + + rx_uart #(.CLOCKS_PER_BAUD(868)) urx ( + .i_clk(clk), + .i_uart_rx(rx), + .o_wr(urx_brx_axiv), + .o_data(urx_brx_axid)); + + logic [7:0] urx_brx_axid; + logic urx_brx_axiv; + + bridge_rx brx ( + .clk(clk), + + .rx_data(urx_brx_axid), + .rx_valid(urx_brx_axiv), + + .addr_o(brx_my_logic_analyzer_addr), + .wdata_o(brx_my_logic_analyzer_wdata), + .rw_o(brx_my_logic_analyzer_rw), + .valid_o(brx_my_logic_analyzer_valid)); + + reg [15:0] brx_my_logic_analyzer_addr; + reg [15:0] brx_my_logic_analyzer_wdata; + reg brx_my_logic_analyzer_rw; + reg brx_my_logic_analyzer_valid; + + la_core my_logic_analyzer ( + .clk(clk), + + .addr_i(brx_my_logic_analyzer_addr), + .wdata_i(brx_my_logic_analyzer_wdata), + .rdata_i(), + .rw_i(brx_my_logic_analyzer_rw), + .valid_i(brx_my_logic_analyzer_valid), + + .larry(larry), + .curly(curly), + .moe(moe), + .shemp(shemp), + + .addr_o(), + .wdata_o(), + .rdata_o(my_logic_analyzer_btx_rdata), + .rw_o(my_logic_analyzer_btx_rw), + .valid_o(my_logic_analyzer_btx_valid)); + + reg [15:0] my_logic_analyzer_btx_rdata; + reg my_logic_analyzer_btx_rw; + reg my_logic_analyzer_btx_valid; + + 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), + + .ready_i(utx_btx_ready), + .data_o(btx_utx_data), + .valid_o(btx_utx_valid)); + + logic utx_btx_ready; + logic btx_utx_valid; + logic [7:0] btx_utx_data; + + uart_tx #(.CLOCKS_PER_BAUD(868)) utx ( + .clk(clk), + + .data(btx_utx_data), + .valid(btx_utx_valid), + .ready(utx_btx_ready), + + .tx(tx)); +endmodule + + /* ---- Module Definitions ---- */ +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: rxuart.v +// +// Project: Verilog Tutorial Example file +// +// Purpose: Receives a character from a UART (serial port) wire. Key +// features of this core include: +// +// - The baud rate is constant, and set by the CLOCKS_PER_BAUD parameter. +// To be successful, one baud interval must be (approximately) +// equal to CLOCKS_PER_BAUD / CLOCK_RATE_HZ seconds long. +// +// - The protocol used is the basic 8N1: 8 data bits, 1 stop bit, and no +// parity. +// +// - This core has no reset +// - This core has no error detection for frame errors +// - This core cannot detect, report, or even recover from, a break +// condition on the line. A break condition is defined as a +// period of time where the i_uart_rx line is held low for longer +// than one data byte (10 baud intervals) +// +// - There's no clock rate detection in this core +// +// Perhaps one of the nicer features of this core is that it (can be) +// formally verified. It depends upon a separate (formally verified) +// transmit core for this purpose. +// +// As with the other cores within this tutorial, there may (or may not) be +// bugs within this design for you to find. +// +// +// Creator: Dan Gisselquist, Ph.D. +// Gisselquist Technology, LLC +// +//////////////////////////////////////////////////////////////////////////////// +// +// Written and distributed by Gisselquist Technology, LLC +// +// This program is hereby granted to the public domain. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +//////////////////////////////////////////////////////////////////////////////// +// +// + + +module rx_uart( + input wire i_clk, + input wire i_uart_rx, + output reg o_wr, + output reg [7:0] o_data); + + parameter [15:0] CLOCKS_PER_BAUD = 868; + localparam [3:0] IDLE = 4'h0; + localparam [3:0] BIT_ZERO = 4'h1; + // localparam [3:0] BIT_ONE = 4'h2; + // localparam [3:0] BIT_TWO = 4'h3; + // localparam [3:0] BIT_THREE = 4'h4; + // localparam [3:0] BIT_FOUR = 4'h5; + // localparam [3:0] BIT_FIVE = 4'h6; + // localparam [3:0] BIT_SIX = 4'h7; + // localparam [3:0] BIT_SEVEN = 4'h8; + localparam [3:0] STOP_BIT = 4'h9; + + reg [3:0] state; + reg [15:0] baud_counter; + reg zero_baud_counter; + + // 2FF Synchronizer + // + reg ck_uart; + reg q_uart; + initial { ck_uart, q_uart } = -1; + always @(posedge i_clk) + { ck_uart, q_uart } <= { q_uart, i_uart_rx }; + + initial state = IDLE; + initial baud_counter = 0; + + always @(posedge i_clk) + if (state == IDLE) begin + state <= IDLE; + baud_counter <= 0; + if (!ck_uart) begin + state <= BIT_ZERO; + baud_counter <= CLOCKS_PER_BAUD+CLOCKS_PER_BAUD/2-1'b1; + end + end + + else if (zero_baud_counter) begin + state <= state + 1; + baud_counter <= CLOCKS_PER_BAUD-1'b1; + if (state == STOP_BIT) begin + state <= IDLE; + baud_counter <= 0; + end + end + + else baud_counter <= baud_counter - 1'b1; + + always @(*) + zero_baud_counter = (baud_counter == 0); + + always @(posedge i_clk) + if ((zero_baud_counter)&&(state != STOP_BIT)) + o_data <= { ck_uart, o_data[7:1] }; + + initial o_wr = 1'b0; + always @(posedge i_clk) + o_wr <= ((zero_baud_counter)&&(state == STOP_BIT)); + +endmodule + + + + +module bridge_rx( + input wire clk, + + input wire[7:0] rx_data, + input wire rx_valid, + + output reg[15:0] addr_o, + output reg[15:0] wdata_o, + output reg rw_o, + output reg valid_o +); + + +// this is a hack, the FSM needs to be updated +// but this will bypass it for now +parameter ready_i = 1; + +parameter ADDR_WIDTH = 0; +parameter DATA_WIDTH = 0; + +localparam PREAMBLE = 8'h4D; +localparam CR = 8'h0D; +localparam LF = 8'h0A; + +localparam ACQUIRE = 0; +localparam TRANSMIT = 1; +localparam ERROR = 2; + +reg [1:0] state; +reg [3:0] bytes_received; + +// no global resets! +initial begin + addr_o = 0; + wdata_o = 0; + rw_o = 0; + valid_o = 0; + bytes_received = 0; + state = ACQUIRE; +end + +reg [3:0] rx_data_decoded; +reg rx_data_is_0_thru_9; +reg rx_data_is_A_thru_F; + +always @(*) begin + rx_data_is_0_thru_9 = (rx_data >= 8'h30) & (rx_data <= 8'h39); + rx_data_is_A_thru_F = (rx_data >= 8'h41) & (rx_data <= 8'h46); + + if (rx_data_is_0_thru_9) rx_data_decoded = rx_data - 8'h30; + else if (rx_data_is_A_thru_F) rx_data_decoded = rx_data - 8'h41 + 'd10; + else rx_data_decoded = 0; +end + + +always @(posedge clk) begin + if (state == ACQUIRE) begin + if(rx_valid) begin + + if (bytes_received == 0) begin + if(rx_data == PREAMBLE) bytes_received <= 1; + end + + else if( (bytes_received >= 1) & (bytes_received <= 4) ) begin + // only advance if byte is valid hex digit + if(rx_data_is_0_thru_9 | rx_data_is_A_thru_F) begin + addr_o <= (addr_o << 4) | rx_data_decoded; + bytes_received <= bytes_received + 1; + end + + else state <= ERROR; + end + + else if( bytes_received == 5) begin + if( (rx_data == CR) | (rx_data == LF)) begin + valid_o <= 1; + rw_o = 0; + bytes_received <= 0; + state <= TRANSMIT; + end + + else if (rx_data_is_0_thru_9 | rx_data_is_A_thru_F) begin + bytes_received <= bytes_received + 1; + wdata_o <= (wdata_o << 4) | rx_data_decoded; + end + + else state <= ERROR; + end + + else if ( (bytes_received >= 6) & (bytes_received <= 8) ) begin + + if (rx_data_is_0_thru_9 | rx_data_is_A_thru_F) begin + wdata_o <= (wdata_o << 4) | rx_data_decoded; + bytes_received <= bytes_received + 1; + end + + else state <= ERROR; + end + + else if (bytes_received == 9) begin + bytes_received <= 0; + if( (rx_data == CR) | (rx_data == LF)) begin + valid_o <= 1; + rw_o <= 1; + state <= TRANSMIT; + end + + else state <= ERROR; + end + end + end + + + else if (state == TRANSMIT) begin + if(ready_i) begin + valid_o <= 0; + state <= ACQUIRE; + end + + if(rx_valid) begin + if ( (rx_data != CR) & (rx_data != LF)) begin + valid_o <= 0; + state <= ERROR; + end + end + end +end + +endmodule + + + + + +module bridge_tx( + input wire clk, + + input wire [15:0] rdata_i, + input wire rw_i, + input wire valid_i, + + output reg [7:0] data_o, + input wire ready_i, + output reg valid_o); + +localparam PREAMBLE = 8'h4D; +localparam CR = 8'h0D; +localparam LF = 8'h0A; + +logic busy; +logic [15:0] buffer; +logic [3:0] byte_counter; + +initial begin + busy = 0; + buffer = 0; + byte_counter = 0; + valid_o = 0; +end + +always @(posedge clk) begin + if (!busy) begin + if (valid_i && !rw_i) begin + busy <= 1; + buffer <= rdata_i; + byte_counter <= 0; + valid_o <= 1; + end + end + + if (busy) begin + + if(ready_i) begin + byte_counter <= byte_counter + 1; + + if (byte_counter > 5) begin + byte_counter <= 0; + + // stop transmitting if we don't have both valid and read + if ( !(valid_i && !rw_i) ) begin + busy <= 0; + valid_o <= 0; + end + end + end + end +end + +always @(*) begin + case (byte_counter) + 0: data_o = PREAMBLE; + 1: data_o = (buffer[15:12] < 10) ? (buffer[15:12] + 8'h30) : (buffer[15:12] + 8'h41 - 'd10); + 2: data_o = (buffer[11:8] < 10) ? (buffer[11:8] + 8'h30) : (buffer[11:8] + 8'h41 - 'd10); + 3: data_o = (buffer[7:4] < 10) ? (buffer[7:4] + 8'h30) : (buffer[7:4] + 8'h41 - 'd10); + 4: data_o = (buffer[3:0] < 10) ? (buffer[3:0] + 8'h30) : (buffer[3:0] + 8'h41 - 'd10); + 5: data_o = CR; + 6: data_o = LF; + default: data_o = 0; + endcase +end + +endmodule + + + + +module uart_tx( + input wire clk, + + input wire [7:0] data, + input wire valid, + output reg busy, + output reg ready, + + output reg tx); + + // this transmitter only works with 8N1 serial, at configurable baudrate + parameter CLOCKS_PER_BAUD = 868; + + reg [9:0] baud_counter; + reg [8:0] data_buf; + reg [3:0] bit_index; + + initial begin + baud_counter = CLOCKS_PER_BAUD; + data_buf = 0; + bit_index = 0; + busy = 0; + ready = 1; + tx = 1; + end + + always @(posedge clk) begin + if (valid && !busy) begin + data_buf <= {1'b1, data}; + bit_index <= 0; + tx <= 0; //wafflestomp that start bit + baud_counter <= CLOCKS_PER_BAUD - 1; + busy <= 1; + ready <= 0; + end + + else if (busy) begin + baud_counter <= baud_counter - 1; + + ready <= (baud_counter == 1) && (bit_index == 9); + + if (baud_counter == 0) begin + baud_counter <= CLOCKS_PER_BAUD - 1; + + + if (bit_index == 9) begin + if(valid) begin + data_buf <= {1'b1, data}; + bit_index <= 0; + tx <= 0; + end + + else begin + busy <= 0; + ready <= 1; + end + // if valid happens here then we should bool + end + + else begin + tx <= data_buf[bit_index]; + bit_index <= bit_index + 1; + end + end + end + end + + + +endmodule + + +`default_nettype wire \ No newline at end of file diff --git a/examples/nexys_a7/single_lut_ram/block_verify.py b/examples/nexys_a7/lut_ram/block_verify.py similarity index 100% rename from examples/nexys_a7/single_lut_ram/block_verify.py rename to examples/nexys_a7/lut_ram/block_verify.py diff --git a/examples/nexys_a7/single_lut_ram/lab-bc.py b/examples/nexys_a7/lut_ram/lab-bc.py similarity index 100% rename from examples/nexys_a7/single_lut_ram/lab-bc.py rename to examples/nexys_a7/lut_ram/lab-bc.py diff --git a/examples/nexys_a7/lut_ram/manta.yaml b/examples/nexys_a7/lut_ram/manta.yaml new file mode 100644 index 0000000..f1e5dd9 --- /dev/null +++ b/examples/nexys_a7/lut_ram/manta.yaml @@ -0,0 +1,10 @@ +--- +cores: + my_lut_ram: + type: lut_ram + size: 64 + +uart: + port: "/dev/tty.usbserial-2102926963071" + baudrate: 115200 + clock_freq: 100000000 \ No newline at end of file diff --git a/examples/nexys_a7/single_lut_ram/src/manta.v b/examples/nexys_a7/lut_ram/src/manta.v similarity index 91% rename from examples/nexys_a7/single_lut_ram/src/manta.v rename to examples/nexys_a7/lut_ram/src/manta.v index ca3b57d..820d05e 100644 --- a/examples/nexys_a7/single_lut_ram/src/manta.v +++ b/examples/nexys_a7/lut_ram/src/manta.v @@ -2,7 +2,7 @@ `timescale 1ns/1ps /* -This manta definition was generated on 09 Mar 2023 at 23:58:38 by fischerm +This manta definition was generated on 14 Mar 2023 at 13:06:49 by fischerm If this breaks or if you've got dank formal verification memes, please contact fischerm [at] mit.edu @@ -31,41 +31,41 @@ module manta ( .rx_data(urx_brx_axid), .rx_valid(urx_brx_axiv), - .addr_o(brx_my_logic_analyzer_addr), - .wdata_o(brx_my_logic_analyzer_wdata), - .rw_o(brx_my_logic_analyzer_rw), - .valid_o(brx_my_logic_analyzer_valid)); + .addr_o(brx_my_lut_ram_addr), + .wdata_o(brx_my_lut_ram_wdata), + .rw_o(brx_my_lut_ram_rw), + .valid_o(brx_my_lut_ram_valid)); - reg [15:0] brx_my_logic_analyzer_addr; - reg [15:0] brx_my_logic_analyzer_wdata; - reg brx_my_logic_analyzer_rw; - reg brx_my_logic_analyzer_valid; + reg [15:0] brx_my_lut_ram_addr; + reg [15:0] brx_my_lut_ram_wdata; + reg brx_my_lut_ram_rw; + reg brx_my_lut_ram_valid; - lut_mem my_logic_analyzer( + lut_ram #(.DEPTH(64)) my_lut_ram ( .clk(clk), - .addr_i(brx_my_logic_analyzer_addr), - .wdata_i(brx_my_logic_analyzer_wdata), + .addr_i(brx_my_lut_ram_addr), + .wdata_i(brx_my_lut_ram_wdata), .rdata_i(), - .rw_i(brx_my_logic_analyzer_rw), - .valid_i(brx_my_logic_analyzer_valid), - + .rw_i(brx_my_lut_ram_rw), + .valid_i(brx_my_lut_ram_valid), + .addr_o(), .wdata_o(), - .rdata_o(my_logic_analyzer_btx_rdata), - .rw_o(my_logic_analyzer_btx_rw), - .valid_o(my_logic_analyzer_btx_valid)); + .rdata_o(my_lut_ram_btx_rdata), + .rw_o(my_lut_ram_btx_rw), + .valid_o(my_lut_ram_btx_valid)); - reg [15:0] my_logic_analyzer_btx_rdata; - reg my_logic_analyzer_btx_rw; - reg my_logic_analyzer_btx_valid; + reg [15:0] my_lut_ram_btx_rdata; + reg my_lut_ram_btx_rw; + reg my_lut_ram_btx_valid; 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), + .rdata_i(my_lut_ram_btx_rdata), + .rw_i(my_lut_ram_btx_rw), + .valid_i(my_lut_ram_btx_valid), .ready_i(utx_btx_ready), .data_o(btx_utx_data), @@ -340,6 +340,53 @@ endmodule +module lut_ram( + input wire clk, + + // 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 DEPTH = 8; +parameter BASE_ADDR = 0; +parameter READ_ONLY = 0; +reg [DEPTH-1:0][15:0] mem; + +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(valid_i) begin + // check if address is valid + if( (addr_i >= BASE_ADDR) && (addr_i <= BASE_ADDR + DEPTH - 1) ) begin + + // read/write + if (rw_i && !READ_ONLY) mem[addr_i - BASE_ADDR] <= wdata_i; + else rdata_o <= mem[addr_i - BASE_ADDR]; + end + end +end +endmodule + + + + module bridge_tx( input wire clk, @@ -485,53 +532,4 @@ module uart_tx( endmodule -`default_nettype none -`timescale 1ns/1ps - -module lut_mem( - input wire clk, - - // 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 DEPTH = 8; -parameter BASE_ADDR = 0; -parameter READ_ONLY = 0; -reg [DEPTH-1:0][15:0] mem; - -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(valid_i) begin - // check if address is valid - if( (addr_i >= BASE_ADDR) && (addr_i <= BASE_ADDR + DEPTH - 1) ) begin - - // read/write - if (rw_i && !READ_ONLY) mem[addr_i - BASE_ADDR] <= wdata_i; - else rdata_o <= mem[addr_i - BASE_ADDR]; - end - end -end -endmodule - -`default_nettype wire - `default_nettype wire \ No newline at end of file diff --git a/examples/nexys_a7/single_lut_ram/src/ssd.v b/examples/nexys_a7/lut_ram/src/ssd.v similarity index 100% rename from examples/nexys_a7/single_lut_ram/src/ssd.v rename to examples/nexys_a7/lut_ram/src/ssd.v diff --git a/examples/nexys_a7/single_lut_ram/src/top_level.sv b/examples/nexys_a7/lut_ram/src/top_level.sv similarity index 65% rename from examples/nexys_a7/single_lut_ram/src/top_level.sv rename to examples/nexys_a7/lut_ram/src/top_level.sv index 66caeda..a29ced6 100644 --- a/examples/nexys_a7/single_lut_ram/src/top_level.sv +++ b/examples/nexys_a7/lut_ram/src/top_level.sv @@ -13,25 +13,20 @@ module top_level ( output logic uart_rxd_out ); - // Signal Generator - // logic [7:0] count; - // always_ff @(posedge clk) count <= count + 1; - - manta manta ( .clk(clk), .rx(uart_txd_in), .tx(uart_rxd_out)); - assign led = manta.brx_my_logic_analyzer_addr; + assign led = manta.brx_my_lut_ram_addr; logic [6:0] cat; assign {cg,cf,ce,cd,cc,cb,ca} = cat; ssd ssd ( .clk_in(clk), .rst_in(btnc), - .val_in( (manta.my_logic_analyzer_btx_rdata << 16) | (manta.brx_my_logic_analyzer_wdata) ), + .val_in( (manta.my_lut_ram_btx_rdata << 16) | (manta.brx_my_lut_ram_wdata) ), .cat_out(cat), .an_out(an)); diff --git a/examples/nexys_a7/single_lut_ram/xdc/top_level.xdc b/examples/nexys_a7/lut_ram/xdc/top_level.xdc similarity index 100% rename from examples/nexys_a7/single_lut_ram/xdc/top_level.xdc rename to examples/nexys_a7/lut_ram/xdc/top_level.xdc diff --git a/src/manta/__init__.py b/src/manta/__init__.py index cffde57..216f352 100644 --- a/src/manta/__init__.py +++ b/src/manta/__init__.py @@ -48,8 +48,7 @@ class UARTInterface: def hdl_top_level_ports(self): # this should return the probes that we want to connect to top-level, but like as a string of verilog - return """input wire rx, - output reg tx,""" + return ["input wire rx", "output reg tx"] def rx_hdl_def(self): uart_rx_def = pkgutil.get_data(__name__, "rx_uart.v").decode() @@ -111,10 +110,39 @@ class UARTInterface: .tx(tx));\n""" -class IOCore: +class LUTRAMCore: def __init__(self, config, interface): self.interface = interface + assert "size" in config, "Size not specified for LUT RAM core." + self.size = config["size"] + + def hdl_inst(self): + hdl = f""" + lut_ram #(.DEPTH({self.size})) {self.name} ( + .clk(clk), + + .addr_i(), + .wdata_i(), + .rdata_i(), + .rw_i(), + .valid_i(), + + .addr_o(), + .wdata_o(), + .rdata_o(), + .rw_o(), + .valid_o());\n""" + + return hdl + + def hdl_def(self): + hdl = pkgutil.get_data(__name__, "lut_ram.v").decode() + return hdl + + def hdl_top_level_ports(self): + # no top_level connections since this core just lives on the bus + return [] class LogicAnalyzerCore: def __init__(self, config, interface): @@ -274,16 +302,16 @@ class LogicAnalyzerCore: return tmpl def hdl_top_level_ports(self): - # this should return the probes that we want to connect to top-level, but like as a string of verilog + # this should return the probes that we want to connect to top-level, but as a list of verilog ports ports = [] for name, width in self.probes.items(): if width == 1: - ports.append(f"input wire {name},") + ports.append(f"input wire {name}") else: - ports.append(f"input wire [{width-1}:0] {name},") + ports.append(f"input wire [{width-1}:0] {name}") - return "\n ".join(ports) + return ports class Manta: def __init__(self, config_filepath): @@ -313,6 +341,9 @@ class Manta: elif core["type"] == "io": new_core = IOCore(core, self.interface) + + elif core["type"] == "lut_ram": + new_core = LUTRAMCore(core, self.interface) else: raise ValueError(f"Unrecognized core type specified for {core_name}.") @@ -380,27 +411,28 @@ class Manta: else: src_name = self.cores[i-1].name + hdl = hdl.replace(".rdata_i()", f".rdata_i({src_name}_{core.name}_rdata)") hdl = hdl.replace(".addr_i()", f".addr_i({src_name}_{core.name}_addr)") hdl = hdl.replace(".wdata_i()", f".wdata_i({src_name}_{core.name}_wdata)") - hdl = hdl.replace(".rdata_i()", f".rdata_i({src_name}_{core.name}_rdata)") hdl = hdl.replace(".rw_i()", f".rw_i({src_name}_{core.name}_rw)") hdl = hdl.replace(".valid_i()", f".valid_i({src_name}_{core.name}_valid)") - + + # connect output if (i < len(self.cores)-1): dst_name = self.cores[i+1] + hdl = hdl.replace(".addr_o()", f".addr_o({core.name}_{dst_name}_addr)") + hdl = hdl.replace(".wdata_o()", f".wdata_o({core.name}_{dst_name}_wdata)") else: dst_name = "btx" - hdl = hdl.replace(".addr_o()", f".addr_o({core.name}_{dst_name}_addr)") - hdl = hdl.replace(".wdata_o()", f".wdata_o({core.name}_{dst_name}_wdata)") hdl = hdl.replace(".rdata_o()", f".rdata_o({core.name}_{dst_name}_rdata)") hdl = hdl.replace(".rw_o()", f".rw_o({core.name}_{dst_name}_rw)") hdl = hdl.replace(".valid_o()", f".valid_o({core.name}_{dst_name}_valid)") - + insts.append(hdl) return insts @@ -438,17 +470,31 @@ Provided under a GNU GPLv3 license. Go wild. # get all the top level connections for each module. interface_ports = self.interface.hdl_top_level_ports() + interface_ports = [f" {port},\n" for port in interface_ports] + interface_ports = "".join(interface_ports) + "\n" - core_chain_ports = [core.hdl_top_level_ports() for core in self.cores] + core_chain_ports = [] + for core in self.cores: + ports = [f" {port},\n" for port in core.hdl_top_level_ports()] + ports = "".join(ports) + core_chain_ports.append(ports) + core_chain_ports = "\n".join(core_chain_ports) - + + ports = interface_ports + core_chain_ports + + # remove trailing comma + ports = ports.rstrip() + if ports[-1] == ",": + ports = ports[:-1] + + print(ports) + return f""" module manta ( input wire clk, - {interface_ports} - - {core_chain_ports}); +{ports}); """ def generate_interface_rx(self): @@ -480,10 +526,10 @@ module manta ( # instantiate interface_tx, substitute in register names interface_tx_inst = self.interface.tx_hdl_inst() - interface_tx_inst = interface_tx_inst.replace("addr_i()", f"addr_o({self.cores[0].name}_btx_addr)") - interface_tx_inst = interface_tx_inst.replace("rdata_i()", f"rdata_o({self.cores[0].name}_btx_rdata)") - interface_tx_inst = interface_tx_inst.replace("rw_i()", f"rw_o({self.cores[0].name}_btx_rw)") - interface_tx_inst = interface_tx_inst.replace("valid_i()", f"valid_o({self.cores[0].name}_btx_valid)") + interface_tx_inst = interface_tx_inst.replace("addr_i()", f"addr_i({self.cores[0].name}_btx_addr)") + interface_tx_inst = interface_tx_inst.replace("rdata_i()", f"rdata_i({self.cores[0].name}_btx_rdata)") + interface_tx_inst = interface_tx_inst.replace("rw_i()", f"rw_i({self.cores[0].name}_btx_rw)") + interface_tx_inst = interface_tx_inst.replace("valid_i()", f"valid_i({self.cores[0].name}_btx_valid)") return interface_tx_conn + interface_tx_inst diff --git a/src/manta/lut_mem.v b/src/manta/lut_ram.v similarity index 96% rename from src/manta/lut_mem.v rename to src/manta/lut_ram.v index d95f49f..c676197 100644 --- a/src/manta/lut_mem.v +++ b/src/manta/lut_ram.v @@ -1,7 +1,7 @@ `default_nettype none `timescale 1ns/1ps -module lut_mem( +module lut_ram( input wire clk, // input port diff --git a/test/bus_fix_tb.sv b/test/bus_fix_tb.sv index 6eea6c2..5e24fd4 100644 --- a/test/bus_fix_tb.sv +++ b/test/bus_fix_tb.sv @@ -56,10 +56,10 @@ module bus_fix_tb; logic brx_mem_rw; logic brx_mem_valid; - lut_mem #( + lut_ram #( .DEPTH(32), .BASE_ADDR(0) - ) mem ( + ) ram ( .clk(clk), .addr_i(brx_mem_addr), .wdata_i(brx_mem_wdata), diff --git a/test/lut_mem_tb.sv b/test/lut_ram_tb.sv similarity index 97% rename from test/lut_mem_tb.sv rename to test/lut_ram_tb.sv index 2179bb6..df060b3 100644 --- a/test/lut_mem_tb.sv +++ b/test/lut_ram_tb.sv @@ -3,7 +3,7 @@ `define CP 10 `define HCP 5 -module lut_mem_tb; +module lut_ram_tb; // https://www.youtube.com/watch?v=WCOAr-96bGc //boilerplate @@ -17,7 +17,7 @@ module lut_mem_tb; logic tb_mem_1_rw; logic tb_mem_1_valid; - lut_mem #( + lut_ram #( .DEPTH(8), .BASE_ADDR(0) ) mem_1 ( @@ -42,7 +42,7 @@ module lut_mem_tb; logic mem_1_mem_2_rw; logic mem_1_mem_2_valid; - lut_mem #( + lut_ram #( .DEPTH(8), .BASE_ADDR(8) ) mem_2 ( @@ -67,7 +67,7 @@ module lut_mem_tb; logic mem_2_mem_3_rw; logic mem_2_mem_3_valid; - lut_mem #( + lut_ram #( .DEPTH(8), .BASE_ADDR(16) ) mem_3 ( @@ -98,8 +98,8 @@ module lut_mem_tb; end initial begin - $dumpfile("lut_mem.vcd"); - $dumpvars(0, lut_mem_tb); + $dumpfile("lut_ram.vcd"); + $dumpvars(0, lut_ram_tb); // setup and reset clk = 0;