summaryrefslogtreecommitdiff
path: root/rtl/core/mul.sv
blob: a80185193f81326a0f2c31d0bf78b064149ea85e (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
`include "core/uarch.sv"

// Realiza la operación a * b + c = q
module core_mul
(
	input  logic clk,      // clock, ya que es una máquina de estados
	input  word  a,        // primer sumando
	             b,        // segundo sumando
	             c_hi,     // parte más significativa de c
	             c_lo,     // parte menos significativa de c
	input  logic long_mul, // 1 si c es de 2 words, cualquier otro valor si c es de 1 word
	             add,      // 1 si c se suma
	             sig,      // 1 si a y b son signed
	             start,    // 1 indica que se inicie la multiplicacion

	output word  q_hi,     // parte más significativa del resultado
	             q_lo,     // parte menos significativa del resultado
	output logic n,        // no hay C ni V, ya que se dejan unaffected
	             z,
	             ready     // 1 cuando la multiplicación está lista
);

	logic wait_state;
	dword c, q;

	assign ready = !start && wait_state == {$bits(wait_state){1'b0}};
	assign {q_hi, q_lo} = q;
	assign n = long_mul ? q_hi[$bits(q_hi) - 1] : q_lo[$bits(q_lo) - 1];
	assign z = q_lo == 0 && (!long_mul || q_hi == 0);

	dsp_mul ip
	(
		.clock0(clk),
		.aclr0(1), //TODO
		.ena0(start || !ready),
		.dataa_0(a),
		.datab_0(b),
		.chainin(c),
		.signa(sig),
		.signb(sig),
		.result(q)
	);

	always_comb
		if(!add)
			c = {$bits(c){1'b0}};
		else if(long_mul)
			c = {c_hi, c_lo};
		else
			c = {{$bits(word){sig && c_lo[$bits(c_lo) - 1]}}, c_lo};

	always_ff @(posedge clk)
		if(wait_state > {$bits(wait_state){1'b0}})
			wait_state <= wait_state - 1;
		else if(start)
			wait_state <= 1;

	initial
		wait_state = 0;

endmodule