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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
module core_mul
#(parameter U=32)
( // realiza la operación a * b + c = q
input logic[U - 1:0] a, // primer sumando
b, // segundo sumando
input logic[U - 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, // reset
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 logic [U - 1:0] q_hi, // parte más significativa del resultado
output logic [U - 1:0] q_lo, // parte menos significativa del resultado
output logic [2*U-1:0] result,
output logic n, // no hay C ni V, ya que se dejan unaffected
z,
q_sig, // 1 si q es signed, cualquier otro 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á realiresultando
);
localparam W = U+1; //U=32 , W=33
localparam IDLE = 1'b0;
localparam START = 1'b1;
logic signed [2*W - 1:0] result_ext, next_result, result_temp; //66
logic next_state, current_state;
logic [1:0] temp, next_temp; //temp es la concatenación de {Q0,Qres}
logic [$clog2(U) - 1:0] count, next_count;
logic [2*W - 1:0] c; //66
logic [2*W - 1:0] a_ext, b_ext;
logic next_rdy;
assign a_ext = {{(W+1){sig && a[W-1]}}, a}; //65
assign b_ext = {{(W+1){sig && b[W-1]}}, b};
always_comb
if (!add)
c = {(2*W){1'b0}};
else if (c_size)
c = {2'b0, c_hi, c_lo};
else
c = {{(W+1){sig && c_lo[W-1]}}, c_lo};
always @ (posedge clk or negedge rst) begin
if(!rst) begin
result_ext <= {(2*W){1'b0}};
rdy <= 1'b0;
current_state <= 1'b0;
temp <= 2'd0;
count <= {$clog2(U){1'b0}};
end
else begin
result_ext <= next_result;
rdy <= next_rdy;
current_state <= next_state;
temp <= next_temp;
count <= next_count;
end
end
always @ (*) begin
unique case(current_state)
IDLE: begin
next_count = {$clog2(U){1'b0}};
next_rdy = 1'b0;
if(start) begin
next_state = START;
next_temp = {a_ext[0],1'b0};
next_result = {{(W/2){1'b0}},a_ext};
end
else begin
next_state = current_state;
next_temp = 2'd0;
next_result = result_ext + c;
end
end
START: begin
unique case(temp)
2'b10: result_temp = {result_ext[2*W-1: U]-b_ext, result_ext[U-1:0]};
2'b01: result_temp = {result_ext[2*W-1: U]+b_ext, result_ext[U-1:0]};
default: result_temp = result_ext;
endcase
next_temp = {a_ext[count+1],a_ext[count]};
next_count = count + 1'b1;
next_result = result_temp >>> 1;
next_rdy = (&count) ? 1'b1 : 1'b0;
next_state = (&count) ? IDLE : current_state;
result = result_ext[2*U-1:0];
q_hi = result_ext[2*U-1: U];
q_lo = result_ext[U-1: 0];
n = result_ext[2*W-1];
z = (|result_ext) ? 1'b0 : 1'b1;
end
endcase
end
endmodule
/*
module mul_tb();
logic clk,rst,start;
logic[7:0]X,Y;
logic[15:0]Z;
logic valid;
always #5 clk = ~clk;
core_mul_mul #(.W(8)) inst (.clk(clk),.rst(rst),.start(start),.a(X),.b(Y),.rdy(valid),.result(Z));
initial
$monitor($time,"a=%d, b=%d, ready=%d, Z=%d ",X,Y,valid,Z);
initial
begin
X=255;Y=150;clk=1'b1;rst=1'b0;start=1'b0;
#10 rst = 1'b1;
#10 start = 1'b1;
#10 start = 1'b0;
@valid
#10 X=-80;Y=-10;start = 1'b1;
#10 start = 1'b0;
end
endmodule
*/
|