1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
module core_mul
#(parameter W=32)
( // realiza la operación a * b + c = q
input logic[W - 1:0] a, // primer sumando
b, // segundo sumando
input logic[W - 1:0] c_hi, // parte más significativa de c
c_lo, // parte menos significativa de c
input logic c_size, // 1 si c es de 2 words, cualquier otro valor si c es de 1 word
clk, // clock, ya que es una máquina de estados
rst,
add // 1 si c se suma
sig // 1 si a y b son signed
q_size // 1 si q es de 2 words, cualquier otro valor si es de 1 word
start // 1 indica que se inicie la multiplicacion
output word q_hi, // parte más significa tiva del resultado
output word q_lo, // parte menos significativa del resultado
output logic z,
n, // no hay C ni V, ya que se dejan unaffected
q_sig // 1 si q es signed, cualquier otr valor si es unsigned
rdy // 1 cuando la multiplicación está lista
//*Se asume lo siguiente:
// - Las señales de entrada son constantes desde el instante en el que start es 1 hasta que rdy sea 1
// - El valor de start puede cambiar durante la multiplicación, pero va a ser ignorado hasta que rdy sea 1
// - El valor de q es UNPREDICTABLE hasta que rdy sea 1
// - Las condiciones para iniciar una multiplicación son que rdy sea 1 y start sea 1
// - rdy solo no es 1 mientras la multiplicación se está realizando
);
//! TODO:
//! Testear que el algoritmo sirva bien @julian
module BoothMul(clk,rst,start,a,b,rdy,p);
input rst;
input signed [3:0]a,b;
output signed [7:0]p;
output rdy;
logic signed [7:0] p,next_p,p_temp;
logic next_state, pres_state;
logic [1:0] temp,next_temp;
logic [1:0] count,next_count;
logic rdy, next_rdy;
parameter IDLE = 1'b0;
parameter START = 1'b1;
always @ (posedge clk or negedge rst) begin
if(!rst) begin
p <= 8'd0;
rdy <= 1'b0;
pres_state <= 1'b0;
temp <= 2'd0;
count <= 2'd0;
end
else begin
p <= next_p;
rdy <= next_rdy;
pres_state <= next_state;
temp <= next_temp;
count <= next_count;
end
end
always @ (*) begin
case(pres_state)
IDLE:
begin
next_count = 2'b0;
next_rdy = 1'b0;
if(start) begin
next_state = START;
next_temp = {a[0],1'b0};
next_p = {4'd0,a};
end
else begin
next_state = pres_state;
next_temp = 2'd0;
next_p = 8'd0;
end
end
START:
begin
case(temp)
2'b10: p_temp = {p[7:4]-b,p[3:0]};
2'b01: p_temp = {p[7:4]+b,p[3:0]};
default: p_temp = {p[7:4],p[3:0]};
endcase
next_temp = {a[count+1],a[count]};
next_count = count + 1'b1;
next_p = p_temp >>> 1;
next_rdy = (&count) ? 1'b1 : 1'b0;
next_state = (&count) ? IDLE : pres_state;
end
endcase
end
endmodule
endmodule
|