dakies/OSS_Verilog huggingface dataset:
module traffic_light (
    input clk,
    input rst_n,
    input pass_request,
    output reg [7:0] clock,
    output reg red,
    output reg yellow,
    output reg green
);

    // State parameters
    parameter idle      = 2'b00,
              s1_red    = 2'b01,
              s2_yellow = 2'b10,
              s3_green  = 2'b11;

    // Internal counter and state
    reg [7:0] cnt;
    reg [1:0] state;

    // Next state logic
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            state <= idle;
            cnt <= 8'd60; // Start with green light duration
        end else begin
            case (state)
                idle: begin
                    state <= s1_red;
                end
                s1_red: begin
                    if (cnt == 0) begin
                        state <= s3_green;
                        cnt <= 8'd60; // Green light duration
                    end
                end
                s2_yellow: begin
                    if (cnt == 0) begin
                        state <= s1_red;
                        cnt <= 8'd10; // Red light duration
                    end
                end
                s3_green: begin
                    if (cnt == 0 || (cnt > 8'd10 && pass_request)) begin
                        state <= s2_yellow;
                        cnt <= 8'd5; // Yellow light duration
                    end
                end
                default: state <= idle;
            endcase
        end
    end

    // Counter logic
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            cnt <= 8'd60; // Reset to green light duration
        end else if (state == s3_green && pass_request && cnt > 8'd10) begin
            cnt <= 8'd10; // Shorten green if pedestrian button is pressed
        end else if (cnt > 0) begin
            cnt <= cnt - 1; // Decrement counter
        end
    end

    // Output logic
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            red <= 1'b0;
            yellow <= 1'b0;
            green <= 1'b0;
        end else begin
            // Set outputs based on state
            red <= (state == s1_red);
            yellow <= (state == s2_yellow);
            green <= (state == s3_green);
        end
    end

    // Assign internal counter to output
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            clock <= 8'd0;
        end else begin
            clock <= cnt;
        end
    end

endmodule
module fsm (
    input IN,
    input CLK,
    input RST,
    output reg MATCH
);

    // Define state identifiers
    parameter [2:0] S0 = 3'b000, // Start state (or state after reset)
                     S1 = 3'b001, // After seeing '1'
                     S2 = 3'b010, // After seeing '10'
                     S3 = 3'b011, // After seeing '100'
                     S4 = 3'b100, // After seeing '1001'
                     S5 = 3'b101; // After seeing '10011'

    // State variable
    reg [2:0] current_state, next_state;

    // Sequential logic for state transitions
    always @(posedge CLK or posedge RST) begin
        if (RST)
            current_state <= S0;
        else
            current_state <= next_state;
    end

    // Combinational logic for next state and MATCH output
    always @(*) begin
        // Default assignment
        MATCH = 0;
        next_state = current_state; // Stay in the current state by default

        case (current_state)
            S0: begin
                if (IN) next_state = S1;
            end
            S1: begin
                if (!IN) next_state = S2;
            end
            S2: begin
                if (!IN) next_state = S3;
                else next_state = S1;
            end
            S3: begin
                if (IN) next_state = S4;
                else next_state = S2;
            end
            S4: begin
                if (IN) begin
                    next_state = S5;
                    MATCH = 1; // MATCH output is set to '1' upon reaching S5
                end else begin
                    next_state = S2;
                end
            end
            S5: begin
                if (IN) next_state = S1;
                else next_state = S2;
            end
            default: next_state = S0;
        endcase
    end

endmodule
module width_8to16 (
    input wire clk,
    input wire rst_n,
    input wire valid_in,
    input wire [7:0] data_in,
    output reg valid_out,
    output reg [15:0] data_out
);

// Internal signal to hold the first 8-bit data and the flag to indicate its presence
reg [7:0] data_lock;
reg data_lock_valid;

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        // Reset state: clear registers and output
        data_out <= 16'b0;
        valid_out <= 1'b0;
        data_lock <= 8'b0;
        data_lock_valid <= 1'b0;
    end else begin
        if (valid_in) begin
            if (data_lock_valid) begin
                // If we already have a valid data_lock, concatenate and output
                data_out <= {data_lock, data_in};
                valid_out <= 1'b1;
                data_lock_valid <= 1'b0; // Reset the data_lock_valid flag
            end else begin
                // Store the first part of the data and wait for the next valid input
                data_lock <= data_in;
                data_lock_valid <= 1'b1;
                valid_out <= 1'b0; // Do not assert valid_out yet
            end
        end else if (!data_lock_valid) begin
            // If valid_in is low and we don't have a valid data_lock, keep outputs deasserted
            valid_out <= 1'b0;
        end
        // No else condition here, if valid_in is low but data_lock_valid is true, we wait.
    end
end

endmodule
module JC_counter (
    input clk,
    input rst_n,
    output reg [63:0] Q
);

    // Johnson counter update logic on clock edge or reset
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            // Active-low reset to zero
            Q <= 64'b0;
        end else begin
            // Check the least significant bit to determine increment or decrement
            if (Q[0] == 1'b0) begin
                // Shift left and append 1 at LSB (note: MSB comes from the inverted LSB)
                Q <= {Q[62:0], ~Q[63]};
            end else begin
                // Shift left and append 0 at LSB (note: MSB comes from the inverted LSB)
                Q <= {Q[62:0], ~Q[63]};
            end
        end
    end

endmodule
module adder_pipe_64bit(
    input clk,
    input rst_n,
    input i_en,
    input [63:0] adda,
    input [63:0] addb,
    output reg [64:0] result,
    output reg o_en
);

    // Define the pipeline stages registers
    reg [63:0] stage0_adda, stage0_addb;
    reg [63:0] stage1_adda, stage1_addb;
    reg [63:0] stage2_adda, stage2_addb;
    reg [64:0] stage3_sum;
    
    // Define the enable signals for each stage
    reg stage0_en, stage1_en, stage2_en, stage3_en;
    
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            // Reset all pipeline registers and enable signals
            {stage0_adda, stage0_addb, stage1_adda, stage1_addb, stage2_adda, stage2_addb, stage3_sum} <= 0;
            {stage0_en, stage1_en, stage2_en, stage3_en, o_en} <= 0;
            result <= 0;
        end else begin
            // Pipeline stage 0 (input latching)
            if (i_en) begin
                stage0_adda <= adda;
                stage0_addb <= addb;
                stage0_en <= 1'b1;
            end else begin
                stage0_en <= 1'b0;
            end
            
            // Pipeline stage 1 (propagation stage)
            if (stage0_en) begin
                stage1_adda <= stage0_adda;
                stage1_addb <= stage0_addb;
                stage1_en <= 1'b1;
            end else begin
                stage1_en <= 1'b0;
            end
            
            // Pipeline stage 2 (propagation stage)
            if (stage1_en) begin
                stage2_adda <= stage1_adda;
                stage2_addb <= stage1_addb;
                stage2_en <= 1'b1;
            end else begin
                stage2_en <= 1'b0;
            end
            
            // Pipeline stage 3 (addition stage)
            if (stage2_en) begin
                stage3_sum <= stage2_adda + stage2_addb;
                stage3_en <= 1'b1;
            end else begin
                stage3_en <= 1'b0;
            end
            
            // Output result
            if (stage3_en) begin
                result <= stage3_sum;
                o_en <= 1'b1;
            end else begin
                o_en <= 1'b0;
            end
        end
    end

endmodule
module right_shifter(
    input wire clk,
    input wire d,
    output reg [7:0] q
);

    // Initialize the 'q' register to 0
    initial begin
        q = 8'b00000000;
    end

    // On each rising edge of the clock, shift 'q' right and insert 'd' at MSB
    always @(posedge clk) begin
        q <= {d, q[7:1]};
    end

endmodule
module serial2parallel (
    input wire clk,
    input wire rst_n,
    input wire din_serial,
    input wire din_valid,
    output reg [7:0] dout_parallel,
    output reg dout_valid
);

    // 3-bit counter to count the number of bits received
    reg [2:0] cnt;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            // Reset the counter and output registers
            cnt <= 0;
            dout_parallel <= 0;
            dout_valid <= 0;
        end else if (din_valid) begin
            // Shift in the serial data into the MSB of dout_parallel
            dout_parallel <= (dout_parallel << 1) | din_serial;
            
            // Increment the counter
            cnt <= cnt + 1;

            // Check if 8 bits have been received
            if (cnt == 7) begin
                // Set the valid output high as all 8 bits are received
                dout_valid <= 1;
                // Reset the counter to start for the next byte
                cnt <= 0;
            end else begin
                // Keep the valid output low as all 8 bits are not yet received
                dout_valid <= 0;
            end
        end else begin
            // If din_valid is not high, do not shift in new data and keep dout_valid low
            dout_valid <= 0;
        end
    end

endmodule
module multi_16bit(
    input clk,
    input rst_n,
    input start,
    input [15:0] ain,
    input [15:0] bin,
    output reg [31:0] yout,
    output reg done
);

    reg [31:0] product;      // Accumulated product
    reg [15:0] multiplicand; // Register for the multiplicand
    reg [15:0] multiplier;   // Register for the multiplier
    reg [4:0] i;             // Shift count register (4 bits for 0-16 range)
    reg done_r;              // Internal completion flag

    always @(posedge clk or negedge rst_n) begin
        if (~rst_n) begin
            // Reset the registers and flags
            i <= 5'b0;
            multiplicand <= 16'b0;
            multiplier <= 16'b0;
            product <= 32'b0;
            done_r <= 1'b0;
            done <= 1'b0;
            yout <= 32'b0;
        end else begin
            if (start) begin
                if (i < 17) begin
                    if (i == 0) begin
                        // Load the registers
                        multiplicand <= ain;
                        multiplier <= bin;
                        product <= 32'b0; // Clear the product register
                    end else begin
                        // Shift and accumulate
                        if (multiplicand[0]) begin
                            product <= product + (multiplier << (i - 1));
                        end
                        multiplicand <= multiplicand >> 1; // Shift right for the next cycle
                    end
                    i <= i + 1;
                end

                // Set the done flag when the operation is complete
                if (i == 16) begin
                    done_r <= 1'b1;
                    yout <= product; // Assign the accumulated product to the output
                end else if (i == 17) begin
                    // Clear the done flag for the next operation
                    done_r <= 1'b0;
                    i <= 0; // Reset the shift count register for the next operation
                end
            end else begin
                // Clear the shift count register if start is not active
                i <= 0;
                done_r <= 1'b0;
            end
            done <= done_r; // Output the done status
        end
    end

endmodule
module multi_pipe_4bit #(parameter size = 4) (
    input clk,
    input rst_n,
    input [size-1:0] mul_a,
    input [size-1:0] mul_b,
    output reg [(2*size)-1:0] mul_out
);

    // Intermediate product registers for pipeline stages
    reg [size-1:0] stage1_mul_a[size-1:0];
    reg [(2*size)-1:0] stage1_product[size-1:0];
    reg [(2*size)-1:0] stage2_sum;

    // Calculate partial products and store them in pipeline registers
    integer i;
    always @(posedge clk or negedge rst_n) begin
        if (~rst_n) begin
            // Reset all pipeline registers
            for (i = 0; i < size; i = i + 1) begin
                stage1_mul_a[i] <= 0;
                stage1_product[i] <= 0;
            end
            stage2_sum <= 0;
            mul_out <= 0;
        end else begin
            // First pipeline stage: calculate and store partial products
            for (i = 0; i < size; i = i + 1) begin
                stage1_mul_a[i] <= mul_a;
                if (mul_b[i]) begin
                    stage1_product[i] <= mul_a << i;
                end else begin
                    stage1_product[i] <= 0;
                end
            end

            // Second pipeline stage: sum the partial products
            stage2_sum <= stage1_product[0];
            for (i = 1; i < size; i = i + 1) begin
                stage2_sum <= stage2_sum + stage1_product[i];
            end

            // Update the output register with the final product
            mul_out <= stage2_sum;
        end
    end

endmodule
module freq_div(
    input CLK_in,  // Input clock signal at 100MHz
    input RST,     // Reset signal (active high)
    output reg CLK_50,   // Output clock signal at 50MHz
    output reg CLK_10,   // Output clock signal at 10MHz
    output reg CLK_1     // Output clock signal at 1MHz
);

    // Counter for the 10MHz clock
    reg [3:0] cnt_10 = 0;  // 5 stages (0-4), toggles at 5
    // Counter for the 1MHz clock
    reg [5:0] cnt_100 = 0; // 50 stages (0-49), toggles at 50

    // Frequency division for 50MHz
    always @(posedge CLK_in or posedge RST) begin
        if (RST) begin
            CLK_50 <= 0;
        end else begin
            CLK_50 <= ~CLK_50; // Toggles each clock cycle (50MHz)
        end
    end

    // Frequency division for 10MHz
    always @(posedge CLK_in or posedge RST) begin
        if (RST) begin
            cnt_10 <= 0;
            CLK_10 <= 0;
        end else begin
            if (cnt_10 == 4) begin
                cnt_10 <= 0;
                CLK_10 <= ~CLK_10; // Toggle the output clock
            end else begin
                cnt_10 <= cnt_10 + 1;
            end
        end
    end

    // Frequency division for 1MHz
    always @(posedge CLK_in or posedge RST) begin
        if (RST) begin
            cnt_100 <= 0;
            CLK_1 <= 0;
        end else begin
            if (cnt_100 == 49) begin
                cnt_100 <= 0;
                CLK_1 <= ~CLK_1; // Toggle the output clock
            end else begin
                cnt_100 <= cnt_100 + 1;
            end
        end
    end

endmodule
module counter_12 (
    input wire rst_n,       // Active low reset
    input wire clk,         // Clock signal
    input wire valid_count, // Enable counting
    output reg [3:0] out    // 4-bit count value
);

    always @(posedge clk or negedge rst_n) begin
        if (~rst_n) begin
            // Reset the counter to 0 when reset is active
            out <= 4'b0000;
        end else if (valid_count) begin
            // Only count when valid_count is high
            if (out == 4'd11) begin
                // Wrap around the counter after reaching 4'd11
                out <= 4'b0000;
            end else begin
                // Increment the counter
                out <= out + 1;
            end
        end
        // When valid_count is low, do nothing (counter is paused)
    end

endmodule
module edge_detect (
    input clk,
    input rst_n,
    input a,
    output reg rise,
    output reg down
);

    // Register to hold the previous value of 'a'
    reg a_prev;

    // Detect edges on the positive clock edge and when reset is not asserted
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            // On reset, clear the rise and down signals and the stored previous value of 'a'
            rise <= 0;
            down <= 0;
            a_prev <= 0;
        end else begin
            // On each clock edge, update the rise and down signals based on the current and previous values of 'a'
            rise <= (a_prev == 0) && (a == 1);  // Set 'rise' if 'a' was 0 and is now 1
            down <= (a_prev == 1) && (a == 0);  // Set 'down' if 'a' was 1 and is now 0
            a_prev <= a;  // Store the current value of 'a' for the next comparison
        end
    end

endmodule
module RAM #(
    parameter WIDTH = 6,
    parameter DEPTH = 8
)(
    input clk,
    input rst_n,
    input write_en,
    input [DEPTH-1:0] write_addr,
    input [WIDTH-1:0] write_data,
    input read_en,
    input [DEPTH-1:0] read_addr,
    output reg [WIDTH-1:0] read_data
);

    // Declare the RAM array
    reg [WIDTH-1:0] RAM [2**DEPTH-1:0];

    // Initialize the RAM array values to 0 on reset
    integer i;
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            for (i = 0; i < 2**DEPTH; i = i + 1) begin
                RAM[i] <= 6'b000000;
            end
        end
        else if (write_en) begin
            // Write operation
            RAM[write_addr] <= write_data;
        end
    end

    // Read operation
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            read_data <= 6'b000000;
        end
        else if (read_en) begin
            read_data <= RAM[read_addr];
        end
        else begin
            read_data <= 6'b000000; // Optionally clear read_data if not enabled
        end
    end

endmodule
module adder_8bit (
    input [7:0] a,
    input [7:0] b,
    input cin,
    output [7:0] sum,
    output cout
);

// Wire declarations for the carry bits between full adders
wire [6:0] carry;

// Instantiate the full adder for each bit
full_adder fa0 (
    .a(a[0]),
    .b(b[0]),
    .cin(cin),
    .sum(sum[0]),
    .cout(carry[0])
);

full_adder fa1 (
    .a(a[1]),
    .b(b[1]),
    .cin(carry[0]),
    .sum(sum[1]),
    .cout(carry[1])
);

full_adder fa2 (
    .a(a[2]),
    .b(b[2]),
    .cin(carry[1]),
    .sum(sum[2]),
    .cout(carry[2])
);

full_adder fa3 (
    .a(a[3]),
    .b(b[3]),
    .cin(carry[2]),
    .sum(sum[3]),
    .cout(carry[3])
);

full_adder fa4 (
    .a(a[4]),
    .b(b[4]),
    .cin(carry[3]),
    .sum(sum[4]),
    .cout(carry[4])
);

full_adder fa5 (
    .a(a[5]),
    .b(b[5]),
    .cin(carry[4]),
    .sum(sum[5]),
    .cout(carry[5])
);

full_adder fa6 (
    .a(a[6]),
    .b(b[6]),
    .cin(carry[5]),
    .sum(sum[6]),
    .cout(carry[6])
);

full_adder fa7 (
    .a(a[7]),
    .b(b[7]),
    .cin(carry[6]),
    .sum(sum[7]),
    .cout(cout)
);

endmodule
module multi_pipe_8bit (
    input          clk,
    input          rst_n,
    input          mul_en_in,
    input  [7:0]   mul_a,
    input  [7:0]   mul_b,
    output         mul_en_out,
    output [15:0]  mul_out
);

    reg [15:0] pipeline [2:0]; // 3-stage pipeline for partial products sum
    reg [7:0]  mul_a_reg, mul_b_reg; // Input registers
    reg        mul_en_in_reg, mul_en_out_reg; // Enable registers

    wire [15:0] partial_product [7:0]; // Array to hold partial products

    // Generate partial products
    genvar i;
    generate
        for (i = 0; i < 8; i = i + 1) begin : gen_partial_products
            assign partial_product[i] = mul_a_reg & {8{mul_b_reg[i]}};
        end
    endgenerate

    // Pipeline stages logic
    always @(posedge clk or negedge rst_n) begin
        if (~rst_n) begin
            mul_a_reg       <= 0;
            mul_b_reg       <= 0;
            mul_en_in_reg   <= 0;
            mul_en_out_reg  <= 0;
            pipeline[0]     <= 0;
            pipeline[1]     <= 0;
            pipeline[2]     <= 0;
        end else begin
            // Input registers update
            if (mul_en_in) begin
                mul_a_reg     <= mul_a;
                mul_b_reg     <= mul_b;
            end

            // Enable signal pipeline update
            mul_en_in_reg   <= mul_en_in; // Register input enable
            mul_en_out_reg  <= mul_en_in_reg; // Register output enable

            // First pipeline stage
            pipeline[0]     <= partial_product[0] + (partial_product[1] << 1);

            // Second pipeline stage
            pipeline[1]     <= pipeline[0] + (partial_product[2] << 2) + (partial_product[3] << 3);

            // Third pipeline stage, final sum
            pipeline[2]     <= pipeline[1] + (partial_product[4] << 4) + (partial_product[5] << 5) +
                               (partial_product[6] << 6) + (partial_product[7] << 7);
        end
    end

    // Output assignment
    assign mul_out = (mul_en_out_reg) ? pipeline[2] : 16'd0;
    assign mul_en_out = mul_en_out_reg;

endmodule
module parallel2serial (
    input         clk,
    input         rst_n,
    input  [3:0]  d,
    output reg    valid_out,
    output reg    dout
);

    // Internal 4-bit register to hold the input data
    reg [3:0] data;

    // 2-bit counter to keep track of the bit position
    reg [1:0] cnt;

    always @(posedge clk or negedge rst_n) begin
        if (~rst_n) begin
            // Asynchronous reset
            cnt <= 2'd0;
            valid_out <= 1'b0;
            dout <= 1'b0;
            data <= 4'd0;
        end else begin
            if (cnt == 2'd3) begin
                // Load new data and reset counter
                data <= d;
                cnt <= 2'd0;
                valid_out <= 1'b1; // Valid output on loading new data
            end else begin
                // Shift data and increment counter
                data <= {data[2:0], 1'b0};
                cnt <= cnt + 2'd1;
                valid_out <= 1'b0;
            end
            // Output the MSB of the data register
            dout <= data[3];
        end
    end

endmodule
module accu (
    input clk,
    input rst_n,
    input [7:0] data_in,
    input valid_in,
    output reg valid_out,
    output reg [9:0] data_out
);

reg [9:0] sum;
reg [1:0] count;

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        // Asynchronous reset: clear the sum, count, and output signals
        sum <= 10'd0;
        count <= 2'd0;
        valid_out <= 1'b0;
        data_out <= 10'd0;
    end else begin
        if (valid_in) begin
            // If a valid input is received, accumulate the sum and increment the count
            if (count < 3) begin
                sum <= sum + data_in;        // Accumulate the input data
                count <= count + 1'b1;       // Increment the count
                valid_out <= 1'b0;           // Keep valid_out low as accumulation is not complete
            end else begin
                // If we have received four inputs, output the accumulated sum
                sum <= sum + data_in;        // Add the last data input to the sum
                data_out <= sum + data_in;   // Output the accumulated sum
                valid_out <= 1'b1;           // Indicate that valid_out is ready
                sum <= 10'd0;                // Reset the sum for the next accumulation
                count <= 2'd0;               // Reset the count for the next accumulation
            end
        end else begin
            // If valid_in is not high, do not accumulate and set valid_out to 0
            valid_out <= 1'b0;
        end
    end
end

endmodule
module div_16bit(
    input wire [15:0] A,  // 16-bit dividend
    input wire [7:0] B,   // 8-bit divisor
    output wire [15:0] result, // 16-bit quotient
    output wire [15:0] odd  // 16-bit remainder
);

    // Intermediate wires to hold the results of each step
    wire [15:0] subtract_results[7:0];
    wire [7:0] compare_results;

    // Initial partial dividend (most significant bits of A)
    wire [7:0] partial_dividend;
    assign partial_dividend = A[15:8];

    // The subtraction and comparison at each step
    genvar i;
    generate
        for (i = 0; i < 8; i = i + 1) begin : div_step
            // Compare and subtract
            assign compare_results[i] = (partial_dividend >= B) ? 1'b1 : 1'b0;
            assign subtract_results[i] = (partial_dividend >= B) ? (partial_dividend - B) : partial_dividend;
            
            // Prepare next partial dividend for the next stage
            if (i < 7) begin
                assign partial_dividend = {subtract_results[i][6:0], A[7-i]};
            end
        end
    endgenerate

    // Combine the compare results to form the quotient
    assign result = {compare_results, A[7:0]};

    // The final remainder is the result of the last subtraction
    assign odd = {subtract_results[7], A[7:0]};

endmodule
module signal_generator (
    input wire clk,
    input wire rst_n,
    output reg [4:0] wave
);

    // State declaration
    reg state;

    // State definitions
    localparam STATE_UP = 1'b0;
    localparam STATE_DOWN = 1'b1;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            // Reset condition
            wave <= 5'b00000; // Initialize wave to 0
            state <= STATE_UP; // Start with incrementing state
        end else begin
            case (state)
                STATE_UP: begin
                    // Increment wave until it reaches 31
                    if (wave == 31) begin
                        state <= STATE_DOWN; // Change state to decrement
                    end else begin
                        wave <= wave + 1;
                    end
                end
                STATE_DOWN: begin
                    // Decrement wave until it reaches 0
                    if (wave == 0) begin
                        state <= STATE_UP; // Change state to increment
                    end else begin
                        wave <= wave - 1;
                    end
                end
                default: begin
                    // In case of an undefined state, reset to known state
                    state <= STATE_UP;
                    wave <= 5'b00000;
                end
            endcase
        end
    end

endmodule
module multi_booth_8bit (
    input wire clk,
    input wire reset,
    input wire [7:0] a,
    input wire [7:0] b,
    output reg [15:0] p,
    output reg rdy
);

    // Internal registers
    reg [7:0] multiplicand;
    reg [8:0] multiplier; // Extra bit for sign extension
    reg [3:0] ctr; // 4-bit counter since we are processing 2 bits at a time

    // Initialize the registers on reset
    always @(posedge clk or posedge reset) begin
        if (reset) begin
            multiplicand <= 0;
            multiplier <= {1'b0, b}; // Sign extend the multiplier
            p <= 0;
            ctr <= 0;
            rdy <= 0;
        end else begin
            // Check if the multiplication process is complete
            if (ctr < 4) begin
                case (multiplier[1:0]) // Radix-4 Booth Encoding
                    2'b01: p <= p + (multiplicand << (ctr * 2));
                    2'b10: p <= p - (multiplicand << (ctr * 2));
                    default: p <= p; // No operation for 00 and 11
                endcase

                // Prepare for the next iteration
                multiplier <= multiplier >> 2; // Consume the next 2 bits
                ctr <= ctr + 1; // Increment the counter
            end else begin
                rdy <= 1; // Indicate that the multiplication is done
            end
        end
    end

    // Sign extension handling for negative numbers
    always @(posedge clk) begin
        if (ctr == 0 && !rdy) begin
            multiplicand <= a[7] ? (~a + 1'b1) : a; // If negative, take 2's complement
        end
    end

endmodule
module pe(
    input clk,
    input rst,
    input [31:0] a,
    input [31:0] b,
    output reg [31:0] c
);

    // Temporary variable to hold the product of a and b
    wire [63:0] product;
    
    // Perform the multiplication of a and b
    assign product = a * b;
    
    always @(posedge clk or posedge rst) begin
        if (rst) begin
            // Reset the accumulator to 0 on reset signal
            c <= 32'd0;
        end else begin
            // Accumulate the product in the register c
            c <= c + product[31:0]; // Note: Truncating the product to 32 bits
        end
    end

endmodule
module alu (
    input [31:0] a,
    input [31:0] b,
    input [5:0] aluc,
    output reg [31:0] r,
    output zero,
    output reg carry,
    output reg negative,
    output reg overflow,
    output reg flag
);

    // Opcode parameters
    parameter ADD = 6'b100000;
    parameter ADDU = 6'b100001;
    parameter SUB = 6'b100010;
    parameter SUBU = 6'b100011;
    parameter AND = 6'b100100;
    parameter OR = 6'b100101;
    parameter XOR = 6'b100110;
    parameter NOR = 6'b100111;
    parameter SLT = 6'b101010;
    parameter SLTU = 6'b101011;
    parameter SLL = 6'b000000;
    parameter SRL = 6'b000010;
    parameter SRA = 6'b000011;
    parameter SLLV = 6'b000100;
    parameter SRLV = 6'b000110;
    parameter SRAV = 6'b000111;
    parameter LUI = 6'b001111;

    // Internal signals
    reg [31:0] res;
    wire signed [31:0] signed_a = a;
    wire signed [31:0] signed_b = b;
    wire [31:0] b_inv;
    wire [32:0] sum;   // For carry and overflow detection
    wire slt_set;

    // Calculate zero flag
    assign zero = (r == 32'b0);

    // Calculate SLT set condition
    assign slt_set = signed_a < signed_b;

    // Extended b inversion for SUB and SUBU
    assign b_inv = ~b + 1'b1;

    // 33-bit sum for carry and overflow detection
    assign sum = {1'b0, a} + (aluc == SUB || aluc == SUBU ? {1'b0, b_inv} : {1'b0, b}) + (aluc == SUB);

    always @(*) begin
        case (aluc)
            ADD, ADDU: begin
                res = a + b;
                carry = sum[32];
                overflow = (a[31] == b[31]) && (res[31] != a[31]);
            end
            SUB, SUBU: begin
                res = a - b;
                carry = !sum[32];
                overflow = (a[31] != b[31]) && (res[31] != a[31]);
            end
            AND: res = a & b;
            OR: res = a | b;
            XOR: res = a ^ b;
            NOR: res = ~(a | b);
            SLT: begin
                res = slt_set;
                flag = slt_set;
            end
            SLTU: begin
                res = a < b;
                flag = a < b;
            end
            SLL: res = b << a[4:0];
            SRL: res = b >> a[4:0];
            SRA: res = signed_b >>> a[4:0];
            SLLV: res = b << b[4:0];
            SRLV: res = b >> b[4:0];
            SRAV: res = signed_b >>> b[4:0];
            LUI: res = b << 16;
            default: res = 32'bz; // High-impedance for undefined operations
        endcase

        // Set the output register to the computed result
        r = res;

        // Set flags
        negative = r[31];
        flag = (aluc == SLT || aluc == SLTU) ? 1'b1 : 1'b0;

        // Clear carry and overflow for logical operations
        if (aluc[5:3] == 3'b100) begin
            carry = 1'b0;
            overflow = 1'b0;
        end
    end

endmodule
module adder_8bit (
    input [7:0] a,
    input [7:0] b,
    input cin,
    output [7:0] sum,
    output cout
);
    // Internal wires for carry propagation
    wire carry_internal;
    
    // Lower 8 bits addition
    assign {carry_internal, sum[7:0]} = a[7:0] + b[7:0] + cin;
    
    // Carry-out is the MSB of the 9-bit result
    assign cout = carry_internal;

endmodule
module adder_16bit (
    input [15:0] a,
    input [15:0] b,
    input Cin,
    output [15:0] y,
    output Co
);
    // Internal wire to carry the carry-out from the lower adder to the higher adder
    wire carry_internal;
    
    // Instantiate the lower 8-bit adder
    adder_8bit lower_adder (
        .a(a[7:0]),
        .b(b[7:0]),
        .cin(Cin),
        .sum(y[7:0]),
        .cout(carry_internal) // Carry-out of lower adder is carry-in of higher adder
    );
    
    // Instantiate the higher 8-bit adder
    adder_8bit higher_adder (
        .a(a[15:8]),
        .b(b[15:8]),
        .cin(carry_internal), // Carry-in is the carry-out from the lower adder
        .sum(y[15:8]),
        .cout(Co) // Carry-out of the full 16-bit adder
    );

endmodule
module synchronizer (
    input wire clk_a,
    input wire clk_b,
    input wire arstn,
    input wire brstn,
    input wire [3:0] data_in,
    input wire data_en,
    output reg [3:0] dataout
);

    // Data register to store input data on clk_a
    reg [3:0] data_reg;
    always @(posedge clk_a or negedge arstn) begin
        if (!arstn)
            data_reg <= 4'b0000;
        else if (data_en)
            data_reg <= data_in;
    end

    // Enable data register to store input enable on clk_a
    reg en_data_reg;
    always @(posedge clk_a or negedge arstn) begin
        if (!arstn)
            en_data_reg <= 1'b0;
        else
            en_data_reg <= data_en;
    end

    // Synchronizer flip-flops for the enable signal on clk_b
    reg en_clk_b_one, en_clk_b_two;
    always @(posedge clk_b or negedge brstn) begin
        if (!brstn) begin
            en_clk_b_one <= 1'b0;
            en_clk_b_two <= 1'b0;
        end else begin
            en_clk_b_one <= en_data_reg;
            en_clk_b_two <= en_clk_b_one;
        end
    end

    // Output assignment based on the synchronized enable signal
    always @(posedge clk_b or negedge brstn) begin
        if (!brstn)
            dataout <= 4'b0000;
        else if (en_clk_b_two)
            dataout <= data_reg;
        // No else condition to hold the previous value when not enabled
    end

endmodule
module asyn_fifo (
  input wclk,
  input rclk,
  input wrstn,
  input rrstn,
  input winc,
  input rinc,
  input [WIDTH-1:0] wdata,
  output reg wfull,
  output reg rempty,
  output reg [WIDTH-1:0] rdata
);
  parameter WIDTH = 8;
  parameter DEPTH = 16;

  reg [WIDTH-1:0] rdata_reg;
  reg [$clog2(DEPTH)-1:0] waddr_bin, raddr_bin;
  reg [$clog2(DEPTH)-1:0] wptr, rptr;
  reg [$clog2(DEPTH)-1:0] wptr_buff, rptr_buff;

  reg [WIDTH-1:0] dual_port_RAM [0:DEPTH-1];
  reg wenc, renc;

  // Dual-port RAM instantiation
  dual_port_RAM dual_port_RAM_inst (
    .wclk(wclk),
    .wenc(wenc),
    .waddr(waddr_bin),
    .wdata(wdata),
    .rclk(rclk),
    .renc(renc),
    .raddr(raddr_bin),
    .rdata(rdata_reg)
  );

  // Write pointer increment logic
  always @(posedge wclk or negedge wrstn) begin
    if (~wrstn) begin
      waddr_bin <= 0;
      wptr <= 0;
      wptr_buff <= 0;
    end else begin
      if (winc) begin
        waddr_bin <= waddr_bin + 1;
        wptr <= wptr + 1;
        wptr_buff <= wptr;
      end
    end
  end

  // Read pointer increment logic
  always @(posedge rclk or negedge rrstn) begin
    if (~rrstn) begin
      raddr_bin <= 0;
      rptr <= 0;
      rptr_buff <= 0;
    end else begin
      if (rinc) begin
        raddr_bin <= raddr_bin + 1;
        rptr <= rptr + 1;
        rptr_buff <= rptr;
      end
    end
  end

  // Gray code conversion for write pointer
  always @(posedge wclk) begin
    wenc <= winc;
    waddr_bin <= wptr ^ (wptr >> 1);
  end

  // Gray code conversion for read pointer
  always @(posedge rclk) begin
    renc <= rinc;
    raddr_bin <= rptr ^ (rptr >> 1);
  end

  // Full and empty signal generation
  always @(wptr or rptr) begin
    wfull = (wptr == ~{rptr[($clog2(DEPTH)-2):0], ~rptr[($clog2(DEPTH)-1)]});
    rempty = (rptr == wptr);
  end

  // Output data assignment
  always @(posedge rclk) begin
    if (renc)
      rdata <= rdata_reg;
  end

endmodule
module fsm (
  input IN,
  input CLK,
  input RST,
  output reg MATCH
);
  reg [4:0] state;
  reg [4:0] next_state;
  
  always @(posedge CLK or posedge RST) begin
    if (RST) begin
      state <= 5'b00000;
      MATCH <= 1'b0;
    end
    else begin
      state <= next_state;
      MATCH <= (state == 5'b10011);
    end
  end
  
  always @(IN) begin
    case (state)
      5'b00000: next_state = (IN == 1'b1) ? 5'b00001 : 5'b00000;
      5'b00001: next_state = (IN == 1'b0) ? 5'b00010 : 5'b00000;
      5'b00010: next_state = (IN == 1'b0) ? 5'b00011 : 5'b00000;
      5'b00011: next_state = (IN == 1'b1) ? 5'b00100 : 5'b00000;
      5'b00100: next_state = (IN == 1'b1) ? 5'b10011 : 5'b00000;
      default: next_state = 5'b00000;
    endcase
  end
endmodule
module width_8to16 (
  input clk,
  input rst_n,
  input valid_in,
  input [7:0] data_in,
  output reg valid_out,
  output reg [15:0] data_out
);
  reg [7:0] data_lock;
  reg [15:0] data_reg;

  always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
      data_lock <= 8'h0;
      data_reg <= 16'h0;
      valid_out <= 1'b0;
      data_out <= 16'h0;
    end
    else begin
      if (valid_in) begin
        data_lock <= data_in;
      end
      else begin
        data_lock <= 8'h0;
      end

      if (valid_in && ~valid_out) begin
        data_reg <= {data_lock, data_in};
        valid_out <= 1'b1;
      end
      else if (valid_out) begin
        data_reg <= {data_lock, data_in};
        valid_out <= 1'b0;
      end
    end
  end

  always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
      data_out <= 16'h0;
    end
    else begin
      if (valid_out)
        data_out <= data_reg;
    end
  end
endmodule
module JC_counter (
  input clk,
  input rst_n,
  output reg [63:0] Q
);
  always @(posedge clk or negedge rst_n) begin
    if (~rst_n)
      Q <= 64'b0;
    else begin
      if (Q[0] == 1'b0)
        Q <= {Q[62:0], 1'b1};
      else
        Q <= {Q[62:0], 1'b0};
    end
  end
endmodule
module adder_pipe_64bit (
  input clk,
  input rst_n,
  input i_en,
  input [63:0] adda,
  input [63:0] addb,
  output reg [64:0] result,
  output reg o_en
);

  reg [63:0] stage1_adda, stage1_addb;
  reg [63:0] stage2_adda, stage2_addb;
  reg [63:0] stage3_adda, stage3_addb;

  always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
      result <= 'b0;
    else if (i_en) begin
      stage1_adda <= adda;
      stage1_addb <= addb;
      stage2_adda <= stage1_adda + stage1_addb;
      stage2_addb <= stage1_adda & stage1_addb;
      stage3_adda <= stage2_adda + stage2_addb;
      stage3_addb <= stage2_adda & stage2_addb;
      result <= {stage3_adda, stage3_addb[63]};
      o_en <= 1'b1;
    end else begin
      o_en <= 1'b0;
    end
  end

endmodule
module right_shifter (
  input clk,
  input d,
  output reg [7:0] q
);
  always @(posedge clk) begin
    q <= {q[6:0], d};
  end
endmodule
module serial2parallel (
  input clk,
  input rst_n,
  input din_serial,
  input din_valid,
  output reg [7:0] dout_parallel,
  output reg dout_valid
);
  reg [3:0] cnt;

  always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
      cnt <= 0;
      dout_parallel <= 0;
      dout_valid <= 0;
    end
    else begin
      if (din_valid) begin
        if (cnt < 7) begin
          cnt <= cnt + 1;
          dout_parallel <= {dout_parallel[6:0], din_serial};
          dout_valid <= 0;
        end
        else begin
          cnt <= 0;
          dout_parallel <= {dout_parallel[6:0], din_serial};
          dout_valid <= 1;
        end
      end
    end
  end
endmodule
module freq_div (
  input CLK_in,
  input RST,
  output reg CLK_50,
  output reg CLK_10,
  output reg CLK_1
);

  reg [2:0] cnt_10;
  reg [5:0] cnt_100;
  
  always @(posedge CLK_in or negedge RST) begin
    if (~RST) begin
      CLK_50 <= 1'b0;
      CLK_10 <= 1'b0;
      CLK_1 <= 1'b0;
      cnt_10 <= 3'b0;
      cnt_100 <= 6'b0;
    end
    else begin
      // CLK_50 generation
      CLK_50 <= ~CLK_50;
      
      // CLK_10 generation
      if (cnt_10 == 3'b100) begin
        CLK_10 <= ~CLK_10;
        cnt_10 <= 3'b0;
      end
      else begin
        cnt_10 <= cnt_10 + 1;
      end
      
      // CLK_1 generation
      if (cnt_100 == 6'b110001) begin
        CLK_1 <= ~CLK_1;
        cnt_100 <= 6'b0;
      end
      else begin
        cnt_100 <= cnt_100 + 1;
      end
    end
  end
endmodule
module counter_12 (
  input rst_n,
  input clk,
  input valid_count,
  output reg [3:0] out
);
  always @(posedge clk or negedge rst_n) begin
    if (~rst_n)
      out <= 4'b0000;
    else if (valid_count) begin
      if (out == 4'd11)
        out <= 4'b0000;
      else
        out <= out + 1;
    end
  end
endmodule
module edge_detect (
  input clk,
  input rst_n,
  input a,
  output reg rise,
  output reg down
);
  reg a_prev;
  
  always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
      rise <= 1'b0;
      down <= 1'b0;
      a_prev <= 1'b0;
    end
    else begin
      if (a == 1'b1 && a_prev == 1'b0)
        rise <= 1'b1;
      else if (a == 1'b0 && a_prev == 1'b1)
        down <= 1'b1;
      else begin
        rise <= 1'b0;
        down <= 1'b0;
      end
      
      a_prev <= a;
    end
  end
endmodule
module calendar (
  input CLK,
  input RST,
  output reg [5:0] Hours,
  output reg [5:0] Mins,
  output reg [5:0] Secs
);
  reg [5:0] next_hours, next_mins, next_secs;

  always @(posedge CLK or posedge RST) begin
    if (RST)
      Secs <= 6'b0;
    else if (Secs == 6'b111111)
      Secs <= 6'b0;
    else
      Secs <= Secs + 1;
  end

  always @(posedge CLK or posedge RST) begin
    if (RST)
      Mins <= 6'b0;
    else if (Secs == 6'b111111 && Mins == 6'b111111)
      Mins <= 6'b0;
    else if (Secs == 6'b111111)
      Mins <= Mins + 1;
  end

  always @(posedge CLK or posedge RST) begin
    if (RST)
      Hours <= 6'b0;
    else if (Secs == 6'b111111 && Mins == 6'b111111 && Hours == 6'b111111)
      Hours <= 6'b0;
    else if (Secs == 6'b111111 && Mins == 6'b111111)
      Hours <= Hours + 1;
  end

endmodule
module RAM #(parameter WIDTH = 4, parameter DEPTH = 8)(
  input clk,
  input rst_n,
  input write_en,
  input [WIDTH-1:0] write_addr,
  input [DEPTH-1:0] write_data,
  input read_en,
  input [WIDTH-1:0] read_addr,
  output reg [DEPTH-1:0] read_data
);
  reg [DEPTH-1:0] RAM [2**WIDTH-1:0];

  always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
      for (integer i = 0; i < 2**WIDTH; i = i + 1)
        RAM[i] <= 0;
    end
    else begin
      if (write_en)
        RAM[write_addr] <= write_data;
    end
  end

  always @(posedge clk or negedge rst_n) begin
    if (~rst_n)
      read_data <= 0;
    else begin
      if (read_en)
        read_data <= RAM[read_addr];
      else
        read_data <= 0;
    end
  end
endmodule
module parallel2serial (
  input clk,
  input rst_n,
  input [3:0] d,
  output reg valid_out,
  output reg dout
);
  reg [2:0] cnt;
  reg [3:0] data;
  
  always @(posedge clk or negedge rst_n) begin
    if (~rst_n)
      cnt <= 3'b0;
    else if (cnt == 3'b11)
      cnt <= 3'b0;
    else
      cnt <= cnt + 1;
  end
  
  always @(posedge clk or negedge rst_n) begin
    if (~rst_n)
      data <= 4'b0;
    else if (cnt == 3'b0)
      data <= d;
    else
      data <= {data[2:0], 1'b0};
  end
  
  always @(posedge clk or negedge rst_n) begin
    if (~rst_n)
      valid_out <= 1'b0;
    else if (cnt == 3'b0)
      valid_out <= 1'b1;
    else
      valid_out <= 1'b0;
  end
  
  always @(posedge clk) begin
    if (valid_out)
      dout <= data[3];
  end
endmodule
module radix2_div #(parameter DATAWIDTH = 8)(
  input clk,
  input rstn,
  input en,
  input [DATAWIDTH-1:0] dividend,
  input [DATAWIDTH-1:0] divisor,
  output reg ready,
  output reg [DATAWIDTH-1:0] quotient,
  output reg [DATAWIDTH-1:0] remainder,
  output reg vld_out
);

  // State enumeration
  localparam IDLE = 2'b00;
  localparam SUB = 2'b01;
  localparam SHIFT = 2'b10;
  localparam DONE = 2'b11;

  // State registers
  reg [1:0] current_state;
  reg [1:0] next_state;
  
  // Data registers
  reg [DATAWIDTH:0] dividend_e;
  reg [DATAWIDTH:0] divisor_e;
  reg [DATAWIDTH:0] quotient_e;
  reg [DATAWIDTH:0] remainder_e;
  reg [DATAWIDTH-1:0] count;

  always @(posedge clk or negedge rstn) begin
    if (~rstn)
      current_state <= IDLE;
    else
      current_state <= next_state;
  end

  always @(current_state, en, dividend, divisor) begin
    case (current_state)
      IDLE: begin
        if (en)
          next_state = SUB;
        else
          next_state = IDLE;
      end

      SUB: begin
        next_state = SHIFT;
      end

      SHIFT: begin
        if (count == DATAWIDTH)
          next_state = DONE;
        else
          next_state = SUB;
      end
      
      DONE: begin
        next_state = IDLE;
      end
    endcase
  end

  always @(*) begin
    case (current_state)
      IDLE: begin
        ready = 1'b1;
        vld_out = 1'b0;
      end

      SUB: begin
        dividend_e = {dividend, 1'b0};
        divisor_e = {divisor, 1'b0};
        quotient_e = {quotient, 1'b0};
        remainder_e = {remainder, 1'b0};

        if (dividend_e >= divisor_e) begin
          quotient_e = quotient_e + 1'b1;
          remainder_e = dividend_e - divisor_e;
        end
      end

      SHIFT: begin
        count = count + 1'b1;
        dividend_e = remainder_e;
        quotient_e = {quotient_e[DATAWIDTH-2:0], 1'b0};
        remainder_e = {remainder_e[DATAWIDTH-2:0], 1'b0};
      end
      
      DONE: begin
        quotient = quotient_e[DATAWIDTH-1:0];
        remainder = remainder_e[DATAWIDTH-1:0];
        ready = 1'b0;
        vld_out = 1'b1;
      end
    endcase
  end

  always @(negedge rstn) begin
    if (~rstn) begin
      dividend_e <= 0;
      divisor_e <= 0;
      quotient_e <= 0;
      remainder_e <= 0;
      count <= 0;
    end
  end
endmodule
module signal_generator (
  input clk,
  input rst_n,
  output reg [4:0] wave
);
  reg [1:0] state;

  always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
      state <= 0;
      wave <= 0;
    end
    else begin
      case (state)
        0: begin
          if (wave == 31)
            state <= 1;
          else
            wave <= wave + 1;
        end
        1: begin
          if (wave == 0)
            state <= 0;
          else
            wave <= wave - 1;
        end
      endcase
    end
  end
endmodule
module multi_booth_8bit (
  input clk,
  input reset,
  input [7:0] a,
  input [7:0] b,
  output reg [15:0] p,
  output reg rdy
);
  reg [7:0] multiplicand;
  reg [7:0] multiplier;
  reg [3:0] ctr;
  
  always @(posedge clk or posedge reset) begin
    if (reset) begin
      multiplicand <= 8'b0;
      multiplier <= 8'b0;
      ctr <= 4'b0;
      p <= 16'b0;
      rdy <= 1'b0;
    end
    else begin
      if (ctr < 4'b10000) begin
        multiplicand <= multiplicand << 1;
        
        if (multiplier[ctr] == 1'b1)
          p <= p + multiplicand;
        
        ctr <= ctr + 1;
      end
      
      if (ctr == 4'b10000)
        rdy <= 1'b1;
    end
  end
endmodule
module pe (
  input clk,
  input rst,
  input [31:0] a,
  input [31:0] b,
  output reg [31:0] c
);
  always @(posedge clk or posedge rst) begin
    if (rst)
      c <= 32'b0;
    else
      c <= c + (a * b);
  end
endmodule
module pulse_detect (
  input clk,
  input rst_n,
  input data_in,
  output reg data_out
);
  reg [2:0] state;
  reg [2:0] next_state;
  
  always @(posedge clk or negedge rst_n) begin
    if (~rst_n)
      state <= 3'b000;
    else
      state <= next_state;
  end
  
  always @(state, data_in) begin
    case (state)
      3'b000: begin
        if (data_in)
          next_state = 3'b001;
        else
          next_state = 3'b000;
      end
      
      3'b001: begin
        if (data_in)
          next_state = 3'b010;
        else
          next_state = 3'b000;
      end
      
      3'b010: begin
        if (data_in)
          next_state = 3'b011;
        else
          next_state = 3'b000;
      end
      
      3'b011: begin
        if (~data_in)
          next_state = 3'b100;
        else
          next_state = 3'b011;
      end
      
      default: next_state = 3'b000;
    endcase
  end
  
  always @(state) begin
    if (state == 3'b011)
      data_out = 1'b1;
    else
      data_out = 1'b0;
  end
endmodule