xiiregexbuilder

FPGA-Accelerated Regular Expression Matching Engine
commit b5cba03ff61bd34e091a58174d878f79f534c3f3
parent 1638294121a88383f75e7e8c206f35f2e796a553
Author: yash modi <yash3108m@gmail.com>
Date:   Wed, 15 Apr 2026 01:02:08 +0530

Week 5: Core processor logic and parallel engine implementation (Part 3: Finalizing)

Diffstat:
Aprocessor/constraints.xdc | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aprocessor/regex_cpu.v | 147+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 215 insertions(+), 0 deletions(-)

diff --git a/processor/constraints.xdc b/processor/constraints.xdc @@ -0,0 +1,68 @@ +## Clock signal +set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { CLK100MHZ }]; +create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports { CLK100MHZ }]; + +## Switches +set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { SW[0] }]; +set_property -dict { PACKAGE_PIN L16 IOSTANDARD LVCMOS33 } [get_ports { SW[1] }]; +set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports { SW[2] }]; +set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 } [get_ports { SW[3] }]; +set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { SW[4] }]; +set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 } [get_ports { SW[5] }]; +set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { SW[6] }]; +set_property -dict { PACKAGE_PIN R13 IOSTANDARD LVCMOS33 } [get_ports { SW[7] }]; +set_property -dict { PACKAGE_PIN T8 IOSTANDARD LVCMOS33 } [get_ports { SW[8] }]; +set_property -dict { PACKAGE_PIN U8 IOSTANDARD LVCMOS33 } [get_ports { SW[9] }]; +set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { SW[10] }]; +set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { SW[11] }]; +set_property -dict { PACKAGE_PIN H6 IOSTANDARD LVCMOS33 } [get_ports { SW[12] }]; +set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 } [get_ports { SW[13] }]; +set_property -dict { PACKAGE_PIN U11 IOSTANDARD LVCMOS33 } [get_ports { SW[14] }]; +set_property -dict { PACKAGE_PIN V10 IOSTANDARD LVCMOS33 } [get_ports { SW[15] }]; + +## LEDs +set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { LED[0] }]; +set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { LED[1] }]; +set_property -dict { PACKAGE_PIN J13 IOSTANDARD LVCMOS33 } [get_ports { LED[2] }]; +set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { LED[3] }]; +set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { LED[4] }]; +set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { LED[5] }]; +set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { LED[6] }]; +set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { LED[7] }]; +set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { LED[8] }]; +set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { LED[9] }]; +set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { LED[10] }]; +set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { LED[11] }]; +set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { LED[12] }]; +set_property -dict { PACKAGE_PIN V14 IOSTANDARD LVCMOS33 } [get_ports { LED[13] }]; +set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 } [get_ports { LED[14] }]; +set_property -dict { PACKAGE_PIN V11 IOSTANDARD LVCMOS33 } [get_ports { LED[15] }]; + +## 7 segment display +set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { SEG[0] }]; +set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33 } [get_ports { SEG[1] }]; +set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { SEG[2] }]; +set_property -dict { PACKAGE_PIN K13 IOSTANDARD LVCMOS33 } [get_ports { SEG[3] }]; +set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { SEG[4] }]; +set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { SEG[5] }]; +set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 } [get_ports { SEG[6] }]; +set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { SEG[7] }]; + +set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { AN[0] }]; +set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { AN[1] }]; +set_property -dict { PACKAGE_PIN T9 IOSTANDARD LVCMOS33 } [get_ports { AN[2] }]; +set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { AN[3] }]; +set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { AN[4] }]; +set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { AN[5] }]; +set_property -dict { PACKAGE_PIN K2 IOSTANDARD LVCMOS33 } [get_ports { AN[6] }]; +set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { AN[7] }]; + +## UART +set_property -dict { PACKAGE_PIN C4 IOSTANDARD LVCMOS33 } [get_ports { UART_TXD_IN }]; +set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { UART_RXD_OUT }]; + +## Buttons +set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports { CPU_RESETN }]; +set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { BTNC }]; +set_property -dict { PACKAGE_PIN M18 IOSTANDARD LVCMOS33 } [get_ports { BTNU }]; +set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { BTND }]; diff --git a/processor/regex_cpu.v b/processor/regex_cpu.v @@ -0,0 +1,147 @@ +`timescale 1ns / 1ps + +module regex_cpu #( + parameter NUM_REGEX = 16 +) ( + input wire clk, + input wire rst, + input wire start, + input wire end_of_str, + input wire [7:0] char_in, + input wire char_valid, + + input wire prog_en, + input wire [ 7:0] prog_addr, + input wire [31:0] prog_data, + + output wire ready, + output reg [NUM_REGEX-1:0] match_bus +); + + // --- Instruction Memory (BRAM Inferred) --- + reg [31:0] imem[0:255]; + initial $readmemh("processor/build/imem.hex", imem); + + always @(posedge clk) begin + if (prog_en) imem[prog_addr] <= prog_data; + end + + // --- State Machine --- + localparam STATE_IDLE = 3'd0; + localparam STATE_START_INIT = 3'd1; + localparam STATE_CHAR_MATCH = 3'd2; + localparam STATE_EPSILON_RECURSE = 3'd3; + localparam STATE_END_OF_STR = 3'd4; + + reg [ 2:0] state = STATE_IDLE; + reg [255:0] active_candidates; + reg [ 5:0] recurse_count; + reg [ 7:0] pc_cnt; + reg [255:0] next_set_buffer; + reg [ 7:0] char_reg; + reg recurse_changed; + + assign ready = (state == STATE_IDLE); + + // Single-port instruction fetch + wire [31:0] current_instr = imem[pc_cnt]; + wire [ 7:0] p_char = current_instr[31:24]; + wire [ 7:0] p_next1 = current_instr[23:16]; + wire [ 7:0] p_next2 = current_instr[15:8]; + wire [ 3:0] p_mid = current_instr[7:4]; + wire p_term = current_instr[3]; + wire p_any = current_instr[0]; + + always @(posedge clk) begin + if (rst) begin + state <= STATE_IDLE; + active_candidates <= 0; + match_bus <= 0; + recurse_count <= 0; + char_reg <= 0; + pc_cnt <= 0; + next_set_buffer <= 0; + end else begin + case (state) + STATE_IDLE: begin + if (start) begin + state <= STATE_START_INIT; + match_bus <= 0; + end else if (char_valid) begin + char_reg <= char_in; + pc_cnt <= 0; + next_set_buffer <= 0; + state <= STATE_CHAR_MATCH; + end else if (end_of_str) begin + pc_cnt <= 0; + state <= STATE_END_OF_STR; + end + end + + STATE_START_INIT: begin + active_candidates <= 256'd1; // Start at Address 0 (the split chain) + recurse_count <= 0; + pc_cnt <= 0; + recurse_changed <= 0; + state <= STATE_EPSILON_RECURSE; + end + + STATE_CHAR_MATCH: begin + if (active_candidates[pc_cnt]) begin + if (p_any || (p_char != 0 && p_char == char_reg)) begin + if (p_next1 != 0) next_set_buffer[p_next1] <= 1'b1; + if (p_next2 != 0) next_set_buffer[p_next2] <= 1'b1; + end + end + + if (pc_cnt == 8'd255) begin + active_candidates <= next_set_buffer; + recurse_count <= 0; + pc_cnt <= 0; + recurse_changed <= 1; // Force at least one pass of epsilon recurse + state <= STATE_EPSILON_RECURSE; + end else begin + pc_cnt <= pc_cnt + 1; + end + end + + STATE_EPSILON_RECURSE: begin + // One pass over all nodes to expand epsilon transitions + if (active_candidates[pc_cnt] && p_char == 0 && !p_any && !p_term) begin + active_candidates[pc_cnt] <= 1'b0; // Node consumed + if (p_next1 != 0) active_candidates[p_next1] <= 1'b1; + if (p_next2 != 0) active_candidates[p_next2] <= 1'b1; + recurse_changed <= 1; + end + + if (pc_cnt == 8'd255) begin + if (recurse_count == 6'd63 || !recurse_changed) begin + state <= STATE_IDLE; + end else begin + recurse_count <= recurse_count + 1; + pc_cnt <= 0; + recurse_changed <= 0; + end + end else begin + pc_cnt <= pc_cnt + 1; + end + end + + STATE_END_OF_STR: begin + if (active_candidates[pc_cnt] && p_term) begin + match_bus[p_mid] <= 1'b1; + end + + if (pc_cnt == 8'd255) begin + state <= STATE_IDLE; + end else begin + pc_cnt <= pc_cnt + 1; + end + end + + default: state <= STATE_IDLE; + endcase + end + end + +endmodule