From 0df4b801a34697f2058b4a7b95e08d2a0576c9db Mon Sep 17 00:00:00 2001 From: Ben Hilburn Date: Thu, 10 Oct 2013 10:17:27 -0700 Subject: Squashed B200 FPGA Source. Code from Josh Blum, Ian Buckley, and Matt Ettus. --- fpga/usrp3/lib/dsp/Makefile.srcs | 38 +++++++ fpga/usrp3/lib/dsp/README.txt | 0 fpga/usrp3/lib/dsp/acc.v | 33 ++++++ fpga/usrp3/lib/dsp/add2.v | 16 +++ fpga/usrp3/lib/dsp/add2_and_clip.v | 12 +++ fpga/usrp3/lib/dsp/add2_and_clip_reg.v | 25 +++++ fpga/usrp3/lib/dsp/add2_and_round.v | 16 +++ fpga/usrp3/lib/dsp/add2_and_round_reg.v | 21 ++++ fpga/usrp3/lib/dsp/add2_reg.v | 22 ++++ fpga/usrp3/lib/dsp/cic_dec_shifter.v | 94 +++++++++++++++++ fpga/usrp3/lib/dsp/cic_decim.v | 76 ++++++++++++++ fpga/usrp3/lib/dsp/cic_int_shifter.v | 88 ++++++++++++++++ fpga/usrp3/lib/dsp/cic_interp.v | 75 ++++++++++++++ fpga/usrp3/lib/dsp/cic_strober.v | 33 ++++++ fpga/usrp3/lib/dsp/clip.v | 24 +++++ fpga/usrp3/lib/dsp/clip_reg.v | 34 ++++++ fpga/usrp3/lib/dsp/cordic_stage.v | 48 +++++++++ fpga/usrp3/lib/dsp/cordic_z24.v | 112 ++++++++++++++++++++ fpga/usrp3/lib/dsp/ddc_chain.v | 164 +++++++++++++++++++++++++++++ fpga/usrp3/lib/dsp/duc_chain.v | 146 ++++++++++++++++++++++++++ fpga/usrp3/lib/dsp/hb_dec.v | 177 ++++++++++++++++++++++++++++++++ fpga/usrp3/lib/dsp/hb_interp.v | 165 +++++++++++++++++++++++++++++ fpga/usrp3/lib/dsp/round.v | 47 +++++++++ fpga/usrp3/lib/dsp/round_reg.v | 32 ++++++ fpga/usrp3/lib/dsp/round_sd.v | 23 +++++ fpga/usrp3/lib/dsp/rx_dcoffset.v | 46 +++++++++ fpga/usrp3/lib/dsp/rx_frontend.v | 78 ++++++++++++++ fpga/usrp3/lib/dsp/rx_frontend_tb.v | 45 ++++++++ fpga/usrp3/lib/dsp/sign_extend.v | 23 +++++ fpga/usrp3/lib/dsp/small_hb_dec.v | 124 ++++++++++++++++++++++ fpga/usrp3/lib/dsp/small_hb_int.v | 99 ++++++++++++++++++ fpga/usrp3/lib/dsp/srl.v | 27 +++++ 32 files changed, 1963 insertions(+) create mode 100644 fpga/usrp3/lib/dsp/Makefile.srcs create mode 100644 fpga/usrp3/lib/dsp/README.txt create mode 100644 fpga/usrp3/lib/dsp/acc.v create mode 100644 fpga/usrp3/lib/dsp/add2.v create mode 100644 fpga/usrp3/lib/dsp/add2_and_clip.v create mode 100644 fpga/usrp3/lib/dsp/add2_and_clip_reg.v create mode 100644 fpga/usrp3/lib/dsp/add2_and_round.v create mode 100644 fpga/usrp3/lib/dsp/add2_and_round_reg.v create mode 100644 fpga/usrp3/lib/dsp/add2_reg.v create mode 100644 fpga/usrp3/lib/dsp/cic_dec_shifter.v create mode 100644 fpga/usrp3/lib/dsp/cic_decim.v create mode 100644 fpga/usrp3/lib/dsp/cic_int_shifter.v create mode 100644 fpga/usrp3/lib/dsp/cic_interp.v create mode 100644 fpga/usrp3/lib/dsp/cic_strober.v create mode 100644 fpga/usrp3/lib/dsp/clip.v create mode 100644 fpga/usrp3/lib/dsp/clip_reg.v create mode 100644 fpga/usrp3/lib/dsp/cordic_stage.v create mode 100644 fpga/usrp3/lib/dsp/cordic_z24.v create mode 100644 fpga/usrp3/lib/dsp/ddc_chain.v create mode 100644 fpga/usrp3/lib/dsp/duc_chain.v create mode 100644 fpga/usrp3/lib/dsp/hb_dec.v create mode 100644 fpga/usrp3/lib/dsp/hb_interp.v create mode 100644 fpga/usrp3/lib/dsp/round.v create mode 100644 fpga/usrp3/lib/dsp/round_reg.v create mode 100644 fpga/usrp3/lib/dsp/round_sd.v create mode 100644 fpga/usrp3/lib/dsp/rx_dcoffset.v create mode 100644 fpga/usrp3/lib/dsp/rx_frontend.v create mode 100644 fpga/usrp3/lib/dsp/rx_frontend_tb.v create mode 100644 fpga/usrp3/lib/dsp/sign_extend.v create mode 100644 fpga/usrp3/lib/dsp/small_hb_dec.v create mode 100644 fpga/usrp3/lib/dsp/small_hb_int.v create mode 100644 fpga/usrp3/lib/dsp/srl.v (limited to 'fpga/usrp3/lib/dsp') diff --git a/fpga/usrp3/lib/dsp/Makefile.srcs b/fpga/usrp3/lib/dsp/Makefile.srcs new file mode 100644 index 000000000..3896ac5b5 --- /dev/null +++ b/fpga/usrp3/lib/dsp/Makefile.srcs @@ -0,0 +1,38 @@ +# +# Copyright 2013 Ettus Research LLC +# + +################################################## +# DSP Sources +################################################## +DSP_SRCS = $(abspath $(addprefix $(BASE_DIR)/../lib/dsp/, \ +ddc_chain.v \ +duc_chain.v \ +sign_extend.v \ +cordic_z24.v \ +clip_reg.v \ +cordic_stage.v \ +clip.v \ +cic_strober.v \ +cic_decim.v \ +cic_interp.v \ +cic_dec_shifter.v \ +cic_int_shifter.v \ +small_hb_dec.v \ +small_hb_int.v \ +hb_dec.v \ +hb_interp.v \ +round_sd.v \ +add2_and_clip_reg.v \ +add2_and_clip.v \ +add2.v \ +add2_reg.v \ +add2_and_round_reg.v \ +add2_and_round.v \ +round_reg.v \ +round.v \ +srl.v \ +acc.v \ +rx_frontend.v \ +rx_dcoffset.v \ +)) diff --git a/fpga/usrp3/lib/dsp/README.txt b/fpga/usrp3/lib/dsp/README.txt new file mode 100644 index 000000000..e69de29bb diff --git a/fpga/usrp3/lib/dsp/acc.v b/fpga/usrp3/lib/dsp/acc.v new file mode 100644 index 000000000..86b68512f --- /dev/null +++ b/fpga/usrp3/lib/dsp/acc.v @@ -0,0 +1,33 @@ +// +// Copyright 2011 Ettus Research LLC +// + + + +module acc + #(parameter IWIDTH=16, OWIDTH=30) + (input clk, + input clear, + input acc, + input [IWIDTH-1:0] in, + output reg [OWIDTH-1:0] out); + + wire [OWIDTH-1:0] in_signext; + sign_extend #(.bits_in(IWIDTH),.bits_out(OWIDTH)) + acc_signext (.in(in),.out(in_signext)); + + // CLEAR & ~ACC --> clears the accumulator + // CLEAR & ACC --> loads the accumulator + // ~CLEAR & ACC --> accumulates + // ~CLEAR & ~ACC --> hold + + wire [OWIDTH-1:0] addend1 = clear ? 0 : out; + wire [OWIDTH-1:0] addend2 = ~acc ? 0 : in_signext; + wire [OWIDTH-1:0] sum_int = addend1 + addend2; + + always @(posedge clk) + out <= sum_int; + +endmodule // acc + + diff --git a/fpga/usrp3/lib/dsp/add2.v b/fpga/usrp3/lib/dsp/add2.v new file mode 100644 index 000000000..124f9d6ca --- /dev/null +++ b/fpga/usrp3/lib/dsp/add2.v @@ -0,0 +1,16 @@ +// +// Copyright 2011 Ettus Research LLC +// + + + +module add2 + #(parameter WIDTH=16) + (input [WIDTH-1:0] in1, + input [WIDTH-1:0] in2, + output [WIDTH-1:0] sum); + + wire [WIDTH:0] sum_int = {in1[WIDTH-1],in1} + {in2[WIDTH-1],in2}; + assign sum = sum_int[WIDTH:1]; // Note -- will have some bias + +endmodule // add2 diff --git a/fpga/usrp3/lib/dsp/add2_and_clip.v b/fpga/usrp3/lib/dsp/add2_and_clip.v new file mode 100644 index 000000000..663f5d004 --- /dev/null +++ b/fpga/usrp3/lib/dsp/add2_and_clip.v @@ -0,0 +1,12 @@ + +module add2_and_clip + #(parameter WIDTH=16) + (input [WIDTH-1:0] in1, + input [WIDTH-1:0] in2, + output [WIDTH-1:0] sum); + + wire [WIDTH:0] sum_int = {in1[WIDTH-1],in1} + {in2[WIDTH-1],in2}; + clip #(.bits_in(WIDTH+1),.bits_out(WIDTH)) clip + (.in(sum_int),.out(sum)); + +endmodule // add2_and_clip diff --git a/fpga/usrp3/lib/dsp/add2_and_clip_reg.v b/fpga/usrp3/lib/dsp/add2_and_clip_reg.v new file mode 100644 index 000000000..8073b3b54 --- /dev/null +++ b/fpga/usrp3/lib/dsp/add2_and_clip_reg.v @@ -0,0 +1,25 @@ + +module add2_and_clip_reg + #(parameter WIDTH=16) + (input clk, + input rst, + input [WIDTH-1:0] in1, + input [WIDTH-1:0] in2, + input strobe_in, + output reg [WIDTH-1:0] sum, + output reg strobe_out); + + wire [WIDTH-1:0] sum_int; + + add2_and_clip #(.WIDTH(WIDTH)) add2_and_clip (.in1(in1),.in2(in2),.sum(sum_int)); + + always @(posedge clk) + if(rst) + sum <= 0; + else if(strobe_in) + sum <= sum_int; + + always @(posedge clk) + strobe_out <= strobe_in; + +endmodule // add2_and_clip_reg diff --git a/fpga/usrp3/lib/dsp/add2_and_round.v b/fpga/usrp3/lib/dsp/add2_and_round.v new file mode 100644 index 000000000..9d0914414 --- /dev/null +++ b/fpga/usrp3/lib/dsp/add2_and_round.v @@ -0,0 +1,16 @@ +// +// Copyright 2011 Ettus Research LLC +// + + + +module add2_and_round + #(parameter WIDTH=16) + (input [WIDTH-1:0] in1, + input [WIDTH-1:0] in2, + output [WIDTH-1:0] sum); + + wire [WIDTH:0] sum_int = {in1[WIDTH-1],in1} + {in2[WIDTH-1],in2}; + assign sum = sum_int[WIDTH:1] + (sum_int[WIDTH] & sum_int[0]); + +endmodule // add2_and_round diff --git a/fpga/usrp3/lib/dsp/add2_and_round_reg.v b/fpga/usrp3/lib/dsp/add2_and_round_reg.v new file mode 100644 index 000000000..cb20a3c1b --- /dev/null +++ b/fpga/usrp3/lib/dsp/add2_and_round_reg.v @@ -0,0 +1,21 @@ +// +// Copyright 2011 Ettus Research LLC +// + + + +module add2_and_round_reg + #(parameter WIDTH=16) + (input clk, + input [WIDTH-1:0] in1, + input [WIDTH-1:0] in2, + output reg [WIDTH-1:0] sum); + + wire [WIDTH-1:0] sum_int; + + add2_and_round #(.WIDTH(WIDTH)) add2_n_rnd (.in1(in1),.in2(in2),.sum(sum_int)); + + always @(posedge clk) + sum <= sum_int; + +endmodule // add2_and_round_reg diff --git a/fpga/usrp3/lib/dsp/add2_reg.v b/fpga/usrp3/lib/dsp/add2_reg.v new file mode 100644 index 000000000..3ac93ae2e --- /dev/null +++ b/fpga/usrp3/lib/dsp/add2_reg.v @@ -0,0 +1,22 @@ +// +// Copyright 2011 Ettus Research LLC +// + + + +module add2_reg + #(parameter WIDTH=16) + (input clk, + input [WIDTH-1:0] in1, + input [WIDTH-1:0] in2, + output reg [WIDTH-1:0] sum); + + wire [WIDTH-1:0] sum_int; + + add2 #(.WIDTH(WIDTH)) add2 (.in1(in1),.in2(in2),.sum(sum_int)); + + always @(posedge clk) + sum <= sum_int; + +endmodule // add2_reg + diff --git a/fpga/usrp3/lib/dsp/cic_dec_shifter.v b/fpga/usrp3/lib/dsp/cic_dec_shifter.v new file mode 100644 index 000000000..efc54c106 --- /dev/null +++ b/fpga/usrp3/lib/dsp/cic_dec_shifter.v @@ -0,0 +1,94 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003 Matt Ettus +// + +// + + +// NOTE This only works for N=4, max decim rate of 128 +// NOTE signal "rate" is EQUAL TO the actual rate, no more -1 BS + +module cic_dec_shifter(rate,signal_in,signal_out); + parameter bw = 16; + parameter maxbitgain = 28; + + input [7:0] rate; + input wire [bw+maxbitgain-1:0] signal_in; + output reg [bw-1:0] signal_out; + + function [4:0] bitgain; + input [7:0] rate; + case(rate) + // Exact Cases -- N*log2(rate) + 8'd1 : bitgain = 0; + 8'd2 : bitgain = 4; + 8'd4 : bitgain = 8; + 8'd8 : bitgain = 12; + 8'd16 : bitgain = 16; + 8'd32 : bitgain = 20; + 8'd64 : bitgain = 24; + 8'd128 : bitgain = 28; + + // Nearest without overflow -- ceil(N*log2(rate)) + 8'd3 : bitgain = 7; + 8'd5 : bitgain = 10; + 8'd6 : bitgain = 11; + 8'd7 : bitgain = 12; + 8'd9 : bitgain = 13; + 8'd10,8'd11 : bitgain = 14; + 8'd12,8'd13 : bitgain = 15; + 8'd14,8'd15 : bitgain = 16; + 8'd17,8'd18,8'd19 : bitgain = 17; + 8'd20,8'd21,8'd22 : bitgain = 18; + 8'd23,8'd24,8'd25,8'd26 : bitgain = 19; + 8'd27,8'd28,8'd29,8'd30,8'd31 : bitgain = 20; + 8'd33,8'd34,8'd35,8'd36,8'd37,8'd38 : bitgain = 21; + 8'd39,8'd40,8'd41,8'd42,8'd43,8'd44,8'd45 : bitgain = 22; + 8'd46,8'd47,8'd48,8'd49,8'd50,8'd51,8'd52,8'd53 : bitgain = 23; + 8'd54,8'd55,8'd56,8'd57,8'd58,8'd59,8'd60,8'd61,8'd62,8'd63 : bitgain = 24; + 8'd65,8'd66,8'd67,8'd68,8'd69,8'd70,8'd71,8'd72,8'd73,8'd74,8'd75,8'd76 : bitgain = 25; + 8'd77,8'd78,8'd79,8'd80,8'd81,8'd82,8'd83,8'd84,8'd85,8'd86,8'd87,8'd88,8'd89,8'd90 : bitgain = 26; + 8'd91,8'd92,8'd93,8'd94,8'd95,8'd96,8'd97,8'd98,8'd99,8'd100,8'd101,8'd102,8'd103,8'd104,8'd105,8'd106,8'd107 : bitgain = 27; + default : bitgain = 28; + endcase // case(rate) + endfunction // bitgain + + wire [4:0] shift = bitgain(rate); + + // We should be able to do this, but can't .... + // assign signal_out = signal_in[shift+bw-1:shift]; + + always @* + case(shift) + 5'd0 : signal_out = signal_in[0+bw-1:0]; + 5'd4 : signal_out = signal_in[4+bw-1:4]; + 5'd7 : signal_out = signal_in[7+bw-1:7]; + 5'd8 : signal_out = signal_in[8+bw-1:8]; + 5'd10 : signal_out = signal_in[10+bw-1:10]; + 5'd11 : signal_out = signal_in[11+bw-1:11]; + 5'd12 : signal_out = signal_in[12+bw-1:12]; + 5'd13 : signal_out = signal_in[13+bw-1:13]; + 5'd14 : signal_out = signal_in[14+bw-1:14]; + 5'd15 : signal_out = signal_in[15+bw-1:15]; + 5'd16 : signal_out = signal_in[16+bw-1:16]; + 5'd17 : signal_out = signal_in[17+bw-1:17]; + 5'd18 : signal_out = signal_in[18+bw-1:18]; + 5'd19 : signal_out = signal_in[19+bw-1:19]; + 5'd20 : signal_out = signal_in[20+bw-1:20]; + 5'd21 : signal_out = signal_in[21+bw-1:21]; + 5'd22 : signal_out = signal_in[22+bw-1:22]; + 5'd23 : signal_out = signal_in[23+bw-1:23]; + 5'd24 : signal_out = signal_in[24+bw-1:24]; + 5'd25 : signal_out = signal_in[25+bw-1:25]; + 5'd26 : signal_out = signal_in[26+bw-1:26]; + 5'd27 : signal_out = signal_in[27+bw-1:27]; + 5'd28 : signal_out = signal_in[28+bw-1:28]; + + default : signal_out = signal_in[28+bw-1:28]; + endcase // case(shift) + +endmodule // cic_dec_shifter + diff --git a/fpga/usrp3/lib/dsp/cic_decim.v b/fpga/usrp3/lib/dsp/cic_decim.v new file mode 100644 index 000000000..feb785de8 --- /dev/null +++ b/fpga/usrp3/lib/dsp/cic_decim.v @@ -0,0 +1,76 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003 Matt Ettus +// + +// + + +module cic_decim + #(parameter bw = 16, parameter N = 4, parameter log2_of_max_rate = 7) + (input clock, + input reset, + input enable, + input [7:0] rate, + input strobe_in, + input strobe_out, + input [bw-1:0] signal_in, + output reg [bw-1:0] signal_out); + + localparam maxbitgain = N * log2_of_max_rate; + + wire [bw+maxbitgain-1:0] signal_in_ext; + reg [bw+maxbitgain-1:0] integrator [0:N-1]; + reg [bw+maxbitgain-1:0] differentiator [0:N-1]; + reg [bw+maxbitgain-1:0] pipeline [0:N-1]; + reg [bw+maxbitgain-1:0] sampler; + + integer i; + + sign_extend #(bw,bw+maxbitgain) + ext_input (.in(signal_in),.out(signal_in_ext)); + + always @(posedge clock) + if(~enable) + for(i=0;i 1) + assign round_corr_nearest_safe = (~in[bits_in-1] & (&in[bits_in-2:bits_out])) ? 0 : + round_corr_nearest; + else + assign round_corr_nearest_safe = round_corr_nearest; + endgenerate + + + assign round_corr = round_to_nearest ? round_corr_nearest_safe : + trunc ? round_corr_trunc : + round_to_zero ? round_corr_rtz : + 0; // default to trunc + + assign out = in[bits_in-1:bits_in-bits_out] + round_corr; + + assign err = in - {out,{(bits_in-bits_out){1'b0}}}; + +endmodule // round diff --git a/fpga/usrp3/lib/dsp/round_reg.v b/fpga/usrp3/lib/dsp/round_reg.v new file mode 100644 index 000000000..c8c77f518 --- /dev/null +++ b/fpga/usrp3/lib/dsp/round_reg.v @@ -0,0 +1,32 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2008 Matt Ettus +// + +// + +// Rounding "macro" +// Keeps the topmost bits, does proper 2s comp rounding (round-to-zero) + +module round_reg + #(parameter bits_in=0, + parameter bits_out=0) + (input clk, + input [bits_in-1:0] in, + output reg [bits_out-1:0] out, + output reg [bits_in-bits_out:0] err); + + wire [bits_out-1:0] temp; + wire [bits_in-bits_out:0] err_temp; + + round #(.bits_in(bits_in),.bits_out(bits_out)) round (.in(in),.out(temp), .err(err_temp)); + + always @(posedge clk) + out <= temp; + + always @(posedge clk) + err <= err_temp; + +endmodule // round_reg diff --git a/fpga/usrp3/lib/dsp/round_sd.v b/fpga/usrp3/lib/dsp/round_sd.v new file mode 100644 index 000000000..94584f6ef --- /dev/null +++ b/fpga/usrp3/lib/dsp/round_sd.v @@ -0,0 +1,23 @@ + + +module round_sd + #(parameter WIDTH_IN=18, + parameter WIDTH_OUT=16, + parameter DISABLE_SD=0) + (input clk, input reset, + input [WIDTH_IN-1:0] in, input strobe_in, + output [WIDTH_OUT-1:0] out, output strobe_out); + + localparam ERR_WIDTH = WIDTH_IN - WIDTH_OUT + 1; + + wire [ERR_WIDTH-1:0] err; + wire [WIDTH_IN-1:0] err_ext, sum; + + sign_extend #(.bits_in(ERR_WIDTH),.bits_out(WIDTH_IN)) ext_err (.in(err), .out(err_ext)); + + add2_and_clip_reg #(.WIDTH(WIDTH_IN)) add2_and_clip_reg + (.clk(clk), .rst(reset), .in1(in), .in2((DISABLE_SD == 0) ? err_ext : 0), .strobe_in(strobe_in), .sum(sum), .strobe_out(strobe_out)); + + round #(.bits_in(WIDTH_IN),.bits_out(WIDTH_OUT)) round_sum (.in(sum), .out(out), .err(err)); + +endmodule // round_sd diff --git a/fpga/usrp3/lib/dsp/rx_dcoffset.v b/fpga/usrp3/lib/dsp/rx_dcoffset.v new file mode 100644 index 000000000..f74b0f1a0 --- /dev/null +++ b/fpga/usrp3/lib/dsp/rx_dcoffset.v @@ -0,0 +1,46 @@ +// +// Copyright 2011 Ettus Research LLC +// + + + + +module rx_dcoffset + #(parameter WIDTH=16, + parameter ADDR=8'd0, + parameter alpha_shift=20) + (input clk, input rst, + input set_stb, input [7:0] set_addr, input [31:0] set_data, + input [WIDTH-1:0] in, output [WIDTH-1:0] out); + + wire set_now = set_stb & (ADDR == set_addr); + + reg fixed; // uses fixed offset + wire [WIDTH-1:0] fixed_dco; + + localparam int_width = WIDTH + alpha_shift; + reg [int_width-1:0] integrator; + wire [WIDTH-1:0] quantized; + + always @(posedge clk) + if(rst) + begin + fixed <= 0; + integrator <= {int_width{1'b0}}; + end + else if(set_now) + begin + fixed <= set_data[31]; + if(set_data[30]) + integrator <= {set_data[29:0],{(int_width-30){1'b0}}}; + end + else if(~fixed) + integrator <= integrator + {{(alpha_shift){out[WIDTH-1]}},out}; + + round_sd #(.WIDTH_IN(int_width),.WIDTH_OUT(WIDTH)) round_sd + (.clk(clk), .reset(rst), .in(integrator), .strobe_in(1'b1), .out(quantized), .strobe_out()); + + add2_and_clip_reg #(.WIDTH(WIDTH)) add2_and_clip_reg + (.clk(clk), .rst(rst), .in1(in), .in2(-quantized), .strobe_in(1'b1), .sum(out), .strobe_out()); + +endmodule // rx_dcoffset diff --git a/fpga/usrp3/lib/dsp/rx_frontend.v b/fpga/usrp3/lib/dsp/rx_frontend.v new file mode 100644 index 000000000..ebe19240c --- /dev/null +++ b/fpga/usrp3/lib/dsp/rx_frontend.v @@ -0,0 +1,78 @@ + +module rx_frontend + #(parameter BASE = 0, + parameter IQCOMP_EN = 1) + (input clk, input rst, + input set_stb, input [7:0] set_addr, input [31:0] set_data, + + input [15:0] adc_a, input adc_ovf_a, + input [15:0] adc_b, input adc_ovf_b, + + output [23:0] i_out, output [23:0] q_out, + input run, + output [31:0] debug + ); + + reg [15:0] adc_i, adc_q; + wire [17:0] adc_i_ofs, adc_q_ofs; + wire [35:0] corr_i, corr_q; wire [17:0] mag_corr,phase_corr; + wire swap_iq; + + setting_reg #(.my_addr(BASE), .width(1)) sr_8 + (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), + .in(set_data),.out(swap_iq),.changed()); + + always @(posedge clk) + if(swap_iq) // Swap + {adc_i,adc_q} <= {adc_b,adc_a}; + else + {adc_i,adc_q} <= {adc_a,adc_b}; + + setting_reg #(.my_addr(BASE+1),.width(18)) sr_1 + (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), + .in(set_data),.out(mag_corr),.changed()); + + setting_reg #(.my_addr(BASE+2),.width(18)) sr_2 + (.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr), + .in(set_data),.out(phase_corr),.changed()); + + generate + if(IQCOMP_EN == 1) + begin + rx_dcoffset #(.WIDTH(18),.ADDR(BASE+3)) rx_dcoffset_i + (.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), + .in({adc_i,2'b00}),.out(adc_i_ofs)); + + rx_dcoffset #(.WIDTH(18),.ADDR(BASE+4)) rx_dcoffset_q + (.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), + .in({adc_q,2'b00}),.out(adc_q_ofs)); + + MULT18X18S mult_mag_corr + (.P(corr_i), .A(adc_i_ofs), .B(mag_corr), .C(clk), .CE(1), .R(rst) ); + + MULT18X18S mult_phase_corr + (.P(corr_q), .A(adc_i_ofs), .B(phase_corr), .C(clk), .CE(1), .R(rst) ); + + add2_and_clip_reg #(.WIDTH(24)) add_clip_i + (.clk(clk), .rst(rst), + .in1({adc_i_ofs,6'd0}), .in2(corr_i[35:12]), .strobe_in(1'b1), + .sum(i_out), .strobe_out()); + + add2_and_clip_reg #(.WIDTH(24)) add_clip_q + (.clk(clk), .rst(rst), + .in1({adc_q_ofs,6'd0}), .in2(corr_q[35:12]), .strobe_in(1'b1), + .sum(q_out), .strobe_out()); + end // if (IQCOMP_EN == 1) + else + begin + rx_dcoffset #(.WIDTH(24),.ADDR(BASE+3)) rx_dcoffset_i + (.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), + .in({adc_i,8'b00}),.out(i_out)); + + rx_dcoffset #(.WIDTH(24),.ADDR(BASE+4)) rx_dcoffset_q + (.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data), + .in({adc_q,8'b00}),.out(q_out)); + end // else: !if(IQCOMP_EN == 1) + endgenerate + +endmodule // rx_frontend diff --git a/fpga/usrp3/lib/dsp/rx_frontend_tb.v b/fpga/usrp3/lib/dsp/rx_frontend_tb.v new file mode 100644 index 000000000..487b72687 --- /dev/null +++ b/fpga/usrp3/lib/dsp/rx_frontend_tb.v @@ -0,0 +1,45 @@ + +`timescale 1ns/1ns +module rx_frontend_tb(); + + reg clk, rst; + + initial rst = 1; + initial #1000 rst = 0; + initial clk = 0; + always #5 clk = ~clk; + + initial $dumpfile("rx_frontend_tb.vcd"); + initial $dumpvars(0,rx_frontend_tb); + + reg [15:0] adc_in; + wire [17:0] adc_out; + + always @(posedge clk) + begin + if(adc_in[13]) + $write("-%d,",-adc_in); + else + $write("%d,",adc_in); + if(adc_out[13]) + $write("-%d\n",-adc_out); + else + $write("%d\n",adc_out); + end + + rx_frontend #(.BASE(0)) rx_frontend + (.clk(clk),.rst(rst), + .set_stb(0),.set_addr(0),.set_data(0), + .adc_a(adc_in), .adc_ovf_a(0), + .adc_b(0), .adc_ovf_b(0), + .i_out(adc_out),.q_out(), + .run(), .debug()); + + always @(posedge clk) + if(rst) + adc_in <= 0; + else + adc_in <= adc_in + 4; + //adc_in <= (($random % 473) + 23)/4; + +endmodule // rx_frontend_tb diff --git a/fpga/usrp3/lib/dsp/sign_extend.v b/fpga/usrp3/lib/dsp/sign_extend.v new file mode 100644 index 000000000..7c85920aa --- /dev/null +++ b/fpga/usrp3/lib/dsp/sign_extend.v @@ -0,0 +1,23 @@ +// -*- verilog -*- +// +// USRP - Universal Software Radio Peripheral +// +// Copyright (C) 2003 Matt Ettus +// + +// + + +// Sign extension "macro" +// bits_out should be greater than bits_in + +module sign_extend (in,out); + parameter bits_in=0; // FIXME Quartus insists on a default + parameter bits_out=0; + + input [bits_in-1:0] in; + output [bits_out-1:0] out; + + assign out = {{(bits_out-bits_in){in[bits_in-1]}},in}; + +endmodule diff --git a/fpga/usrp3/lib/dsp/small_hb_dec.v b/fpga/usrp3/lib/dsp/small_hb_dec.v new file mode 100644 index 000000000..fc776c2d7 --- /dev/null +++ b/fpga/usrp3/lib/dsp/small_hb_dec.v @@ -0,0 +1,124 @@ +// +// Copyright 2011 Ettus Research LLC +// + + +// Short halfband decimator (intended to be followed by another stage) +// Implements impulse responses of the form [A 0 B 0.5 B 0 A] +// +// These taps designed by halfgen4 from ldoolittle: +// 2 * 131072 * halfgen4(.75/8,2) +module small_hb_dec + #(parameter WIDTH=18) + (input clk, + input rst, + input bypass, + input run, + input stb_in, + input [WIDTH-1:0] data_in, + output reg stb_out, + output reg [WIDTH-1:0] data_out); + + // Round off inputs to 17 bits because of 18 bit multipliers + localparam INTWIDTH = 17; + wire [INTWIDTH-1:0] data_rnd; + wire stb_rnd; + + round_sd #(.WIDTH_IN(WIDTH),.WIDTH_OUT(INTWIDTH)) round_in + (.clk(clk),.reset(rst),.in(data_in),.strobe_in(stb_in),.out(data_rnd),.strobe_out(stb_rnd)); + + + reg stb_rnd_d1; + reg [INTWIDTH-1:0] data_rnd_d1; + always @(posedge clk) stb_rnd_d1 <= stb_rnd; + always @(posedge clk) data_rnd_d1 <= data_rnd; + + wire go; + reg phase, go_d1, go_d2, go_d3, go_d4; + always @(posedge clk) + if(rst | ~run) + phase <= 0; + else if(stb_rnd_d1) + phase <= ~phase; + assign go = stb_rnd_d1 & phase; + always @(posedge clk) + if(rst | ~run) + begin + go_d1 <= 0; + go_d2 <= 0; + go_d3 <= 0; + go_d4 <= 0; + end + else + begin + go_d1 <= go; + go_d2 <= go_d1; + go_d3 <= go_d2; + go_d4 <= go_d3; + end + + wire [17:0] coeff_a = -10690; + wire [17:0] coeff_b = 75809; + + reg [INTWIDTH-1:0] d1, d2, d3, d4 , d5, d6; + always @(posedge clk) + if(stb_rnd_d1 | rst) + begin + d1 <= data_rnd_d1; + d2 <= d1; + d3 <= d2; + d4 <= d3; + d5 <= d4; + d6 <= d5; + end + + reg [17:0] sum_a, sum_b, middle, middle_d1; + + always @(posedge clk) + if(go) + begin + sum_a <= {data_rnd_d1[INTWIDTH-1],data_rnd_d1} + {d6[INTWIDTH-1],d6}; + sum_b <= {d2[INTWIDTH-1],d2} + {d4[INTWIDTH-1],d4}; + //middle <= {d3[INTWIDTH-1],d3}; + middle <= {d3,1'b0}; + end + + always @(posedge clk) + if(go_d1) + middle_d1 <= middle; + + wire [17:0] sum = go_d1 ? sum_b : sum_a; + wire [17:0] coeff = go_d1 ? coeff_b : coeff_a; + wire [35:0] prod; + MULT18X18S mult(.C(clk), .CE(go_d1 | go_d2), .R(rst), .P(prod), .A(coeff), .B(sum) ); + + localparam ACCWIDTH = 30; + reg [ACCWIDTH-1:0] accum; + + always @(posedge clk) + if(rst) + accum <= 0; + else if(go_d2) + accum <= {middle_d1[17],middle_d1[17],middle_d1,{(16+ACCWIDTH-36){1'b0}}} + {prod[35:36-ACCWIDTH]}; + else if(go_d3) + accum <= accum + {prod[35:36-ACCWIDTH]}; + + wire [WIDTH:0] accum_rnd; + wire [WIDTH-1:0] accum_rnd_clip; + + wire stb_round; + + round_sd #(.WIDTH_IN(ACCWIDTH),.WIDTH_OUT(WIDTH+1)) round_acc + (.clk(clk), .reset(rst), .in(accum), .strobe_in(go_d4), .out(accum_rnd), .strobe_out(stb_round)); + + clip #(.bits_in(WIDTH+1),.bits_out(WIDTH)) clip (.in(accum_rnd), .out(accum_rnd_clip)); + + // Output + always @(posedge clk) + begin + stb_out <= bypass ? stb_in : stb_round; + data_out <= bypass ? data_in : accum_rnd_clip; + end + + +endmodule // small_hb_dec diff --git a/fpga/usrp3/lib/dsp/small_hb_int.v b/fpga/usrp3/lib/dsp/small_hb_int.v new file mode 100644 index 000000000..4b03b5d0c --- /dev/null +++ b/fpga/usrp3/lib/dsp/small_hb_int.v @@ -0,0 +1,99 @@ +// +// Copyright 2011 Ettus Research LLC +// + + +// Short halfband decimator (intended to be followed by another stage) +// Implements impulse responses of the form [A 0 B 0.5 B 0 A] +// +// These taps designed by halfgen4 from ldoolittle: +// 2 * 131072 * halfgen4(.75/8,2) + +module small_hb_int + #(parameter WIDTH=18) + (input clk, + input rst, + input bypass, + input stb_in, + input [WIDTH-1:0] data_in, + input [7:0] output_rate, + input stb_out, + output reg [WIDTH-1:0] data_out); + + + reg [WIDTH-1:0] d1, d2, d3, d4, d5, d6; + + localparam MWIDTH = 36; + wire [MWIDTH-1:0] prod; + + reg [6:0] stbin_d; + + always @(posedge clk) + stbin_d <= {stbin_d[5:0],stb_in}; + + always @(posedge clk) + if (rst) + begin + d1 <= 0; + d2 <= 0; + d3 <= 0; + d4 <= 0; + d5 <= 0; + d6 <= 0; + end + else if(stb_in) + begin + d1 <= data_in; + d2 <= d1; + d3 <= d2; + d4 <= d3; + d5 <= d4; + d6 <= d5; + end + + wire [WIDTH-1:0] sum_outer, sum_inner; + add2_and_round_reg #(.WIDTH(WIDTH)) add_outer (.clk(clk),.in1(d1),.in2(d4),.sum(sum_outer)); + add2_and_round_reg #(.WIDTH(WIDTH)) add_inner (.clk(clk),.in1(d2),.in2(d3),.sum(sum_inner)); + + wire [17:0] coeff_outer = -10690; + wire [17:0] coeff_inner = 75809; + + MULT18X18S mult(.C(clk), .CE(1), .R(rst), .P(prod), .A(stbin_d[1] ? coeff_outer : coeff_inner), + .B(stbin_d[1] ? sum_outer : sum_inner) ); + + wire [MWIDTH:0] accum; + acc #(.IWIDTH(MWIDTH),.OWIDTH(MWIDTH+1)) + acc (.clk(clk),.clear(stbin_d[2]),.acc(|stbin_d[3:2]),.in(prod),.out(accum)); + + wire [WIDTH+2:0] accum_rnd; + round_reg #(.bits_in(MWIDTH+1),.bits_out(WIDTH+3)) + final_round (.clk(clk),.in(accum),.out(accum_rnd)); + + wire [WIDTH-1:0] clipped; + clip_reg #(.bits_in(WIDTH+3),.bits_out(WIDTH)) final_clip + (.clk(clk),.in(accum_rnd),.strobe_in(1'b1), .out(clipped)); + + reg [WIDTH-1:0] saved, saved_d3; + always @(posedge clk) + if(stbin_d[6]) + saved <= clipped; + + always @(posedge clk) + if(stbin_d[3]) + saved_d3 <= d3; + + always @(posedge clk) + if(bypass) + data_out <= data_in; + else if(stb_in & stb_out) + case(output_rate) + 1 : data_out <= d6; + 2 : data_out <= d4; + 3, 4, 5, 6, 7 : data_out <= d3; + default : data_out <= d2; + endcase // case(output_rate) + else if(stb_out) + data_out <= saved; + +endmodule // small_hb_int + diff --git a/fpga/usrp3/lib/dsp/srl.v b/fpga/usrp3/lib/dsp/srl.v new file mode 100644 index 000000000..bbd8ac1c9 --- /dev/null +++ b/fpga/usrp3/lib/dsp/srl.v @@ -0,0 +1,27 @@ +// +// Copyright 2011 Ettus Research LLC +// + + + +module srl + #(parameter WIDTH=18) + (input clk, + input rst, + input write, + input [WIDTH-1:0] in, + input [3:0] addr, + output [WIDTH-1:0] out); + + genvar i; + generate + for (i=0;i