xiiregexbuilder

FPGA-Accelerated Regular Expression Matching Engine

output-pii/top_fpga.v (5358B)


  1`timescale 1ns / 1ps
  2
  3module top_fpga (
  4    input  wire clk,        // 100 MHz system clock
  5    input  wire rst_btn,    // Physical reset button
  6    input  wire uart_rx_pin,// USB UART RX pin
  7    output wire uart_tx_pin // USB UART TX pin
  8);
  9
 10
 11    wire [7:0] rx_data;
 12    wire       rx_ready;
 13    
 14    uart_rx uart_inst (
 15        .clk(clk),
 16        .rx(uart_rx_pin),
 17        .rx_data(rx_data),
 18        .rx_ready(rx_ready)
 19    );
 20
 21    reg        nfa_start = 1'b1;
 22    reg  [7:0] nfa_char_in = 8'h00;
 23    reg        nfa_en = 1'b0;
 24    wire [6:0] match_bus;
 25    wire [6:0] active_bus;
 26
 27    top regex_engine (
 28        .clk(clk),
 29        .en(nfa_en),
 30        .rst(rst_btn),
 31        .start(nfa_start),
 32        .char_in(nfa_char_in),
 33        .match_bus(match_bus),
 34        .active_bus(active_bus)
 35    );
 36
 37
 38    // UART TX Signals
 39    reg        tx_start = 1'b0;
 40    reg  [7:0] tx_data = 8'h00;
 41    wire       tx_busy;
 42
 43    uart_tx uart_tx_inst (
 44        .clk(clk),
 45        .tx_start(tx_start),
 46        .tx_data(tx_data),
 47        .tx(uart_tx_pin),
 48        .tx_busy(tx_busy)
 49    );
 50
 51    // 128-Byte Latency Buffering with Precise Alignment
 52    localparam DELAY_LEN = 128;
 53    (* ram_style = "distributed" *) reg [7:0] delay_bram [0:DELAY_LEN-1];
 54    reg [6:0] delay_ptr = 0;
 55    reg [DELAY_LEN-1:0] commit_history = 0;
 56
 57    // Per-NFA Active Histories to isolate redaction contexts
 58    reg [DELAY_LEN-1:0] active_history_0 = 0;
 59    reg [DELAY_LEN-1:0] active_history_1 = 0;
 60    reg [DELAY_LEN-1:0] active_history_2 = 0;
 61    reg [DELAY_LEN-1:0] active_history_3 = 0;
 62    reg [DELAY_LEN-1:0] active_history_4 = 0;
 63    reg [DELAY_LEN-1:0] active_history_5 = 0;
 64    reg [DELAY_LEN-1:0] active_history_6 = 0;
 65
 66    // Power-On-Reset Initialization
 67    reg [7:0] por_count = 0;
 68    wire por_rst = (por_count < 8'hFF);
 69
 70    reg rx_ready_prev = 0;
 71    reg [1:0] step = 0;
 72    reg [7:0] rx_latch = 0;
 73
 74    always @(posedge clk) begin
 75        if (rst_btn || por_rst) begin
 76            if (por_count < 8'h80) begin
 77                delay_bram[por_count[6:0]] <= 8'h20; // Initialize BRAM sequentially
 78            end
 79            if (por_count < 8'hFF) por_count <= por_count + 1;
 80            
 81            nfa_en <= 0;
 82            nfa_start <= 1;
 83            tx_start <= 0;
 84            rx_ready_prev <= 0;
 85            delay_ptr <= 0;
 86            commit_history <= 0;
 87            step <= 0;
 88            active_history_0 <= 0;
 89            active_history_1 <= 0;
 90            active_history_2 <= 0;
 91            active_history_3 <= 0;
 92            active_history_4 <= 0;
 93            active_history_5 <= 0;
 94            active_history_6 <= 0;
 95
 96        end else begin
 97            nfa_start <= 0;
 98            nfa_en <= 0;
 99            tx_start <= 0;
100            rx_ready_prev <= rx_ready;
101
102            // Character Processing Sequence
103            if (rx_ready && !rx_ready_prev) begin
104                rx_latch <= rx_data;
105                step <= 1;
106            end
107
108            case (step)
109                1: begin
110                    // Step 1: Feed NFA Engine
111                    nfa_char_in <= rx_latch;
112                    nfa_en <= 1;
113                    step <= 2;
114                end
115                2: begin
116                    // Step 2: NFA Results and Redaction Output
117                    // 1. Read delayed char and check redaction bit (Sampling BEFORE shift)
118                    tx_data <= (commit_history[DELAY_LEN-2]) ? 8'h58 : delay_bram[delay_ptr];
119                    tx_start <= 1;
120
121                    // 2. Overwrite slot with new character
122                    delay_bram[delay_ptr] <= rx_latch;
123                    delay_ptr <= delay_ptr + 1;
124
125                    // 3. Update Histories (Isolating contexts)
126                    active_history_0 <= active_bus[0] ? {active_history_0[DELAY_LEN-2:0], 1'b1} : 128'd0;
127                    active_history_1 <= active_bus[1] ? {active_history_1[DELAY_LEN-2:0], 1'b1} : 128'd0;
128                    active_history_2 <= active_bus[2] ? {active_history_2[DELAY_LEN-2:0], 1'b1} : 128'd0;
129                    active_history_3 <= active_bus[3] ? {active_history_3[DELAY_LEN-2:0], 1'b1} : 128'd0;
130                    active_history_4 <= active_bus[4] ? {active_history_4[DELAY_LEN-2:0], 1'b1} : 128'd0;
131                    active_history_5 <= active_bus[5] ? {active_history_5[DELAY_LEN-2:0], 1'b1} : 128'd0;
132                    active_history_6 <= active_bus[6] ? {active_history_6[DELAY_LEN-2:0], 1'b1} : 128'd0;
133                    commit_history <= {commit_history[DELAY_LEN-2:0], 1'b0}
134                                      | (match_bus[0] ? {active_history_0[DELAY_LEN-2:0], 1'b1} : 128'd0)
135                                      | (match_bus[1] ? {active_history_1[DELAY_LEN-2:0], 1'b1} : 128'd0)
136                                      | (match_bus[2] ? {active_history_2[DELAY_LEN-2:0], 1'b1} : 128'd0)
137                                      | (match_bus[3] ? {active_history_3[DELAY_LEN-2:0], 1'b1} : 128'd0)
138                                      | (match_bus[4] ? {active_history_4[DELAY_LEN-2:0], 1'b1} : 128'd0)
139                                      | (match_bus[5] ? {active_history_5[DELAY_LEN-2:0], 1'b1} : 128'd0)
140                                      | (match_bus[6] ? {active_history_6[DELAY_LEN-2:0], 1'b1} : 128'd0);
141
142                    step <= 0;
143                end
144            endcase
145        end
146    end
147endmodule