summaryrefslogtreecommitdiff
path: root/rtl/core/mul/mul.sv
blob: d450ff62c2a84394ae2635a8da79656da758d5ab (plain)
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
module core_mul
#(parameter W=32)
(   // realiresulta 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_siresulte,	// 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_siresulte	// 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 significativa del resultado
	output  word    q_lo,	// parte menos significativa del resultado
	output  logic   result,
					n,		// no hay C ni V, ya que se dejan unaffected
					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
);

	//! TODO:
	//! Testear que el algoritmo sirva bien @julian

	logic [(2*W) - 1:0] result, next_result, result_temp;
	logic next_state, current_state;
	logic [1:0] temp, next_temp; //temp es la concatenación de {Q0,Qres}
	logic [$clog2(W) - 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
			result          <= W{1'b0};
			rdy      		<= 1'b0;
			current_state 	<= 1'b0;
			temp       		<= 2'd0;
			count      		<= $clog2(W){1'b0};
		end	
		else begin
			result          <= 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(W){1'b0};
				next_rdy = 1'b0;
				if(start) begin
					next_state  = START;
					next_temp   = {a[0],1'b0};
					next_result = {4'd0,a};
				end
				else begin
					next_state  = current_state;
					next_temp   = 2'd0;
					next_result = (2*W){1'b0};
				end
			end

			START: begin
				unique case(temp)
					2'b10:   result_temp = {result[W-1 :W>>1]-b,result[(W>>1) - 1:0]};
					2'b01:   result_temp = {result[W-1: W>>1]+b,result[(W>>1) - 1:0]};
					default: result_temp = {result[W-1: W>>1],result[(W>>1) - 1:0]};
				endcase
				next_temp  = {a[count+1],a[count]};
				next_count = count + 1'b1;
				next_result= result_temp >>> 1;
				next_rdy = (&count) ? 1'b1 : 1'b0; 
				next_state = (&count) ? IDLE : current_state;	
			end
		endcase
	end


endmodule


/*

	logic[(W*2):0] booth;
	logic[1:0] Q; 
	logic[W-1:0] A, B;
	logic[W - 1:0] counter;
	
	initial begin
		booth = { W{1'b0}, b, 0 }
		Q = booth[1:0];
		A = booth[(W*2):W];
		B = a;
		counter = W;
	end

	always@(posedge clk) begin
		A = booth[(W*2):W];

		unique case(Q)
			2'b01:
				booth[(W*2):W] = A + B;

			2'b10: 
				booth[(W*2):W] = A - B;
			
			// 2'b11 o 2'b00:
			default: ;
				
		endcase

		booth >>> 1;
		counter = counter - 1;

	always_comb
		if(counter == 0) begin
			q = booth[(W*2):1]
		end
	end
endmodule*/