commit 907199802749d357c7f9a12bdb596fee78e5f6a7
parent a9386b4caec8fcf9c2b7545e2be8b251cdf1af26
Author: yash modi <yash3108m@gmail.com>
Date: Sun, 29 Mar 2026 16:27:41 +0530
Week 2: Complete Verilog Emitter Optimization (Part 1: Initial definitions)
Diffstat:
| M | src/emitter.cpp | | | 169 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 169 insertions(+), 0 deletions(-)
diff --git a/src/emitter.cpp b/src/emitter.cpp
@@ -398,3 +398,172 @@ module uart_rx #(
end
STOP_BIT: begin
if (clk_count < CLKS_PER_BIT-1) begin
+ clk_count <= clk_count + 1;
+ end else begin
+ if (rx == 1'b1) rx_ready <= 1'b1;
+ state <= IDLE;
+ end
+ end
+ endcase
+ end
+endmodule
+)";
+}
+
+// =============================================================================
+// emitUARTTX - uart_tx.v
+// =============================================================================
+void Emitter::emitUARTTX(const std::filesystem::path &outputDir)
+{
+ auto filePath = outputDir / "uart_tx.v";
+ std::ofstream out(filePath);
+ out.exceptions(std::ofstream::failbit | std::ofstream::badbit);
+
+ out << "`timescale 1ns / 1ps\n\n";
+ out << R"(
+module uart_tx #(
+ parameter CLKS_PER_BIT = 868 // 100 MHz / 115200 baud
+)(
+ input wire clk,
+ input wire rst,
+ input wire [7:0] tx_data,
+ input wire tx_start,
+ output reg tx_busy,
+ output reg tx
+);
+ localparam S_IDLE = 3'd0;
+ localparam S_START_BIT = 3'd1;
+ localparam S_DATA_BITS = 3'd2;
+ localparam S_STOP_BIT = 3'd3;
+
+ reg [2:0] state = S_IDLE;
+ reg [9:0] clk_cnt = 10'd0;
+ reg [2:0] bit_idx = 3'd0;
+ reg [7:0] tx_shift = 8'd0;
+
+ always @(posedge clk) begin
+ if (rst) begin
+ state <= S_IDLE;
+ tx <= 1'b1;
+ tx_busy <= 1'b0;
+ clk_cnt <= 10'd0;
+ bit_idx <= 3'd0;
+ tx_shift <= 8'd0;
+ end else begin
+ case (state)
+ S_IDLE: begin
+ tx <= 1'b1;
+ tx_busy <= 1'b0;
+ clk_cnt <= 10'd0;
+ bit_idx <= 3'd0;
+ if (tx_start) begin
+ tx_shift <= tx_data;
+ tx_busy <= 1'b1;
+ state <= S_START_BIT;
+ end
+ end
+ S_START_BIT: begin
+ tx <= 1'b0;
+ if (clk_cnt < CLKS_PER_BIT - 1)
+ clk_cnt <= clk_cnt + 1;
+ else begin
+ clk_cnt <= 10'd0;
+ state <= S_DATA_BITS;
+ end
+ end
+ S_DATA_BITS: begin
+ tx <= tx_shift[0];
+ if (clk_cnt < CLKS_PER_BIT - 1)
+ clk_cnt <= clk_cnt + 1;
+ else begin
+ clk_cnt <= 10'd0;
+ tx_shift <= tx_shift >> 1;
+ if (bit_idx < 7)
+ bit_idx <= bit_idx + 1;
+ else begin
+ bit_idx <= 3'd0;
+ state <= S_STOP_BIT;
+ end
+ end
+ end
+ S_STOP_BIT: begin
+ tx <= 1'b1;
+ if (clk_cnt < CLKS_PER_BIT - 1)
+ clk_cnt <= clk_cnt + 1;
+ else begin
+ clk_cnt <= 10'd0;
+ state <= S_IDLE;
+ end
+ end
+ default: state <= S_IDLE;
+ endcase
+ end
+ end
+endmodule
+)";
+}
+
+// =============================================================================
+// emitFIFO - uart_rx_fifo.v
+// =============================================================================
+void Emitter::emitFIFO(const std::filesystem::path &outputDir)
+{
+ auto filePath = outputDir / "uart_rx_fifo.v";
+ std::ofstream out(filePath);
+ out.exceptions(std::ofstream::failbit | std::ofstream::badbit);
+
+ out << "`timescale 1ns / 1ps\n\n";
+ out << R"(
+module uart_rx_fifo #(
+ parameter DEPTH_LOG2 = 4 // depth = 2^DEPTH_LOG2 = 16
+)(
+ input wire clk,
+ input wire rst,
+ input wire [7:0] wr_data,
+ input wire wr_en,
+ output wire full,
+ output wire [7:0] rd_data,
+ input wire rd_en,
+ output wire empty
+);
+ localparam DEPTH = 1 << DEPTH_LOG2;
+
+ reg [7:0] mem [0:DEPTH-1];
+ reg [DEPTH_LOG2-1:0] wr_ptr = {DEPTH_LOG2{1'b0}};
+ reg [DEPTH_LOG2-1:0] rd_ptr = {DEPTH_LOG2{1'b0}};
+ reg [DEPTH_LOG2 :0] count = {(DEPTH_LOG2+1){1'b0}};
+
+ assign full = (count == DEPTH[DEPTH_LOG2:0]);
+ assign empty = (count == {(DEPTH_LOG2+1){1'b0}});
+ assign rd_data = mem[rd_ptr];
+
+ always @(posedge clk) begin
+ if (rst) begin
+ wr_ptr <= {DEPTH_LOG2{1'b0}};
+ rd_ptr <= {DEPTH_LOG2{1'b0}};
+ count <= {(DEPTH_LOG2+1){1'b0}};
+ end else begin
+ if (wr_en && !full && rd_en && !empty) begin
+ mem[wr_ptr] <= wr_data;
+ wr_ptr <= wr_ptr + 1;
+ rd_ptr <= rd_ptr + 1;
+ end else if (wr_en && !full) begin
+ mem[wr_ptr] <= wr_data;
+ wr_ptr <= wr_ptr + 1;
+ count <= count + 1;
+ end else if (rd_en && !empty) begin
+ rd_ptr <= rd_ptr + 1;
+ count <= count - 1;
+ end
+ end
+ end
+endmodule
+)";
+}
+
+// =============================================================================
+// emitTopFPGA - top_fpga.v
+// =============================================================================
+void Emitter::emitTopFPGA(const std::vector<std::unique_ptr<NFA>> &nfas, const std::filesystem::path &outputDir)
+{
+ auto filePath = outputDir / "top_fpga.v";