dakies/OSS_Verilog huggingface dataset:
module freq_div(
    input CLK_in,  // Input clock signal
    input RST,     // Reset signal
    output reg CLK_50,  // Output clock signal with a frequency of CLK_in divided by 2
    output reg CLK_10,  // Output clock signal with a frequency of CLK_in divided by 10
    output reg CLK_1    // Output clock signal with a frequency of CLK_in divided by 100
);

    // Counter for the CLK_10 generation
    reg [3:0] cnt_10 = 4'd0; // 4 bits counter to count up to 9 (10 states)
    
    // Counter for the CLK_1 generation
    reg [6:0] cnt_100 = 7'd0; // 7 bits counter to count up to 99 (100 states)

    // CLK_50 generation
    always @(posedge CLK_in or posedge RST) begin
        if (RST) begin
            CLK_50 <= 1'b0;
        end else begin
            CLK_50 <= ~CLK_50;
        end
    end

    // CLK_10 generation
    always @(posedge CLK_in or posedge RST) begin
        if (RST) begin
            cnt_10 <= 4'd0;
            CLK_10 <= 1'b0;
        end else begin
            if (cnt_10 == 4'd4) begin
                CLK_10 <= ~CLK_10;
                cnt_10 <= 4'd0;
            end else begin
                cnt_10 <= cnt_10 + 1'b1;
            end
        end
    end

    // CLK_1 generation
    always @(posedge CLK_in or posedge RST) begin
        if (RST) begin
            cnt_100 <= 7'd0;
            CLK_1 <= 1'b0;
        end else begin
            if (cnt_100 == 7'd49) begin
                CLK_1 <= ~CLK_1;
                cnt_100 <= 7'd0;
            end else begin
                cnt_100 <= cnt_100 + 1'b1;
            end
        end
    end

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

    // Counter operation
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            // Reset condition
            out <= 4'b0000;
        end else if (valid_count) begin
            // Counting enabled
            if (out == 4'd11) begin
                // Wrap the counter after reaching 11
                out <= 4'b0000;
            end else begin
                // Increment the counter
                out <= out + 1;
            end
        end
        // When valid_count is not active, counter holds the value (no 'else' needed)
    end

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

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

    // Always block for edge detection and output signal generation
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            // Asynchronous reset: active low
            rise <= 0;
            down <= 0;
            a_prev <= 0;
        end else begin
            // Check for rising edge
            if (a == 1 && a_prev == 0) begin
                rise <= 1;
            end else begin
                rise <= 0;
            end
            // Check for falling edge
            if (a == 0 && a_prev == 1) begin
                down <= 1;
            end else begin
                down <= 0;
            end
            // Update the previous value of 'a'
            a_prev <= a;
        end
    end

endmodule
module adder_32bit(
    input [32:1] A,   // 32-bit input operand A
    input [32:1] B,   // 32-bit input operand B
    output [32:1] S,  // 32-bit output sum
    output C32        // Carry-out output
);

    wire C16; // Intermediate carry between lower and upper CLA blocks

    // Instantiate the lower 16-bit CLA block
    cla_16bit cla_lower(
        .A(A[16:1]),
        .B(B[16:1]),
        .Cin(1'b0), // Assuming there is no initial carry-in
        .S(S[16:1]),
        .Cout(C16)
    );

    // Instantiate the upper 16-bit CLA block
    cla_16bit cla_upper(
        .A(A[32:17]),
        .B(B[32:17]),
        .Cin(C16),
        .S(S[32:17]),
        .Cout(C32)
    );

endmodule
module cla_16bit(
    input [16:1] A,
    input [16:1] B,
    input Cin,
    output [16:1] S,
    output Cout
);

    wire [16:0] C; // Internal carry bits, C[0] is Cin
    wire [16:1] G; // Generate terms
    wire [16:1] P; // Propagate terms

    assign C[0] = Cin;

    // Generate and propagate terms
    genvar i;
    generate
        for (i = 1; i <= 16; i = i + 1) begin : gen_prop
            assign G[i] = A[i] & B[i];   // Generate
            assign P[i] = A[i] | B[i];   // Propagate
            assign C[i] = G[i] | (P[i] & C[i-1]); // Carry
        end
    endgenerate

    // Calculate sum and carry out
    for (i = 1; i <= 16; i = i + 1) begin : sum_loop
        assign S[i] = A[i] ^ B[i] ^ C[i-1]; // Sum bit
    end

    assign Cout = C[16]; // Final carry-out

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

    // Memory array
    reg [WIDTH-1:0] RAM [(1<<DEPTH)-1:0];
    integer i;

    // Write operation
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            // Reset RAM contents to 0 on reset
            for (i = 0; i < (1<<DEPTH); i = i + 1) begin
                RAM[i] <= 0;
            end
        end else if (write_en) begin
            // Write data to RAM
            RAM[write_addr] <= write_data;
        end
    end

    // Read operation
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            // Clear read_data on reset
            read_data <= 0;
        end else if (read_en) begin
            // Read data from RAM
            read_data <= RAM[read_addr];
        end else begin
            // Optionally clear read_data if not reading
            read_data <= read_data; // Or you could clear it or do nothing
        end
    end

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

    // Intermediate registers for pipelined stages
    reg [7:0] mul_a_reg, mul_b_reg;
    reg [15:0] partial_products [7:0];
    reg [15:0] sum [6:0]; // 7 intermediate sums
    reg mul_en_out_reg; // Register for mul_en_in signal

    // Input control logic
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            mul_a_reg <= 0;
            mul_b_reg <= 0;
            mul_en_out_reg <= 0;
        end else if (mul_en_in) begin
            mul_a_reg <= mul_a;
            mul_b_reg <= mul_b;
            mul_en_out_reg <= mul_en_in;
        end
    end

    // Generate partial products
    integer i;
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            for (i = 0; i < 8; i = i + 1) begin
                partial_products[i] <= 0;
            end
        end else begin
            for (i = 0; i < 8; i = i + 1) begin
                partial_products[i] <= mul_b_reg[i] ? (mul_a_reg << i) : 0;
            end
        end
    end

    // Calculate the intermediate sums
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            for (i = 0; i < 7; i = i + 1) begin
                sum[i] <= 0;
            end
        end else begin
            sum[0] <= partial_products[0] + partial_products[1];
            sum[1] <= partial_products[2] + partial_products[3];
            sum[2] <= partial_products[4] + partial_products[5];
            sum[3] <= partial_products[6] + partial_products[7];
            sum[4] <= sum[0] + sum[1];
            sum[5] <= sum[2] + sum[3];
            sum[6] <= sum[4] + sum[5];
        end
    end

    // Final product calculation
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            mul_out <= 0;
            mul_en_out <= 0;
        end else begin
            mul_out <= sum[6];
            mul_en_out <= mul_en_out_reg;
        end
    end

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

    // Internal counter to keep track of bit position
    reg [1:0] cnt; // 2-bit counter for 4 clock cycles

    // Register to hold the current state of the data
    reg [3:0] data;

    // On every clock edge...
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            // Reset the state and outputs
            cnt <= 2'b0;
            valid_out <= 1'b0;
            dout <= 1'b0;
            data <= 4'b0;
        end else begin
            // Check if it is time to load new data and reset the counter
            if (cnt == 2'b11) begin
                data <= d;         // Load the new data
                cnt <= 2'b0;      // Reset the counter
                valid_out <= 1'b1; // Output is valid
                dout <= d[3];      // Start with MSB
            end else begin
                cnt <= cnt + 2'b1; // Increment the counter
                valid_out <= (cnt == 2'b0) ? 1'b1 : 1'b0; // Valid only after loading new data or when counter is 0
                data <= {data[2:0], 1'b0}; // Shift left the data
                dout <= data[3]; // Output the leftmost bit
            end
        end
    end
endmodule
module radix2_div #(parameter DATAWIDTH = 8) (
    input wire clk,
    input wire rstn,
    input wire en,
    input wire [DATAWIDTH-1:0] dividend,
    input wire [DATAWIDTH-1:0] divisor,
    output reg ready,
    output reg [DATAWIDTH-1:0] quotient,
    output reg [DATAWIDTH-1:0] remainder,
    output reg vld_out
);

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

    // FSM and data registers
    reg [1:0] current_state, next_state;
    reg [DATAWIDTH-1:0] dividend_e, divisor_e;
    reg [DATAWIDTH-1:0] quotient_e, remainder_e;
    reg [DATAWIDTH:0] count;

    // Next state logic
    always @(posedge clk or negedge rstn) begin
        if (!rstn) begin
            current_state <= IDLE;
        end else begin
            current_state <= next_state;
        end
    end

    // FSM, data registers, and output logic
    always @(posedge clk or negedge rstn) begin
        if (!rstn) begin
            dividend_e <= 0;
            divisor_e <= 0;
            quotient_e <= 0;
            remainder_e <= 0;
            count <= 0;
            ready <= 1;
            vld_out <= 0;
        end else begin
            case (current_state)
                IDLE: begin
                    ready <= 1;
                    vld_out <= 0;
                    if (en) begin
                        dividend_e <= dividend;
                        divisor_e <= divisor;
                        quotient_e <= 0;
                        remainder_e <= 0;
                        count <= DATAWIDTH; // Set counter for number of iterations
                        next_state <= SUB;
                        ready <= 0;
                    end
                end
                SUB: begin
                    // Subtraction stage
                    if (dividend_e >= divisor_e) begin
                        remainder_e <= dividend_e - divisor_e;
                        quotient_e <= (quotient_e << 1) | 1;
                    end else begin
                        remainder_e <= dividend_e;
                        quotient_e <= quotient_e << 1;
                    end
                    next_state <= SHIFT;
                end
                SHIFT: begin
                    // Shifting stage
                    if (count > 0) begin
                        dividend_e <= remainder_e << 1;
                        count <= count - 1;
                        next_state <= SUB;
                    end else begin
                        next_state <= DONE;
                    end
                end
                DONE: begin
                    // Completion stage
                    quotient <= quotient_e;
                    remainder <= remainder_e;
                    vld_out <= 1;
                    next_state <= IDLE;
                end
                default: begin
                    next_state <= IDLE;
                end
            endcase
        end
    end

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

    // Define state to store input data and count the number of inputs
    reg [9:0] sum;
    reg [1:0] count;

    // Always block to handle the accumulation and output generation
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            // Reset state
            sum <= 10'd0;
            count <= 2'd0;
            valid_out <= 1'b0;
            data_out <= 10'd0;
        end else begin
            if (valid_in) begin
                // When a valid input is provided, add it to the sum
                sum <= sum + data_in;
                count <= count + 1'b1; // Increment the count of valid inputs

                // Reset the valid_out flag each cycle unless it's being set this cycle
                valid_out <= 1'b0;

                if (count == 2'd3) begin
                    // If four valid inputs have been accumulated, output the sum
                    data_out <= sum + data_in; // Include the current data_in in the sum
                    valid_out <= 1'b1; // Set valid_out high to indicate valid output
                    sum <= 10'd0; // Reset sum for the next round of accumulation
                    count <= 2'd0; // Reset count for the next round of accumulation
                end
            end
        end
    end

endmodule
module div_16bit(
    input [15:0] A,
    input [7:0] B,
    output reg [15:0] result,
    output reg [15:0] odd
);
    integer i;
    
    always @(*) begin
        // Initialize the outputs
        result = 0;
        odd = A; // Start with the full dividend as the initial remainder
        
        // Check for division by zero. This check can be enhanced to handle the error.
        if (B == 0) begin
            result = 16'hFFFF; // Indicate an error or overflow
            odd = A;
        end else begin
            // Perform the division using a for loop to iterate over each bit
            for (i = 15; i >= 0; i = i - 1) begin
                // Shift left the result to make room for the next bit
                result = result << 1;
                // Extract the highest bits of the remainder to match divisor width
                if (odd[15:8] >= B) begin
                    // Subtract the divisor from the extracted bits and get the new remainder
                    odd[15:8] = odd[15:8] - B;
                    // Since the remainder is larger, set the quotient bit to 1
                    result[0] = 1;
                end
                // Shift up the remainder to bring in the next bit of the dividend
                if (i > 0) begin
                    odd = odd << 1;
                    odd[0] = A[i-1];
                end
            end
        end
    end
endmodule
module signal_generator (
    input wire clk,
    input wire rst_n,
    output reg [4:0] wave // 5-bit signal for the waveform
);

// State declaration
reg state; // Use a 1-bit signal to store the state, 0 for incrementing, 1 for decrementing

// Waveform generation logic
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        // Active-low reset: clear the state and wave registers
        state <= 0;
        wave <= 5'b00000;
    end else begin
        case (state)
            // State 0: Increment wave until it reaches 31
            0: begin
                if (wave == 5'b11111) begin
                    state <= 1; // Transition to state 1 to start decrementing
                end else begin
                    wave <= wave + 1;
                end
            end
            
            // State 1: Decrement wave until it reaches 0
            1: begin
                if (wave == 5'b00000) begin
                    state <= 0; // Transition back to state 0 to start incrementing
                end else begin
                    wave <= wave - 1;
                end
            end
            
            // Handle undefined states (should never occur with a well-defined 1-bit state)
            default: begin
                state <= 0;
                wave <= 5'b00000;
            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 [8:0] multiplier; // extra bit for the booth algorithm
    reg [3:0] ctr; // counter for the iterations

    always @(posedge clk or posedge reset) begin
        if (reset) begin
            // Synchronous reset initialization
            p <= 16'b0;
            multiplicand <= a;
            multiplier <= {1'b0, b}; // extra bit for the booth algorithm
            ctr <= 4'b0;
            rdy <= 1'b0;
        end else begin
            if (ctr < 8) begin
                case (multiplier[1:0])
                    2'b01: p[15:0] <= p + {multiplicand, ctr[2:0]};
                    2'b10: p[15:0] <= p - {multiplicand, ctr[2:0]};
                    default: p <= p; // cases 2'b00 and 2'b11 result in no operation
                endcase
                // Shift multiplier to bring next pair of bits into position
                multiplier <= multiplier >> 2;
                ctr <= ctr + 1;
            end else begin
                rdy <= 1'b1; // Multiplication process is completed
            end
        end
    end

endmodule
module pe (
    input wire clk,
    input wire rst,
    input wire [31:0] a,
    input wire [31:0] b,
    output reg [63:0] c // Changed to 64 bits to avoid overflow
);

    // Perform multiplication and accumulation on the positive edge of the clock
    always @(posedge clk or posedge rst) begin
        if (rst) begin
            // Reset the accumulator to 0 when rst is high
            c <= 64'b0; // Extended to 64 bits to hold the result without overflow
        end else begin
            // Multiply a and b, and accumulate the result
            c <= c + (a * b); // Here, a * b is a 64-bit operation
        end
    end

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

    // ALU control codes
    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;

    // Temporary variables for calculations
    reg [31:0] temp;
    reg [63:0] extended_result;

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

    // Set the negative flag
    assign negative = r[31];

    // Set the carry flag - only makes sense for addition/subtraction
    assign carry = (aluc == ADD || aluc == SUB) && (extended_result[32]);

    // Set the overflow flag - only makes sense for addition/subtraction
    assign overflow = ((aluc == ADD || aluc == SUB) &&
                      ((a[31] && b[31] && !r[31]) ||
                       (!a[31] && !b[31] && r[31])));

    always @(*) begin
        flag = 1'b0; // Default flag
        case (aluc)
            ADD: begin
                extended_result = {1'b0, a} + {1'b0, b};
                r = extended_result[31:0];
            end
            ADDU: r = a + b;
            SUB: begin
                extended_result = {1'b0, a} - {1'b0, b};
                r = extended_result[31:0];
            end
            SUBU: r = a - b;
            AND: r = a & b;
            OR: r = a | b;
            XOR: r = a ^ b;
            NOR: r = ~(a | b);
            SLT: begin
                r = $signed(a) < $signed(b);
                flag = r;
            end
            SLTU: begin
                r = a < b;
                flag = r;
            end
            SLL: r = b << a[4:0];
            SRL: r = b >> a[4:0];
            SRA: r = $signed(b) >>> a[4:0];
            SLLV: r = b << a;
            SRLV: r = b >> a;
            SRAV: r = $signed(b) >>> a;
            LUI: r = {b[15:0], 16'b0};
            default: r = 32'bz; // High-impedance for undefined operation
        endcase
    end
endmodule
module adder_16bit (
    input wire [15:0] a,
    input wire [15:0] b,
    input wire Cin,
    output wire [15:0] y,
    output wire Co
);

    // Wires for the carry between lower and upper 8-bit adders
    wire carry;

    // Instantiate the 8-bit adders
    adder_8bit lower_adder (
        .a(a[7:0]),
        .b(b[7:0]),
        .cin(Cin),
        .sum(y[7:0]),
        .cout(carry) // Carry from lower 8 bits
    );

    adder_8bit upper_adder (
        .a(a[15:8]),
        .b(b[15:8]),
        .cin(carry), // Carry from lower 8 bits
        .sum(y[15:8]),
        .cout(Co) // Carry out from the entire 16-bit adder
    );

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

    wire [6:0] carry;

    // Instantiate the 1-bit full adders
    genvar i;
    generate
        for (i = 0; i < 8; i = i + 1) begin : full_adder_loop
            if (i == 0) begin
                full_adder fa (
                    .a(a[i]),
                    .b(b[i]),
                    .cin(cin),
                    .sum(sum[i]),
                    .cout(carry[i])
                );
            end else if (i == 7) begin
                full_adder fa (
                    .a(a[i]),
                    .b(b[i]),
                    .cin(carry[i-1]),
                    .sum(sum[i]),
                    .cout(cout)
                );
            end else begin
                full_adder fa (
                    .a(a[i]),
                    .b(b[i]),
                    .cin(carry[i-1]),
                    .sum(sum[i]),
                    .cout(carry[i])
                );
            end
        end
    endgenerate

endmodule
module full_adder (
    input wire a,
    input wire b,
    input wire cin,
    output wire sum,
    output wire cout
);

    assign sum = a ^ b ^ cin;
    assign cout = (a & b) | (b & cin) | (cin & a);

endmodule
module pulse_detect(
    input wire clk,
    input wire rst_n,
    input wire data_in,
    output reg data_out
);

// State declaration to keep track of the previous, current, and next input states
reg [2:0] shift_reg;

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        // Reset condition
        shift_reg <= 3'b000;
        data_out <= 1'b0;
    end else begin
        // Shift the register and input the new data
        shift_reg <= {shift_reg[1:0], data_in};

        // Detecting a pulse
        // A pulse is detected when the register holds 010
        if (shift_reg == 3'b010) begin
            data_out <= 1'b1; // Pulse detected, set output high
        end else begin
            data_out <= 1'b0; // No pulse, set output low
        end
    end
end

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
);

// Internal register declarations
reg [3:0] data_reg_a; // Register on clock A domain
reg en_data_reg_a; // Enable register on clock A domain
reg en_data_reg_b; // Enable register on clock B domain (first stage)
reg en_data_reg_bb; // Enable register on clock B domain (second stage)

// Data register update with clock A
always @(posedge clk_a or negedge arstn) begin
    if (!arstn) begin
        data_reg_a <= 4'b0000;
        en_data_reg_a <= 1'b0;
    end else begin
        data_reg_a <= data_in;
        en_data_reg_a <= data_en;
    end
end

// Enable signal synchronization with clock B
always @(posedge clk_b or negedge brstn) begin
    if (!brstn) begin
        en_data_reg_b <= 1'b0;
        en_data_reg_bb <= 1'b0;
    end else begin
        en_data_reg_b <= en_data_reg_a;
        en_data_reg_bb <= en_data_reg_b;
    end
end

// Output assignment with clock B
always @(posedge clk_b or negedge brstn) begin
    if (!brstn) begin
        dataout <= 4'b0000;
    end else if (en_data_reg_bb) begin
        dataout <= data_reg_a; // Synchronized data transfer on the second enable activation
    end
    // No need for an else clause to retain the previous value, as this is implicit with registers
end

endmodule
module calendar(
    input CLK,      // Clock input
    input RST,      // Active high reset
    output reg [5:0] Hours,  // 6-bit hours (0-23)
    output reg [5:0] Mins,   // 6-bit minutes (0-59)
    output reg [5:0] Secs    // 6-bit seconds (0-59)
);

    // Seconds logic
    always @(posedge CLK or posedge RST) begin
        if (RST) begin
            Secs <= 0;
        end else if (Secs == 59) begin
            Secs <= 0;
        end else begin
            Secs <= Secs + 1;
        end
    end

    // Minutes logic
    always @(posedge CLK or posedge RST) begin
        if (RST) begin
            Mins <= 0;
        end else if (Secs == 59 && Mins == 59) begin
            Mins <= 0;
        end else if (Secs == 59) begin
            Mins <= Mins + 1;
        end
    end

    // Hours logic
    always @(posedge CLK or posedge RST) begin
        if (RST) begin
            Hours <= 0;
        end else if (Secs == 59 && Mins == 59 && Hours == 23) begin
            Hours <= 0;
        end else if (Secs == 59 && Mins == 59) begin
            Hours <= Hours + 1;
        end
    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 track the stored byte
    reg [7:0] data_lock;
    // Internal signal to indicate if we've stored the first byte
    reg flag;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            // Reset the state
            data_out <= 16'd0;
            valid_out <= 1'b0;
            data_lock <= 8'd0;
            flag <= 1'b0;
        end else if (valid_in) begin
            if (flag) begin
                // We've received the second byte, concatenate
                data_out <= {data_lock, data_in};
                valid_out <= 1'b1;
                flag <= 1'b0;  // Reset the flag as we've used the stored byte
            end else begin
                // Store the first byte and wait for the second byte
                data_lock <= data_in;
                flag <= 1'b1;
                valid_out <= 1'b0;  // Output is not valid until we have two bytes
            end
        end else if (flag) begin
            // If we have a stored byte but no new valid input, keep outputs invalid
            valid_out <= 1'b0;
        end
    end

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

    // On every rising edge of the clock or falling edge of reset
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            // Active-low reset condition; reset the counter value
            Q <= 64'b0;
        end else begin
            // Check the least significant bit to decide on appending a '1' or '0'
            if (Q[0] == 1'b0) begin
                // LSB is '0', so shift left and append '1' at the MSB
                Q <= {Q[62:0], 1'b1};
            end else begin
                // LSB is '1', so shift left and append '0' at the MSB (inverting the sequence)
                Q <= {Q[62:0], 1'b0};
            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
);

    // Pipeline stage registers
    reg [31:0] adda_stage1, addb_stage1;
    reg [63:0] sum_stage1;
    reg carry_stage1;
    reg stage1_en, stage2_en;

    // Intermediate sum and carry
    wire [31:0] sum_lower, sum_upper;
    wire carry_lower, carry_upper;

    // Lower 32-bit adder
    assign {carry_lower, sum_lower} = adda[31:0] + addb[31:0];

    // Upper 32-bit adder with carry-in
    assign {carry_upper, sum_upper} = adda[63:32] + addb[63:32] + carry_stage1;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            // Reset all pipeline registers and outputs
            {adda_stage1, addb_stage1} <= 0;
            sum_stage1 <= 0;
            carry_stage1 <= 0;
            result <= 0;
            stage1_en <= 0;
            stage2_en <= 0;
            o_en <= 0;
        end else begin
            // Pipeline stage 1
            if (i_en) begin
                adda_stage1 <= adda[31:0];
                addb_stage1 <= addb[31:0];
                sum_stage1 <= {sum_upper, sum_lower};
                carry_stage1 <= carry_lower;
                stage1_en <= 1;
            end

            // Pipeline stage 2
            if (stage1_en) begin
                result <= {carry_upper, sum_stage1};
                stage2_en <= 1;
            end

            // Output enable logic
            o_en <= stage2_en;
            if (stage2_en) begin
                // Clear enable signals for the next operation
                stage1_en <= 0;
                stage2_en <= 0;
            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

// Perform the right shift operation on the rising edge of the clock
always @(posedge clk) begin
    q <= {d, q[7:1]}; // Insert the input bit d into the most significant bit of q, and shift the rest right
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
);

    // Internal counter to keep track of the number of bits received
    reg [2:0] cnt;

    // Reset and data shifting is handled on the rising edge of the clock
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            // When reset is asserted, clear the counter and output registers
            cnt <= 3'b000;
            dout_parallel <= 8'b00000000;
            dout_valid <= 1'b0;
        end else if (din_valid) begin
            // Shift in the serial data into dout_parallel starting with the MSB
            dout_parallel <= {din_serial, dout_parallel[7:1]};
            // Increment the counter
            cnt <= cnt + 3'b001;
            // If 8 bits have been received, indicate that dout_parallel is valid
            if (cnt == 3'b111) begin
                dout_valid <= 1'b1;
                cnt <= 3'b000; // Reset the counter for the next batch of 8 bits
            end else begin
                dout_valid <= 1'b0;
            end
        end else begin
            // When din_valid is not high, do not shift in new data
            dout_valid <= 1'b0;
        end
    end

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

    // Internal signals
    reg [31:0] product;
    reg [15:0] multiplicand;
    reg [15:0] multiplier;
    reg [4:0] count; // 16-bit multiplier requires a 5-bit counter

    // Control FSM states
    localparam IDLE = 0, MULTIPLY = 1, DONE = 2;
    reg [1:0] state;

    // FSM for controlling the multiplication process
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            // Synchronous reset
            state <= IDLE;
            product <= 0;
            multiplicand <= 0;
            multiplier <= 0;
            count <= 0;
            done <= 0;
        end else begin
            case (state)
                IDLE: begin
                    if (start) begin
                        multiplicand <= ain;
                        multiplier <= bin;
                        product <= 0;
                        count <= 0;
                        state <= MULTIPLY;
                        done <= 0;
                    end
                end
                MULTIPLY: begin
                    if (count < 16) begin
                        // Perform shift and add
                        if (multiplier[0]) begin
                            product <= product + (multiplicand << count);
                        end
                        multiplier <= multiplier >> 1;
                        count <= count + 1;
                    end else begin
                        state <= DONE;
                    end
                end
                DONE: begin
                    // Multiplication done, assert done signal
                    done <= 1;
                    state <= IDLE; // Optionally, go back to IDLE or wait for a reset or a new start
                end
                default: state <= IDLE;
            endcase
        end
    end

    // Assign the output
    always @(posedge clk) begin
        if (state == DONE) begin
            yout <= product; // Assign the product to output when done
        end
    end

endmodule
module freq_div(
    input CLK_in, // Input clock signal at 100MHz
    input RST,    // Active high reset signal
    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 generation
    reg [2:0] cnt_10; // 3-bit counter for dividing by 10
    // Counter for the 1MHz clock generation
    reg [5:0] cnt_100; // 6-bit counter for dividing by 100

    // CLK_50 generation
    always @(posedge CLK_in or posedge RST) begin
        if (RST) begin
            // Reset condition
            CLK_50 <= 1'b0;
        end else begin
            // Toggle CLK_50 every clock cycle to divide the frequency by 2
            CLK_50 <= ~CLK_50;
        end
    end

    // CLK_10 generation
    always @(posedge CLK_in or posedge RST) begin
        if (RST) begin
            // Reset condition
            CLK_10 <= 1'b0;
            cnt_10 <= 3'd0;
        end else begin
            if (cnt_10 == 3'd4) begin
                // Toggle CLK_10 and reset the counter
                CLK_10 <= ~CLK_10;
                cnt_10 <= 3'd0;
            end else begin
                // Increment the counter
                cnt_10 <= cnt_10 + 1;
            end
        end
    end

    // CLK_1 generation
    always @(posedge CLK_in or posedge RST) begin
        if (RST) begin
            // Reset condition
            CLK_1 <= 1'b0;
            cnt_100 <= 6'd0;
        end else begin
            if (cnt_100 == 6'd49) begin
                // Toggle CLK_1 and reset the counter
                CLK_1 <= ~CLK_1;
                cnt_100 <= 6'd0;
            end else begin
                // Increment the counter
                cnt_100 <= cnt_100 + 1;
            end
        end
    end

endmodule
module counter_12 (
    input wire rst_n,
    input wire clk,
    input wire valid_count,
    output reg [3:0] out
);

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            // Active low reset
            out <= 4'b0000;
        end else if (valid_count) begin
            if (out == 4'd11) begin
                // Reset to 0 if the counter reaches 11
                out <= 4'b0000;
            end else begin
                // Increment the counter
                out <= out + 1;
            end
        end
        // Counter holds the value if valid_count is 0
    end

endmodule
module edge_detect(
    input clk,      // Clock signal
    input rst_n,    // Reset signal (active low)
    input a,        // Input signal
    output reg rise, // Output signal indicating a rising edge
    output reg down  // Output signal indicating a falling edge
);

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

    // Edge detection is done on positive clock edge
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            // Asynchronous reset: outputs and previous value register are reset
            rise <= 1'b0;
            down <= 1'b0;
            a_prev <= 1'b0;
        end else begin
            // On every clock edge, update the rise and down signals
            rise <= (a_prev == 1'b0 && a == 1'b1); // Rising edge detected
            down <= (a_prev == 1'b1 && a == 1'b0); // Falling edge detected
            
            // Update the previous value of 'a'
            a_prev <= a;
        end
    end

endmodule
module adder_32bit(
    input [32:1] A,
    input [32:1] B,
    output [32:1] S,
    output C32
);

    wire C16; // Carry out from the lower 16-bit CLA block

    // Instantiate two 16-bit CLA blocks
    cla_16bit cla_lower(
        .A(A[16:1]),
        .B(B[16:1]),
        .cin(1'b0), // no carry-in for the least significant block
        .S(S[16:1]),
        .cout(C16)
    );

    cla_16bit cla_upper(
        .A(A[32:17]),
        .B(B[32:17]),
        .cin(C16), // carry-in is the carry-out from the lower 16-bit block
        .S(S[32:17]),
        .cout(C32)
    );

endmodule
module cla_16bit(
    input [16:1] A,
    input [16:1] B,
    input cin,
    output [16:1] S,
    output cout
);

    wire [4:0] c; // intermediate carries between CLA blocks, c[0] is cin

    assign c[0] = cin;

    // Instantiate four 4-bit CLA blocks
    genvar i;
    generate
        for (i = 0; i < 4; i = i + 1) begin : cla_block
            cla_4bit cla_unit(
                .A(A[i*4+4:i*4+1]),
                .B(B[i*4+4:i*4+1]),
                .cin(c[i]),
                .S(S[i*4+4:i*4+1]),
                .cout(c[i+1])
            );
        end
    endgenerate

    assign cout = c[4]; // The carry-out of the last CLA block is the carry-out of the entire 16-bit block

endmodule
module cla_4bit(
    input [4:1] A,
    input [4:1] B,
    input cin,
    output [4:1] S,
    output cout
);

    wire [4:1] g; // generate
    wire [4:1] p; // propagate
    wire [4:0] c; // carries, c[0] is cin

    // Generate and propagate terms
    assign g = A & B;
    assign p = A ^ B;

    // Calculate carries
    assign c[0] = cin;
    assign c[1] = g[1] | (p[1] & c[0]);
    assign c[2] = g[2] | (p[2] & c[1]);
    assign c[3] = g[3] | (p[3] & c[2]);
    assign c[4] = g[4] | (p[4] & c[3]);

    // Calculate the sum
    assign S = p ^ c[4:1];

    // Carry-out is the last carry bit
    assign cout = c[4];

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

wire [6:0] carry; // Internal carry wires

// Instantiate 8 full adders
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 full_adder (
    input wire a,
    input wire b,
    input wire cin,
    output wire sum,
    output wire cout
);

assign sum = a ^ b ^ cin;
assign cout = (a & b) | (b & cin) | (a & cin);

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

    // Register declarations for pipeline stages
    reg [7:0] reg_a, reg_b; // Registers to hold inputs in the first stage
    reg [15:0] partial_product; // Register to hold the partial product
    reg mul_en_in_reg; // Register to hold the input enable signal
    
    // Pipeline stage 1 - capturing the inputs and enabling the multiplication
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            reg_a <= 0;
            reg_b <= 0;
            mul_en_in_reg <= 0;
        end else if (mul_en_in) begin
            reg_a <= mul_a;
            reg_b <= mul_b;
            mul_en_in_reg <= mul_en_in;
        end
    end
    
    // Pipeline stage 2 - performing the multiplication
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            partial_product <= 0;
            mul_en_out <= 0;
        end else begin
            if (mul_en_in_reg) begin
                // Perform multiplication when enabled
                partial_product <= reg_a * reg_b;
                mul_en_out <= mul_en_in_reg; // Propagate the enable signal to the output
            end else begin
                partial_product <= 0; // Reset partial product if not enabled
                mul_en_out <= 0; // Reset output enable signal
            end
        end
    end
    
    // Output assignment
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            mul_out <= 0;
        end else begin
            if (mul_en_out) begin
                // Output the final product when enabled
                mul_out <= partial_product;
            end else begin
                mul_out <= 0; // Reset output if not enabled
            end
        end
    end

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

// Internal registers
reg [2:0] cnt; // 3-bit counter to track the bit position
reg [3:0] data; // Register to hold the current state of data being serialized

// Sequential logic for counter and data register
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        // Asynchronous reset
        cnt <= 3'd0;
        data <= 4'd0;
        valid_out <= 1'b0;
    end else begin
        // Check if we are on the last bit
        if (cnt == 3'd3) begin
            // Load new data and reset counter
            data <= d;
            cnt <= 3'd0;
            valid_out <= 1'b1; // Output is valid on the loading of new data
        end else begin
            // Shift data and increment counter
            data <= {data[2:0], 1'b0};
            cnt <= cnt + 3'd1;
            valid_out <= (cnt == 3'd0) ? 1'b1 : 1'b0; // Output is valid only if the counter was 0 before incrementing
        end
    end
end

// Combinational logic for serial output
always @(*) begin
    // dout is assigned the MSB of the data register
    dout = data[3];
end

endmodule
module radix2_div #(
    parameter DATAWIDTH = 8
)(
    input wire clk,
    input wire rstn,
    input wire en,
    input wire [DATAWIDTH-1:0] dividend,
    input wire [DATAWIDTH-1:0] divisor,
    output reg ready,
    output reg [DATAWIDTH-1:0] quotient,
    output reg [DATAWIDTH-1:0] remainder,
    output reg vld_out
);

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

// FSM and data registers
reg [1:0] current_state, next_state;
reg [DATAWIDTH-1:0] dividend_e, divisor_e, quotient_e, remainder_e;
reg [DATAWIDTH:0] count; // Count needs an extra bit to go up to DATAWIDTH

// State transition logic
always @(posedge clk or negedge rstn) begin
    if (!rstn) begin
        current_state <= IDLE;
    end else begin
        current_state <= next_state;
    end
end

// Next state and data computation logic
always @(*) begin
    // Default assignments
    next_state = current_state;
    ready = 1'b0;
    vld_out = 1'b0;
    dividend_e = dividend_e;
    divisor_e = divisor_e << 1;
    quotient_e = quotient_e;
    remainder_e = remainder_e;

    case (current_state)
        IDLE: begin
            ready = 1'b1;
            if (en) begin
                dividend_e = dividend;
                divisor_e = divisor;
                quotient_e = 0;
                remainder_e = 0;
                count = DATAWIDTH;
                next_state = SUB;
            end
        end
        SUB: begin
            // Perform subtraction if the remainder is greater or equal to divisor
            if (remainder_e >= divisor_e) begin
                remainder_e = remainder_e - divisor_e;
                quotient_e = (quotient_e << 1) | 1'b1;
            end else begin
                quotient_e = quotient_e << 1;
            end
            next_state = SHIFT;
        end
        SHIFT: begin
            if (count == 0) begin
                next_state = DONE;
            end else begin
                remainder_e = remainder_e << 1;
                remainder_e[0] = dividend_e[DATAWIDTH-1];
                dividend_e = dividend_e << 1;
                count = count - 1'b1;
                next_state = SUB;
            end
        end
        DONE: begin
            quotient = quotient_e;
            remainder = remainder_e;
            vld_out = 1'b1;
            if (!en) begin
                next_state = IDLE;
            end
        end
    endcase
end

// Asynchronous reset logic
always @(negedge rstn) begin
    if (!rstn) begin
        quotient <= 0;
        remainder <= 0;
        dividend_e <= 0;
        divisor_e <= 0;
        quotient_e <= 0;
        remainder_e <= 0;
        count <= 0;
        ready <= 0;
        vld_out <= 0;
        current_state <= IDLE;
    end
end

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

// Internal signals
reg [9:0] sum;
reg [1:0] count;

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        // Reset
        sum <= 10'd0;
        count <= 2'd0;
        data_out <= 10'd0;
        valid_out <= 1'b0;
    end else begin
        if (valid_in) begin
            // When valid_in is high, accumulate the data
            if (count < 3) begin
                // Accumulate data if count is less than 3
                sum <= sum + data_in;
                count <= count + 1'b1;
                valid_out <= 1'b0;
            end else begin
                // On the 4th data, output the sum and reset
                sum <= sum + data_in;
                data_out <= sum + data_in;
                valid_out <= 1'b1;
                sum <= 10'd0; // Reset sum
                count <= 2'd0; // Reset count
            end
        end else if (valid_out) begin
            // Ensure valid_out is high for only 1 cycle
            valid_out <= 1'b0;
        end
    end
end

endmodule