Subversion Repositories programming

Rev

Rev 204 | Rev 206 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/* A 4-bit multiplier, following the algorithm from
 * Pg. 179, Figure 3.7. */

module MUL4_CONTROL (prod_in, alu_op, write_op, shift_op, clk, ctr);

    input prod_in, clk;
    input[0:3] ctr;
    output[0:1] alu_op;
    output write_op, shift_op;

    always @(negedge clk) begin
        if (ctr <= 4) begin
            force write_op = prod_in;
            force shift_op = 'b1;
            force alu_op = 'b10;
        end else begin
            release write_op;
            release shift_op;
            release alu_op;
        end
    end

endmodule

module MUL4_MULTIPLICAND (in, out, clk);

    input[0:3] in;
    output[0:3] out;
    input clk;

    reg[0:3] value;

    always @(in) begin
        value = in;
    end

    assign out = value;

endmodule

module MUL4_PRODUCT (left4, right4, shift_op, write_op, out, clk);

    input[0:3] left4, right4;
    input shift_op, write_op, clk;
    output[0:7] out;

    reg[0:7] value;

    always @(right4) begin
        value[0:3] = 'b0000;
        value[4:7] = right4;
    end

    always @(negedge clk) begin
        if (shift_op == 1) begin
            if (write_op == 1) begin
                value[0:3] = left4[0:3];
            end
            
            value = value >> 1;
        end
    end

    assign out = value;

endmodule

module testme;

    reg[0:3] a, b;
    wire[0:7] w_out;

    MUL4 mult (a, b, w_out);

    initial begin
        $monitor ("time=%0d a=%b b=%b prod=%b", $time, a, b, w_out);
    end
    
    initial begin
            a = 'b0011; b = 'b0011;
        #10 a = 'b0001; b = 'b1100;
        #10 a = 'b1100; b = 'b0011;
        #10 a = 'b0101; b = 'b1010;
        #8
        #2 $finish;
    end

endmodule

module MUL4 (a, b, out);

    input[0:3] a, b;
    output[0:7] out;

    reg[0:3] counter;
    reg clk;

    initial begin
        clk = 'b0;
        counter ='b0000;
        cin = 'b0;
    end

    always begin
        #1 clk = ~clk;
    end

    always @(negedge clk) begin
        counter = counter + 'b1;
    end
/*
    initial begin
        $monitor ("time=%0d counter=%b clk=%b w_mout=%b w_prod=%b w_aop=%b w_sop=%b w_wop=%b out=%b",
               $time, counter, clk, w_mout, w_prod, w_aop, w_sop, w_wop, out);
    end
*/
    wire[0:7] w_prod;
    wire[0:3] w_mout, w_alu_out;
    wire[0:1] w_aop;
    wire w_sop, w_wop, w_cout;
    reg cin;

    MUL4_PRODUCT mp (w_alu_out, a, w_sop, w_wop, w_prod, clk);
    MUL4_MULTIPLICAND mm (b, w_mout, clk);
    MUL4_CONTROL mc (w_prod[7], w_aop, w_wop, w_sop, clk, counter);
    ALU4 ma (w_prod[0:3], w_mout, cin, w_aop, w_cout, w_alu_out);

    always @(counter) begin
        if (counter == 4) begin
            force out = w_prod;
            counter = 'b1111; //reset counter
        end else begin
            release out;
        end
    end

endmodule