commit 042756fa5985d38096c916cc5219f6e64a847ed9
parent bfe7a9821ad84be824769d432b5375d0e83ae22e
Author: Vishrut Gurrala <maydayv7@gmail.com>
Date: Sun, 5 Apr 2026 01:39:07 +0530
Week 3: Implement UART RX and partial FPGA top wrapper (Part 2: Core logic)
Diffstat:
2 files changed, 89 insertions(+), 0 deletions(-)
diff --git a/output-eg/top_fpga.v b/output-eg/top_fpga.v
@@ -47,3 +47,69 @@ module top_fpga #(
.rst (rst_btn),
.wr_data(rx_data),
.wr_en (rx_ready && !fifo_full),
+ .full (fifo_full),
+ .rd_data(fifo_rd_data),
+ .rd_en (fifo_rd_en),
+ .empty (fifo_empty)
+ );
+
+ // NFA Engine
+ reg nfa_start = 1'b1;
+ reg nfa_end_of_str = 1'b0;
+ reg [7:0] nfa_char_in = 8'h00;
+ reg nfa_en = 1'b0;
+ wire [5:0] match_bus;
+
+ top regex_engine (
+ .clk (clk),
+ .en (nfa_en),
+ .rst (rst_btn),
+ .start (nfa_start),
+ .end_of_str (nfa_end_of_str),
+ .char_in (nfa_char_in),
+ .match_bus (match_bus)
+ );
+
+ // Hardware Counters
+ reg [31:0] byte_count = 32'd0;
+ // One 16-bit hit counter per regex
+ reg [15:0] match_count [0:15];
+ integer ci;
+ initial begin
+ for (ci = 0; ci < 16; ci = ci + 1)
+ match_count[ci] = 16'd0;
+ end
+
+ // UART TX & Drain Sub-FSM
+ localparam TX_BUF_LEN = 128;
+ reg [7:0] tx_buf [0:TX_BUF_LEN-1];
+ reg [6:0] tx_len = 7'd0;
+ reg [6:0] tx_ptr = 7'd0;
+ reg tx_send = 1'b0; // pulse: start draining tx_buf
+
+ wire tx_busy;
+ reg tx_start_r = 1'b0;
+ reg [7:0] tx_data_r = 8'd0;
+
+ uart_tx #(.CLKS_PER_BIT(CLKS_PER_BIT)) uart_tx_inst (
+ .clk (clk),
+ .rst (rst_btn),
+ .tx_data (tx_data_r),
+ .tx_start(tx_start_r),
+ .tx_busy (tx_busy),
+ .tx (uart_tx_pin)
+ );
+
+ // hex nibble → ASCII character
+ function [7:0] hex_char;
+ input [3:0] nibble;
+ begin
+ hex_char = (nibble < 4'd10) ? (8'd48 + nibble) : (8'd55 + nibble);
+ end
+ endfunction
+
+ localparam TX_IDLE = 2'd0, TX_LOAD = 2'd1, TX_WAIT = 2'd2, TX_NEXT = 2'd3;
+ reg [1:0] tx_state = TX_IDLE;
+
+ always @(posedge clk) begin
+ tx_start_r <= 1'b0;
diff --git a/output-eg/uart_rx.v b/output-eg/uart_rx.v
@@ -15,3 +15,26 @@ module uart_rx #(
reg [2:0] bit_idx = 0;
always @(posedge clk) begin
+ case (state)
+ IDLE: begin
+ rx_ready <= 1'b0;
+ clk_count <= 0;
+ bit_idx <= 0;
+ if (rx == 1'b0) state <= START_BIT;
+ end
+ START_BIT: begin
+ if (clk_count == (CLKS_PER_BIT-1)/2) begin
+ if (rx == 1'b0) begin
+ clk_count <= 0;
+ state <= DATA_BITS;
+ end else state <= IDLE;
+ end else clk_count <= clk_count + 1;
+ end
+ DATA_BITS: begin
+ if (clk_count < CLKS_PER_BIT-1) begin
+ clk_count <= clk_count + 1;
+ end else begin
+ clk_count <= 0;
+ rx_data[bit_idx] <= rx;
+ if (bit_idx < 7) bit_idx <= bit_idx + 1;
+ else state <= STOP_BIT;