-
Notifications
You must be signed in to change notification settings - Fork 2
/
mpemu.v
97 lines (81 loc) · 2.1 KB
/
mpemu.v
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
// simulates multiplier ip core provided by xilinx
module mpemu(
input wire clk,
input wire [23:0] mpcand_i,
input wire [23:0] mplier_i,
output wire [27:0] mprod_o);
`ifndef NO_IP
// A: signed 24 bit
// B: signed 24 bit
// P: Custom Output Width MSB=46 LSB=19
// Pipeline Stages 5
mp mp(
.clk(clk),
.a(mpcand_i),
.b(mplier_i),
.p(mprod_o));
`else
reg [23:0] delay_a[4:0];
reg [23:0] delay_b[4:0];
always @(posedge clk) begin
delay_a[0] <= mpcand_i;
delay_a[1] <= delay_a[0];
delay_a[2] <= delay_a[1];
delay_a[3] <= delay_a[2];
delay_a[4] <= delay_a[3];
delay_b[0] <= mplier_i;
delay_b[1] <= delay_b[0];
delay_b[2] <= delay_b[1];
delay_b[3] <= delay_b[2];
delay_b[4] <= delay_b[3];
end
wire [23:0] delayed_a = delay_a[4];
wire [23:0] delayed_b = delay_b[4];
wire [46:0] prod_full = $signed(delayed_a) * $signed(delayed_b);
assign mprod_o = prod_full[46:19];
`endif
endmodule
module mpemu_scale(
input wire clk,
input wire [23:0] mpcand_i,
input wire [31:0] scale_i,
output wire [31:0] mprod_o);
`ifndef NO_IP
// A: signed 24 bit
// B: unsigned 32 bit
// P: Custom Output Width MSB=55 LSB=24
// Pipeline Stages 6
mp_scale mp_scale(
.clk(clk),
.a(mpcand_i),
.b(scale_i),
.p(mprod_o));
`else
reg [23:0] delay_a[6:0];
reg [31:0] delay_b[6:0];
always @(posedge clk) begin
delay_a[0] <= mpcand_i;
delay_a[1] <= delay_a[0];
delay_a[2] <= delay_a[1];
delay_a[3] <= delay_a[2];
delay_a[4] <= delay_a[3];
delay_a[5] <= delay_a[4];
delay_a[6] <= delay_a[5];
delay_b[0] <= scale_i;
delay_b[1] <= delay_b[0];
delay_b[2] <= delay_b[1];
delay_b[3] <= delay_b[2];
delay_b[4] <= delay_b[3];
delay_b[5] <= delay_b[4];
delay_b[6] <= delay_b[5];
end
wire [23:0] delayed_a = delay_a[5];
wire [31:0] delayed_b = delay_b[5];
wire signed [32:0] delayed_b_signed = {1'b0, delay_b[5]};
// for saturated delay
wire [23:0] delayed_a2 = delay_a[6];
wire [31:0] delayed_b2 = delay_b[6];
wire signed [55:0] prod_full = $signed(delayed_a) * $signed(delayed_b_signed);
assign mprod_o = prod_full[55:24];
`endif
endmodule