Attention
This documentation is a work in progress. Expect to see errors and unfinished things.
complex_mul_flat Source File
1`timescale 1ns / 1ns
2// TODO:
3// Could potentially save a cycle in the flip-flop, by combining Add and Saturate into 1 cycle
4module complex_mul_flat(
5 input clk, // Rising edge clock input; all logic is synchronous in this domain
6 input gate_in, // Flag marking input data valid
7 input signed [17:0] x_I, // Multiplicand 1, real
8 input signed [17:0] x_Q, // Multiplicand 1, imag
9 input signed [17:0] y_I, // Multiplicand 2, real
10 input signed [17:0] y_Q, // Multiplicand 2, imag
11 output signed [17:0] z_I, // Result, real
12 output signed [17:0] z_Q, // Result, imag
13 output signed [35:0] z_I_all, // Result, real, large
14 output signed [35:0] z_Q_all, // Result, imag, large
15 output gate_out // Delayed version of gate_in
16);
17
18// Flow-through vector multiplier
19// Assumes there is some guarantee that you will never multiply two
20// full-scale negative values together.
21// (A + j B) * (C + j D)
22reg signed [35:0] AC=0, BD=0, AD=0, BC=0, z_I_all_i=0, z_Q_all_i=0;
23reg signed [18:0] I_small=0, Q_small=0;
24
25`define SAT(x,old,new) ((~|x[old:new] | &x[old:new]) ? x[new:0] : {x[old],{new{~x[old]}}})
26
27// Keep one guard bit through the addition step. That, and the
28// strange-looking "+1" below, reduces the average error offset
29// to -1/4 result bit.
30wire signed [19:0] z_I_sel=z_I_all_i[35:16], z_Q_sel=z_Q_all_i[35:16];
31
32always @(posedge clk) begin
33 AC <= x_I * y_I;
34 BD <= x_Q * y_Q;
35 AD <= x_I * y_Q;
36 BC <= x_Q * y_I;
37 // Fit 2 36bit signed number additions into a 35 bit number, as signed multiply
38 // produces a bogus bit
39 z_I_all_i <= AC - BD;
40 z_Q_all_i <= AD + BC + 1;
41 I_small <= `SAT(z_I_sel, 19, 18);
42 Q_small <= `SAT(z_Q_sel, 19, 18);
43end
44`undef SAT
45
46assign z_I_all = z_I_all_i;
47assign z_Q_all = z_Q_all_i;
48assign z_I = I_small[18:1];
49assign z_Q = Q_small[18:1];
50
51
52// This gate input isn't really used, but describes the length of this
53// pipeline to let users keep track of the data flow.
54
55reg [2:0] gate_sr=0;
56always @(posedge clk) gate_sr <= {gate_sr[1:0],gate_in};
57assign gate_out = gate_sr[2];
58
59endmodule