Rev 206 | Blame | Compare with Previous | Last modification | View Log | RSS feed
/**
* Copyright 2006, Ira W. Snyder (devel@irasnyder.com)
* License: GNU General Public License v2 (or, at your option, any later
* version)
*/
/**
* Name: Ira Snyder
* Class: CS365 - Computer Architecture
* Project #1 - Part 2
* Due: 2006-02-06
*/
/**
* File: MUL4.v
* Purpose: Implementation of a 4-bit multiplier.
*
* A 4-bit multiplier, following the algorithm from
* Pg. 179, Figure 3.7 of the book Computer Organization and Design by
* Patterson and Hennessey.
*/
// This controls the multiplication unit.
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;
// Only trigger at the negative edge of the clock. We should stay constant
// in all other cases.
always @(negedge clk) begin
// If we have a "low enough" counter, set the correct
// operations based on the input of the last bit in the product
// register.
//
// If the counter is out of range, then don't do anything, since we
// want to give the hardware some time to accept new values, for the
// next multiplication operation.
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
// This stores the "right" mutiplying number until it changes.
module MUL4_MULTIPLICAND (in, out, clk);
input[0:3] in;
output[0:3] out;
input clk;
reg[0:3] value;
// Only change the value stored in this
// register when the input changes.
always @(in) begin
value = in;
end
assign out = value;
endmodule
// This stores the 8-bit product of the multiplication unit. It gets reset
// when it's right 4 bits change.
//
// It will write the value coming in on it's left4 input every negative edge
// of the clock, only if it is getting the write signal from the control unit.
// It will then shift the value if it is getting the shift operation from the
// control unit. Since we NEVER write without a shift, this implementation is
// safe.
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;
// Storage register
reg[0:7] value;
// Reset the storage register whenever the leftmost multiplying number
// changes.
always @(right4) begin
value[0:3] = 'b0000;
value[4:7] = right4;
end
// Every time we get to the negative edge of the clock, we should check
// and see if we need to WRITE + SHIFT, or just SHIFT, based on the
// signals sent from the control unit.
always @(negedge clk) begin
if (shift_op == 1) begin
if (write_op == 1) begin
// Write the ALU's value into the left half of the register.
value[0:3] = left4[0:3];
end
// Shift the register, since we got a shift signal. This is here
// to make sure that we write FIRST, then shift SECOND.
value = value >> 1;
end
end
// Set the output to the new value in the storage register.
assign out = value;
endmodule
// The actual multiplier unit. It takes 10 "$time" units from when you give
// the inputs until the output is set correctly.
module MUL4 (a, b, out);
input[0:3] a, b;
output[0:7] out;
reg[0:3] counter;
reg clk;
// Set initial variable values
initial begin
clk = 'b0;
counter ='b0000;
cin = 'b0;
end
// Clock generator
always begin
#1 clk = ~clk;
end
// Increment the counter at the negative edge of the clock
always @(negedge clk) begin
counter = counter + 'b1;
end
/* //DEBUGGING INFORMATION
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);
// Set the output, since we have a valid result right now.
// Also reset the counter every time it reaches 4, it is used
// to keep the MUL4_CONTROL in sync.
always @(counter) begin
if (counter == 4) begin
force out = w_prod; // set the output
counter = 'b1111; // reset counter
end else begin
release out;
end
end
endmodule