//Booths multiplier for two 8-bit numbers.
`timescale 1ns/100ps
module mul(in, out, clk, reset);
input [7:0]in;
input clk, reset;
output [15:0]out;
wire [15:0]out;
reg [7:0]m;
reg [8:0]q;
reg [16:0]x;
reg [7:0]a;
reg f;
reg [2:0]nextstate;
reg [2:0]state;
reg [15:0]temp;
reg [2:0] counter;
reg [5:0] count_state;
reg count;
wire [8:0]temp1;
wire [8:0]temp2;
parameter state_idle =3'b000,
state_loadm =3'b001,
state_loadq= 3'b010,
state_execute =3'b011,
state_concat =3'b100,
state_shift =3'b101,
state_divide= 3'b110;
assign out[15:0] = temp[15:0];
assign temp1[8:0] = a[7:0] + m[7:0] ;
assign temp2[8:0] = a[7:0] - m[7:0] ;
//reset block
always @(posedge clk ) begin
if (reset == 1'b1)
state <= state_idle;
else
state <= nextstate;
end
//state machine block
always @(state or count_state)begin
$display ($time, " nextstate=%b,state=%b,temp1=%b,temp2=%b",
nextstate,state,temp1,temp2);
case(state)
state_idle : if (count_state < 6'h36)
nextstate <= state_loadm;
else
nextstate <= state_idle;
state_loadm : nextstate <= state_loadq;
state_loadq : nextstate <=state_execute;
state_execute : nextstate <= state_concat;
state_concat : nextstate <= state_shift;
state_shift : nextstate <= state_divide;
state_divide : if (count_state > 6'h36)
nextstate <= state_idle;
else
nextstate <= state_execute;
default : nextstate <= state_idle;
endcase
$display($time,"m=%b,a=%b,q=%b,x=%b,nextstate=%b,state=%b,counter=%b,temp=%b,out=%b,",m,a,q,x,nextstate,state,counter,temp,out);
end
//added count_state, which is a counter for state counting
always @(posedge clk) begin
if (reset)
count_state <= 6'b0;
else
count_state <= count_state + 1;
end
//m block (multiplicand block)
always @(posedge clk) begin
if ((state == state_idle) || reset)
m <= 8'b0000_0000;
else begin
if (state == state_loadm)begin
m <= in;
$display($time,"loadm=%b,a=%b,q=%b,temp1=%b,temp2=%b",m,a,q,temp1,temp2);
end
else m <= m;
end
end
//count block
always @(posedge clk) begin
if (((state == state_execute) && (counter <=
3'b111)) || (reset))
count <= 1'b0;
else begin
if ((state == state_shift) && (counter < 3'b111))
count <= 1'b1;
else count <= count;
end
end
//counter block
always @(posedge clk) begin
if((state == state_idle) || (reset))
counter[2:0] <= 3'b000;
else begin
if((state == state_execute) && (count == 1'b1)
&& (counter < 3'b111)) begin
counter <= counter + 1;
$display ($time, " in b'11 aftercount x = %b, a=%b,
q=%b, counter = %b", x,a,q,counter);
end
else counter[2:0] <= counter[2:0];
end
end
//q block (multiplier block)
always @(posedge clk) begin
if ((state == state_idle) || reset)
q <= 8'b0000_0000;
else begin
if (state == state_loadq)begin
q[8:0] <= {in[7],in[7:0]};
$display($time,"loadq=%b,a=%b,q=%b",m,a,q);
end
else begin
if ((state == state_divide) && (counter <
3'b111)) begin
q[8:0] <= x[8:0];
$display ($time," after divideq x=%b,a=%b,q=%b,counter=%b",x,a,q,counter);
end
else begin
if ((state == state_execute) && (counter == 3'b111))
q[1] <= 1'b0;
else q[1] <= q[1];
end
end
end
end
//a block (accumulator block)
always @(posedge clk) begin
if ((state == state_idle) || reset)
a[7:0] <= 8'b0000_0000;
else begin
if ((state == state_execute) && (counter <=
3'b111))begin
$display($time,"counter=%b,state=%b",counter,state);
if (((f == 1'b0) && (q[1] == 1'b0) &&
(q[0] == 1'b1)) || ((f==1'b1) && (q[1] == 1'b0) && (q[0]
== 1'b0)))
a[7:0] <= temp1[7:0];
else begin
if (((f == 1'b0) && (q[1] == 1'b1) &&
(q[0] == 1'b1)) || ((f==1'b1) && (q[1] == 1'b1) && (q[0]
== 1'b0)))
a[7:0] <= temp2[7:0];
else begin
a[7:0] <= a[7:0];
$display($time,"a=%b,q=%b",a,q);
end
end
$display($time,"a=%b,temp=%b,out=%b,",m,a,q,temp1,temp2,x,nextstate,f,temp,out);
end
else begin
if ((state == state_divide) && (counter <
3'b111)) begin
a[7:0] <= {x[16],x[16:9]};
$display ($time, " after dividea - x = %b, a=%b,
q=%b", x, a, q);
end
end
end
end
//f block
always @(posedge clk) begin
if ((state == state_idle) || reset || ((state == 3'b011)
&& (counter <= 3'b111)&&(f == 1'b1) && (q[1]
== 1'b0) && (q[0] == 1'b0)))
f <= 1'b0;
else begin
if ((state == state_execute) && (counter <=
3'b111) && (f == 1'b0) && (q[1]== 1'b1) && (q[0]
== 1'b1))begin
f <= 1'b1;
$display($time,"counter=%b,state=%b",counter,state);
end
end
end
//temp block (temp contains the output)
always @(posedge clk) begin
if ((state == state_idle) || reset)
temp <= 16'h0000;
else begin
if ((state == state_execute) && (counter == 3'b111))begin
temp[15:0] <= {a[7:0],q[8:1]};
$display ($time, " counter= %b - YOU CAME IN checkCOUNTER,
temp=%b,x=%b", counter,temp,x);
end
else begin
if ((state == state_execute) && (counter <=
3'b111))begin
$display($time,"counter=%b,state=%b",counter,state);
if ((m[7:0] == 8'b00000000) || (q[8:0] == 8'b00000000))
begin
temp[15:0] <= {a[7:0],q[8:1]};
end
end
end
end
end
//x block (accumulator concatenated to the multiplier
is x)
always @(posedge clk) begin
if ((state == state_idle) || reset)
x <= 17'h00000;
else begin
if (state == state_concat) begin
$display($time,"beforeconcat x=%b,a=%b,q=%b",x,a,q);
x[16:0] <= {a[7:0],q[8:0]};
$display($time,"afterconcat x=%b,temp1=%b,temp2=%b",x,temp1,temp2);
end
else begin
if ((state == state_shift) && (counter < 3'b111
))begin
x[16:0] <= {x[16],x[16:1]};
$display($time,"x=aftershift=%b",x);
end
end
end
end
endmodule