EDA Playground'da Dene

ALU Design Under Test(DUT)

ALU Tasarım Kodları | Bitirme projesi

Kaynak Kod

module alu (
    input  logic        clk,
    input  logic        rst_n,
    input  logic        in_valid,
    input  logic [7:0]  operand_a,
    input  logic [7:0]  operand_b,
    input  logic [2:0]  opcode,
    output logic        out_valid,
    output logic [15:0] result,
    output logic [3:0]  flags
);

    // Internal signals for combinational logic outputs
    logic [15:0] next_result;
    logic [3:0]  next_flags;

    // Opcode definitions for better readability
    localparam bit [2:0] 
        OP_ADD = 3'b000,
        OP_SUB = 3'b001,
        OP_MUL = 3'b010,
        OP_AND = 3'b011,
        OP_OR  = 3'b100,
        OP_XOR = 3'b101,
        OP_SHL = 3'b110,
        OP_SHR = 3'b111;

    // Flag bit positions
    localparam int FLAG_Z = 0; // Zero
    localparam int FLAG_N = 1; // Negative
    localparam int FLAG_C = 2; // Carry (for 8-bit operations)
    localparam int FLAG_P = 3; // Parity

    // =========================================================================
    // Combinational Block: Arithmetic & Logic Operations
    // =========================================================================
    always_comb begin
        // Default initializations to prevent latches
        next_result = 16'd0;
        next_flags  = 4'd0;

        // Perform the operation based on opcode
        case (opcode)
            OP_ADD: next_result = operand_a + operand_b;
            OP_SUB: next_result = operand_a - operand_b;
            OP_MUL: next_result = operand_a * operand_b; // 8-bit * 8-bit = 16-bit
            OP_AND: next_result = {8'h00, operand_a & operand_b};
            OP_OR:  next_result = {8'h00, operand_a | operand_b};
            OP_XOR: next_result = {8'h00, operand_a ^ operand_b};
            OP_SHL: next_result = {8'h00, operand_a} << 1;
            OP_SHR: next_result = {8'h00, operand_a} >> 1;
            default: next_result = 16'd0;
        endcase

        // Calculate status flags
        next_flags[FLAG_Z] = (next_result == 16'd0);
        next_flags[FLAG_N] = next_result[15]; 
        
        // Carry flag makes sense mainly for ADD/SUB out of the 8th bit
        if (opcode == OP_ADD || opcode == OP_SUB) begin
            next_flags[FLAG_C] = next_result[8];
        end else begin
            next_flags[FLAG_C] = 1'b0;
        end
        
        // Parity flag (XOR reduction of the result)
        next_flags[FLAG_P] = ^next_result;
    end

    // =========================================================================
    // Sequential Block: Output Registers
    // =========================================================================
    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            // Reset state
            out_valid <= 1'b0;
            result    <= 16'd0;
            flags     <= 4'd0;
        end else begin
            // Pipeline the valid signal
            out_valid <= in_valid;
            
            // Only update outputs when input data is valid
            if (in_valid) begin
                result <= next_result;
                flags  <= next_flags;
            end
        end
    end

endmodule