| 207 |
ira |
1 |
/**
|
|
|
2 |
* Copyright 2006, Ira W. Snyder (devel@irasnyder.com)
|
|
|
3 |
* License: GNU General Public License v2 (or, at your option, any later
|
|
|
4 |
* version)
|
|
|
5 |
*/
|
| 198 |
ira |
6 |
|
| 207 |
ira |
7 |
/**
|
|
|
8 |
* Name: Ira Snyder
|
|
|
9 |
* Class: CS365 - Computer Architecture
|
|
|
10 |
* Project #1 - Part 2
|
|
|
11 |
* Due: 2006-02-06
|
|
|
12 |
*/
|
|
|
13 |
|
|
|
14 |
/**
|
|
|
15 |
* File: MUL4.v
|
|
|
16 |
* Purpose: Implementation of a 4-bit multiplier.
|
|
|
17 |
*
|
|
|
18 |
* A 4-bit multiplier, following the algorithm from
|
|
|
19 |
* Pg. 179, Figure 3.7 of the book Computer Organization and Design by
|
|
|
20 |
* Patterson and Hennessey.
|
|
|
21 |
*/
|
|
|
22 |
|
|
|
23 |
// This controls the multiplication unit.
|
| 204 |
ira |
24 |
module MUL4_CONTROL (prod_in, alu_op, write_op, shift_op, clk, ctr);
|
| 198 |
ira |
25 |
|
|
|
26 |
input prod_in, clk;
|
| 204 |
ira |
27 |
input[0:3] ctr;
|
| 198 |
ira |
28 |
output[0:1] alu_op;
|
|
|
29 |
output write_op, shift_op;
|
|
|
30 |
|
| 207 |
ira |
31 |
// Only trigger at the negative edge of the clock. We should stay constant
|
|
|
32 |
// in all other cases.
|
| 204 |
ira |
33 |
always @(negedge clk) begin
|
| 207 |
ira |
34 |
// If we have a "low enough" counter, set the correct
|
|
|
35 |
// operations based on the input of the last bit in the product
|
|
|
36 |
// register.
|
|
|
37 |
//
|
|
|
38 |
// If the counter is out of range, then don't do anything, since we
|
|
|
39 |
// want to give the hardware some time to accept new values, for the
|
|
|
40 |
// next multiplication operation.
|
| 204 |
ira |
41 |
if (ctr <= 4) begin
|
|
|
42 |
force write_op = prod_in;
|
|
|
43 |
force shift_op = 'b1;
|
|
|
44 |
force alu_op = 'b10;
|
|
|
45 |
end else begin
|
|
|
46 |
release write_op;
|
|
|
47 |
release shift_op;
|
|
|
48 |
release alu_op;
|
|
|
49 |
end
|
| 198 |
ira |
50 |
end
|
|
|
51 |
|
|
|
52 |
endmodule
|
|
|
53 |
|
| 207 |
ira |
54 |
// This stores the "right" mutiplying number until it changes.
|
| 198 |
ira |
55 |
module MUL4_MULTIPLICAND (in, out, clk);
|
|
|
56 |
|
|
|
57 |
input[0:3] in;
|
|
|
58 |
output[0:3] out;
|
|
|
59 |
input clk;
|
|
|
60 |
|
|
|
61 |
reg[0:3] value;
|
|
|
62 |
|
| 207 |
ira |
63 |
// Only change the value stored in this
|
|
|
64 |
// register when the input changes.
|
| 198 |
ira |
65 |
always @(in) begin
|
|
|
66 |
value = in;
|
|
|
67 |
end
|
|
|
68 |
|
|
|
69 |
assign out = value;
|
|
|
70 |
|
|
|
71 |
endmodule
|
|
|
72 |
|
| 207 |
ira |
73 |
// This stores the 8-bit product of the multiplication unit. It gets reset
|
|
|
74 |
// when it's right 4 bits change.
|
|
|
75 |
//
|
|
|
76 |
// It will write the value coming in on it's left4 input every negative edge
|
|
|
77 |
// of the clock, only if it is getting the write signal from the control unit.
|
|
|
78 |
// It will then shift the value if it is getting the shift operation from the
|
|
|
79 |
// control unit. Since we NEVER write without a shift, this implementation is
|
|
|
80 |
// safe.
|
| 198 |
ira |
81 |
module MUL4_PRODUCT (left4, right4, shift_op, write_op, out, clk);
|
|
|
82 |
|
|
|
83 |
input[0:3] left4, right4;
|
|
|
84 |
input shift_op, write_op, clk;
|
|
|
85 |
output[0:7] out;
|
|
|
86 |
|
| 207 |
ira |
87 |
// Storage register
|
| 198 |
ira |
88 |
reg[0:7] value;
|
|
|
89 |
|
| 207 |
ira |
90 |
// Reset the storage register whenever the leftmost multiplying number
|
|
|
91 |
// changes.
|
| 198 |
ira |
92 |
always @(right4) begin
|
|
|
93 |
value[0:3] = 'b0000;
|
|
|
94 |
value[4:7] = right4;
|
|
|
95 |
end
|
|
|
96 |
|
| 207 |
ira |
97 |
// Every time we get to the negative edge of the clock, we should check
|
|
|
98 |
// and see if we need to WRITE + SHIFT, or just SHIFT, based on the
|
|
|
99 |
// signals sent from the control unit.
|
| 204 |
ira |
100 |
always @(negedge clk) begin
|
| 198 |
ira |
101 |
if (shift_op == 1) begin
|
|
|
102 |
if (write_op == 1) begin
|
| 207 |
ira |
103 |
|
|
|
104 |
// Write the ALU's value into the left half of the register.
|
| 198 |
ira |
105 |
value[0:3] = left4[0:3];
|
|
|
106 |
end
|
| 207 |
ira |
107 |
|
|
|
108 |
// Shift the register, since we got a shift signal. This is here
|
|
|
109 |
// to make sure that we write FIRST, then shift SECOND.
|
| 198 |
ira |
110 |
value = value >> 1;
|
|
|
111 |
end
|
|
|
112 |
end
|
|
|
113 |
|
| 207 |
ira |
114 |
// Set the output to the new value in the storage register.
|
| 198 |
ira |
115 |
assign out = value;
|
|
|
116 |
|
|
|
117 |
endmodule
|
|
|
118 |
|
| 207 |
ira |
119 |
// The actual multiplier unit. It takes 10 "$time" units from when you give
|
|
|
120 |
// the inputs until the output is set correctly.
|
| 205 |
ira |
121 |
module MUL4 (a, b, out);
|
| 204 |
ira |
122 |
|
|
|
123 |
input[0:3] a, b;
|
|
|
124 |
output[0:7] out;
|
|
|
125 |
|
|
|
126 |
reg[0:3] counter;
|
|
|
127 |
reg clk;
|
|
|
128 |
|
| 207 |
ira |
129 |
// Set initial variable values
|
| 204 |
ira |
130 |
initial begin
|
|
|
131 |
clk = 'b0;
|
|
|
132 |
counter ='b0000;
|
|
|
133 |
cin = 'b0;
|
|
|
134 |
end
|
|
|
135 |
|
| 207 |
ira |
136 |
// Clock generator
|
| 204 |
ira |
137 |
always begin
|
|
|
138 |
#1 clk = ~clk;
|
|
|
139 |
end
|
|
|
140 |
|
| 207 |
ira |
141 |
// Increment the counter at the negative edge of the clock
|
| 204 |
ira |
142 |
always @(negedge clk) begin
|
|
|
143 |
counter = counter + 'b1;
|
|
|
144 |
end
|
| 207 |
ira |
145 |
|
| 206 |
ira |
146 |
/* //DEBUGGING INFORMATION
|
| 204 |
ira |
147 |
initial begin
|
|
|
148 |
$monitor ("time=%0d counter=%b clk=%b w_mout=%b w_prod=%b w_aop=%b w_sop=%b w_wop=%b out=%b",
|
|
|
149 |
$time, counter, clk, w_mout, w_prod, w_aop, w_sop, w_wop, out);
|
|
|
150 |
end
|
| 206 |
ira |
151 |
*/
|
| 207 |
ira |
152 |
|
| 204 |
ira |
153 |
wire[0:7] w_prod;
|
|
|
154 |
wire[0:3] w_mout, w_alu_out;
|
|
|
155 |
wire[0:1] w_aop;
|
|
|
156 |
wire w_sop, w_wop, w_cout;
|
|
|
157 |
reg cin;
|
|
|
158 |
|
|
|
159 |
MUL4_PRODUCT mp (w_alu_out, a, w_sop, w_wop, w_prod, clk);
|
|
|
160 |
MUL4_MULTIPLICAND mm (b, w_mout, clk);
|
|
|
161 |
MUL4_CONTROL mc (w_prod[7], w_aop, w_wop, w_sop, clk, counter);
|
|
|
162 |
ALU4 ma (w_prod[0:3], w_mout, cin, w_aop, w_cout, w_alu_out);
|
|
|
163 |
|
| 206 |
ira |
164 |
// Set the output, since we have a valid result right now.
|
|
|
165 |
// Also reset the counter every time it reaches 4, it is used
|
|
|
166 |
// to keep the MUL4_CONTROL in sync.
|
| 204 |
ira |
167 |
always @(counter) begin
|
|
|
168 |
if (counter == 4) begin
|
| 206 |
ira |
169 |
force out = w_prod; // set the output
|
| 207 |
ira |
170 |
counter = 'b1111; // reset counter
|
| 204 |
ira |
171 |
end else begin
|
|
|
172 |
release out;
|
|
|
173 |
end
|
|
|
174 |
end
|
|
|
175 |
|
|
|
176 |
endmodule
|
|
|
177 |
|