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