commit 856f6b7b5f181faa34d3647ba0e1a7c714eba4d1
parent 95ad58a8359cbd2ad7cb090aba50c641410c0418
Author: yash modi <yash3108m@gmail.com>
Date: Thu, 23 Apr 2026 02:55:42 +0530
Week 6: Verilog NFA generation for example regexes and project specifications (Part 3: Finalizing)
Diffstat:
7 files changed, 315 insertions(+), 24 deletions(-)
diff --git a/output-eg/nfa_4.v b/output-eg/nfa_4.v
@@ -8,7 +8,8 @@ module nfa_4 (
input wire start,
input wire end_of_str,
input wire [7:0] char_in,
- output reg match
+ output reg match,
+ output wire active
);
// One-hot state register
@@ -16,9 +17,9 @@ module nfa_4 (
wire [3:0] next_state;
assign next_state[0] = 1'b0;
- assign next_state[1] = (state_reg[0] && (char_in == 8'd97));
- assign next_state[2] = (state_reg[1] && (char_in == 8'd98));
- assign next_state[3] = (state_reg[2] && (char_in == 8'd99));
+ assign next_state[1] = (state_reg[0] && (char_in == 8'd102));
+ assign next_state[2] = (state_reg[1] && (char_in == 8'd108));
+ assign next_state[3] = (state_reg[1] && (char_in == 8'd121)) | (state_reg[2] && (char_in == 8'd121));
always @(posedge clk) begin
if (rst || start) begin
@@ -42,4 +43,7 @@ module nfa_4 (
end
end
+ // Active logic: high if any state other than state 0 is active
+ assign active = |state_reg[3:1];
+
endmodule
diff --git a/output-eg/nfa_5.v b/output-eg/nfa_5.v
@@ -8,19 +8,26 @@ module nfa_5 (
input wire start,
input wire end_of_str,
input wire [7:0] char_in,
- output reg match
+ output reg match,
+ output wire active
);
// One-hot state register
- reg [5:0] state_reg;
- wire [5:0] next_state;
+ reg [11:0] state_reg;
+ wire [11:0] next_state;
assign next_state[0] = 1'b0;
- assign next_state[1] = (state_reg[0] && (char_in == 8'd97)) | (state_reg[1] && (char_in == 8'd97)) | (state_reg[2] && (char_in == 8'd97));
- assign next_state[2] = (state_reg[0] && (char_in == 8'd98)) | (state_reg[1] && (char_in == 8'd98)) | (state_reg[2] && (char_in == 8'd98));
- assign next_state[3] = (state_reg[0] && (char_in == 8'd99)) | (state_reg[1] && (char_in == 8'd99)) | (state_reg[2] && (char_in == 8'd99));
- assign next_state[4] = (state_reg[3] && (char_in == 8'd100)) | (state_reg[4] && (char_in == 8'd100)) | (state_reg[5] && (char_in == 8'd100));
- assign next_state[5] = (state_reg[3] && (char_in == 8'd101)) | (state_reg[4] && (char_in == 8'd101)) | (state_reg[5] && (char_in == 8'd101));
+ assign next_state[1] = (state_reg[0] && (char_in == 8'd97));
+ assign next_state[2] = (state_reg[1] && (char_in == 8'd112));
+ assign next_state[3] = (state_reg[2] && (char_in == 8'd112));
+ assign next_state[4] = (state_reg[3] && (char_in == 8'd108));
+ assign next_state[5] = (state_reg[4] && (char_in == 8'd101));
+ assign next_state[6] = (state_reg[0] && (char_in == 8'd111));
+ assign next_state[7] = (state_reg[6] && (char_in == 8'd114));
+ assign next_state[8] = (state_reg[7] && (char_in == 8'd97));
+ assign next_state[9] = (state_reg[8] && (char_in == 8'd110));
+ assign next_state[10] = (state_reg[9] && (char_in == 8'd103));
+ assign next_state[11] = (state_reg[10] && (char_in == 8'd101));
always @(posedge clk) begin
if (rst || start) begin
@@ -37,11 +44,14 @@ module nfa_5 (
match <= 1'b0;
end else if (en) begin
if (end_of_str) begin
- match <= (|{state_reg[4], state_reg[5]});
+ match <= (|{state_reg[5], state_reg[11]});
end else begin
match <= 1'b0;
end
end
end
+ // Active logic: high if any state other than state 0 is active
+ assign active = |state_reg[11:1];
+
endmodule
diff --git a/output-eg/nfa_6.v b/output-eg/nfa_6.v
@@ -0,0 +1,56 @@
+`timescale 1ns / 1ps
+
+// NFA for regex index 6
+module nfa_6 (
+ input wire clk,
+ input wire en,
+ input wire rst,
+ input wire start,
+ input wire end_of_str,
+ input wire [7:0] char_in,
+ output reg match,
+ output wire active
+);
+
+ // One-hot state register
+ reg [10:0] state_reg;
+ wire [10:0] next_state;
+
+ assign next_state[0] = 1'b0;
+ assign next_state[1] = (state_reg[0] && (char_in == 8'd114));
+ assign next_state[2] = (state_reg[1] && (char_in == 8'd101));
+ assign next_state[3] = (state_reg[2] && (char_in == 8'd100));
+ assign next_state[4] = (state_reg[0] && (char_in == 8'd98));
+ assign next_state[5] = (state_reg[4] && (char_in == 8'd108));
+ assign next_state[6] = (state_reg[5] && (char_in == 8'd117));
+ assign next_state[7] = (state_reg[6] && (char_in == 8'd101));
+ assign next_state[8] = (state_reg[3] && (char_in == 8'd99)) | (state_reg[7] && (char_in == 8'd99));
+ assign next_state[9] = (state_reg[8] && (char_in == 8'd97));
+ assign next_state[10] = (state_reg[9] && (char_in == 8'd114));
+
+ always @(posedge clk) begin
+ if (rst || start) begin
+ // Reset to start state (one-hot)
+ state_reg <= 1 << 0;
+ end else if (en) begin
+ state_reg <= next_state;
+ end
+ end
+
+ // Match logic: asserted on cycle following end_of_str
+ always @(posedge clk) begin
+ if (rst || start) begin
+ match <= 1'b0;
+ end else if (en) begin
+ if (end_of_str) begin
+ match <= state_reg[10];
+ end else begin
+ match <= 1'b0;
+ end
+ end
+ end
+
+ // Active logic: high if any state other than state 0 is active
+ assign active = |state_reg[10:1];
+
+endmodule
diff --git a/output-eg/nfa_7.v b/output-eg/nfa_7.v
@@ -0,0 +1,50 @@
+`timescale 1ns / 1ps
+
+// NFA for regex index 7
+module nfa_7 (
+ input wire clk,
+ input wire en,
+ input wire rst,
+ input wire start,
+ input wire end_of_str,
+ input wire [7:0] char_in,
+ output reg match,
+ output wire active
+);
+
+ // One-hot state register
+ reg [4:0] state_reg;
+ wire [4:0] next_state;
+
+ assign next_state[0] = 1'b0;
+ assign next_state[1] = (state_reg[0] && (char_in == 8'd108));
+ assign next_state[2] = (state_reg[1] && (char_in == 8'd111));
+ assign next_state[3] = (state_reg[2] && (char_in == 8'd108)) | (state_reg[4] && (char_in == 8'd108));
+ assign next_state[4] = (state_reg[3] && (char_in == 8'd111));
+
+ always @(posedge clk) begin
+ if (rst || start) begin
+ // Reset to start state (one-hot)
+ state_reg <= 1 << 0;
+ end else if (en) begin
+ state_reg <= next_state;
+ end
+ end
+
+ // Match logic: asserted on cycle following end_of_str
+ always @(posedge clk) begin
+ if (rst || start) begin
+ match <= 1'b0;
+ end else if (en) begin
+ if (end_of_str) begin
+ match <= (|{state_reg[2], state_reg[4]});
+ end else begin
+ match <= 1'b0;
+ end
+ end
+ end
+
+ // Active logic: high if any state other than state 0 is active
+ assign active = |state_reg[4:1];
+
+endmodule
diff --git a/output-eg/nfa_8.v b/output-eg/nfa_8.v
@@ -0,0 +1,50 @@
+`timescale 1ns / 1ps
+
+// NFA for regex index 8
+module nfa_8 (
+ input wire clk,
+ input wire en,
+ input wire rst,
+ input wire start,
+ input wire end_of_str,
+ input wire [7:0] char_in,
+ output reg match,
+ output wire active
+);
+
+ // One-hot state register
+ reg [4:0] state_reg;
+ wire [4:0] next_state;
+
+ assign next_state[0] = 1'b0;
+ assign next_state[1] = (state_reg[0] && (char_in == 8'd103));
+ assign next_state[2] = (state_reg[1] && (char_in == 8'd111));
+ assign next_state[3] = (state_reg[2] && (char_in == 8'd111)) | (state_reg[4] && (char_in == 8'd111));
+ assign next_state[4] = (state_reg[3] && (char_in == 8'd100));
+
+ always @(posedge clk) begin
+ if (rst || start) begin
+ // Reset to start state (one-hot)
+ state_reg <= 1 << 0;
+ end else if (en) begin
+ state_reg <= next_state;
+ end
+ end
+
+ // Match logic: asserted on cycle following end_of_str
+ always @(posedge clk) begin
+ if (rst || start) begin
+ match <= 1'b0;
+ end else if (en) begin
+ if (end_of_str) begin
+ match <= state_reg[4];
+ end else begin
+ match <= 1'b0;
+ end
+ end
+ end
+
+ // Active logic: high if any state other than state 0 is active
+ assign active = |state_reg[4:1];
+
+endmodule
diff --git a/output-eg/nfa_9.v b/output-eg/nfa_9.v
@@ -0,0 +1,51 @@
+`timescale 1ns / 1ps
+
+// NFA for regex index 9
+module nfa_9 (
+ input wire clk,
+ input wire en,
+ input wire rst,
+ input wire start,
+ input wire end_of_str,
+ input wire [7:0] char_in,
+ output reg match,
+ output wire active
+);
+
+ // One-hot state register
+ reg [5:0] state_reg;
+ wire [5:0] next_state;
+
+ assign next_state[0] = 1'b0;
+ assign next_state[1] = (state_reg[0] && (char_in == 8'd104));
+ assign next_state[2] = (state_reg[1] && (char_in == 8'd101));
+ assign next_state[3] = (state_reg[0] && (char_in == 8'd108)) | (state_reg[2] && (char_in == 8'd108));
+ assign next_state[4] = (state_reg[3] && (char_in == 8'd108));
+ assign next_state[5] = (state_reg[4] && (char_in == 8'd111));
+
+ always @(posedge clk) begin
+ if (rst || start) begin
+ // Reset to start state (one-hot)
+ state_reg <= 1 << 0;
+ end else if (en) begin
+ state_reg <= next_state;
+ end
+ end
+
+ // Match logic: asserted on cycle following end_of_str
+ always @(posedge clk) begin
+ if (rst || start) begin
+ match <= 1'b0;
+ end else if (en) begin
+ if (end_of_str) begin
+ match <= state_reg[5];
+ end else begin
+ match <= 1'b0;
+ end
+ end
+ end
+
+ // Active logic: high if any state other than state 0 is active
+ assign active = |state_reg[5:1];
+
+endmodule
diff --git a/output-eg/top_fpga.v b/output-eg/top_fpga.v
@@ -1,28 +1,28 @@
`timescale 1ns / 1ps
// =============================================================================
-// top_fpga.v — FPGA Top-Level
-// Regex count: 6
+// top_fpga.v - FPGA Top-Level
+// Regex count: 16
//
// Architecture:
// uart_rx → uart_rx_fifo → Control FSM → top (NFA engine)
// → uart_tx → host PC
//
// UART response packet (one line per newline received from host):
-// "MATCH=<6-bit binary> BYTES=<8 hex> HITS=<4 hex per regex,comma-sep>\r\n"
+// "MATCH=<16-bit binary> BYTES=<8 hex> HITS=<4 hex per regex,comma-sep>\r\n"
//
// Send '?' (0x3F) to query counters without feeding the NFA.
// =============================================================================
module top_fpga #(
- parameter NUM_REGEX = 6,
+ parameter NUM_REGEX = 16,
parameter CLKS_PER_BIT = 868 // 100 MHz / 115200 baud
)(
input wire clk,
input wire rst_btn,
input wire uart_rx_pin,
output wire uart_tx_pin,
- output reg [5:0] match_leds
+ output reg [15:0] match_leds
);
// UART RX
@@ -58,7 +58,7 @@ module top_fpga #(
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;
+ wire [15:0] match_bus;
top regex_engine (
.clk (clk),
@@ -144,7 +144,7 @@ module top_fpga #(
integer ri;
task build_response;
- input [5:0] mbits;
+ input [15:0] mbits;
input [31:0] bcount;
integer k;
begin : build_task
@@ -158,6 +158,16 @@ module top_fpga #(
tx_buf[p]=8'h48; p=p+1; // H
tx_buf[p]=8'h3D; p=p+1; // =
// match bits, MSB first
+ tx_buf[p] = (mbits[15]) ? 8'h31 : 8'h30; p=p+1;
+ tx_buf[p] = (mbits[14]) ? 8'h31 : 8'h30; p=p+1;
+ tx_buf[p] = (mbits[13]) ? 8'h31 : 8'h30; p=p+1;
+ tx_buf[p] = (mbits[12]) ? 8'h31 : 8'h30; p=p+1;
+ tx_buf[p] = (mbits[11]) ? 8'h31 : 8'h30; p=p+1;
+ tx_buf[p] = (mbits[10]) ? 8'h31 : 8'h30; p=p+1;
+ tx_buf[p] = (mbits[9]) ? 8'h31 : 8'h30; p=p+1;
+ tx_buf[p] = (mbits[8]) ? 8'h31 : 8'h30; p=p+1;
+ tx_buf[p] = (mbits[7]) ? 8'h31 : 8'h30; p=p+1;
+ tx_buf[p] = (mbits[6]) ? 8'h31 : 8'h30; p=p+1;
tx_buf[p] = (mbits[5]) ? 8'h31 : 8'h30; p=p+1;
tx_buf[p] = (mbits[4]) ? 8'h31 : 8'h30; p=p+1;
tx_buf[p] = (mbits[3]) ? 8'h31 : 8'h30; p=p+1;
@@ -222,6 +232,66 @@ module top_fpga #(
tx_buf[p]=hex_char(tmp16[11: 8]); p=p+1;
tx_buf[p]=hex_char(tmp16[ 7: 4]); p=p+1;
tx_buf[p]=hex_char(tmp16[ 3: 0]); p=p+1;
+ tx_buf[p]=8'h2C; p=p+1; // ','
+ tmp16 = match_count[6];
+ tx_buf[p]=hex_char(tmp16[15:12]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[11: 8]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[ 7: 4]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[ 3: 0]); p=p+1;
+ tx_buf[p]=8'h2C; p=p+1; // ','
+ tmp16 = match_count[7];
+ tx_buf[p]=hex_char(tmp16[15:12]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[11: 8]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[ 7: 4]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[ 3: 0]); p=p+1;
+ tx_buf[p]=8'h2C; p=p+1; // ','
+ tmp16 = match_count[8];
+ tx_buf[p]=hex_char(tmp16[15:12]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[11: 8]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[ 7: 4]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[ 3: 0]); p=p+1;
+ tx_buf[p]=8'h2C; p=p+1; // ','
+ tmp16 = match_count[9];
+ tx_buf[p]=hex_char(tmp16[15:12]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[11: 8]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[ 7: 4]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[ 3: 0]); p=p+1;
+ tx_buf[p]=8'h2C; p=p+1; // ','
+ tmp16 = match_count[10];
+ tx_buf[p]=hex_char(tmp16[15:12]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[11: 8]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[ 7: 4]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[ 3: 0]); p=p+1;
+ tx_buf[p]=8'h2C; p=p+1; // ','
+ tmp16 = match_count[11];
+ tx_buf[p]=hex_char(tmp16[15:12]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[11: 8]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[ 7: 4]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[ 3: 0]); p=p+1;
+ tx_buf[p]=8'h2C; p=p+1; // ','
+ tmp16 = match_count[12];
+ tx_buf[p]=hex_char(tmp16[15:12]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[11: 8]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[ 7: 4]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[ 3: 0]); p=p+1;
+ tx_buf[p]=8'h2C; p=p+1; // ','
+ tmp16 = match_count[13];
+ tx_buf[p]=hex_char(tmp16[15:12]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[11: 8]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[ 7: 4]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[ 3: 0]); p=p+1;
+ tx_buf[p]=8'h2C; p=p+1; // ','
+ tmp16 = match_count[14];
+ tx_buf[p]=hex_char(tmp16[15:12]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[11: 8]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[ 7: 4]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[ 3: 0]); p=p+1;
+ tx_buf[p]=8'h2C; p=p+1; // ','
+ tmp16 = match_count[15];
+ tx_buf[p]=hex_char(tmp16[15:12]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[11: 8]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[ 7: 4]); p=p+1;
+ tx_buf[p]=hex_char(tmp16[ 3: 0]); p=p+1;
tx_buf[p]=8'h0D; p=p+1; // CR
tx_buf[p]=8'h0A; p=p+1; // LF
tx_len = p[6:0];
@@ -244,7 +314,7 @@ module top_fpga #(
reg [3:0] state = S_RESET_NFA;
- reg [5:0] snap_match = 6'b0;
+ reg [15:0] snap_match = 16'b0;
reg [31:0] snap_bytes = 32'd0;
integer k;
@@ -256,7 +326,7 @@ module top_fpga #(
if (rst_btn) begin
state <= S_RESET_NFA;
- match_leds <= 6'b0;
+ match_leds <= 16'b0;
byte_count <= 32'd0;
for (k = 0; k < 16; k = k + 1)
match_count[k] <= 16'd0;
@@ -308,7 +378,7 @@ module top_fpga #(
snap_match <= match_bus;
snap_bytes <= byte_count;
match_leds <= match_bus;
- for (k = 0; k < 6; k = k + 1)
+ for (k = 0; k < 16; k = k + 1)
if (match_bus[k]) match_count[k] <= match_count[k] + 16'd1;
state <= S_TX_ARM;
end
@@ -329,7 +399,7 @@ module top_fpga #(
end
S_QUERY_TX: begin
- build_response(6'b0, byte_count);
+ build_response(16'b0, byte_count);
tx_send <= 1'b1;
state <= S_TX_WAIT;
end