Attention
This documentation is a work in progress. Expect to see errors and unfinished things.
iq_modulator Source File
1`timescale 1ns / 1ns
2
3module iq_modulator #(
4 parameter WIDTH=16,
5 // zero_bias adds a small amount of "random" noise to eliminate DC bias in output
6 parameter zero_bias=0
7) (
8 input clk,
9 input signed [WIDTH-1:0] sin,
10 input signed [WIDTH-1:0] cos,
11 output signed [WIDTH-1:0] d_out,
12 input signed [WIDTH-1:0] ampi,
13 input signed [WIDTH-1:0] ampq
14);
15// note that negative full-scale amplitude is considered invalid
16// also plan that abs(ampi+ampq*i) < 1
17
18// Universal definition; note: old and new are msb numbers, not bit widths.
19`define SAT(x,old,new) ((~|x[old:new] | &x[old:new]) ? x[new:0] : {x[old],{new{~x[old]}}})
20reg signed [2*WIDTH-1:0] p1=0, p2=0; // product registers
21wire signed [WIDTH:0] p1s = p1[2*WIDTH-2:WIDTH-2];
22wire signed [WIDTH:0] p2s = p2[2*WIDTH-2:WIDTH-2];
23wire signed [1:0] fuzz = zero_bias ? p1[WIDTH-3] : 0;
24wire signed [WIDTH+1:0] sum = p1s + p2s + 1 + fuzz; // one lsb guard, with rounding
25reg signed [WIDTH:0] d3=0;
26always @(posedge clk) begin
27 p1 <= ampi * cos;
28 p2 <= ampq * sin;
29 d3 <= `SAT(sum, WIDTH+1, WIDTH);
30end
31assign d_out = d3[WIDTH:1];
32`undef SAT
33
34endmodule