mercury receiver implementation in verilog kirk weedman kd7irs

22
Mercury Receiver Mercury Receiver Implementation in Verilog Implementation in Verilog Kirk Weedman Kirk Weedman KD7IRS KD7IRS

Upload: lenard-nelson

Post on 17-Dec-2015

301 views

Category:

Documents


4 download

TRANSCRIPT

Mercury ReceiverMercury Receiver

Implementation in VerilogImplementation in Verilog

Kirk WeedmanKirk Weedman

KD7IRSKD7IRS

StagesStages

VARCIC CIC

FIR

I

Q

CORDIC

VARCIC CIC

FIR

Stages: 5Decimation: 80/160/320

Stages: 11Decimation: 4 Decimation

: 2

22

22

23

23

24

24

ADC Data

Frequency

32

rate 2

Out_strobe

Out_strobe

Out_strobe

Out_strobe

In_strobe

In_strobe

In_strobe

In_strobe

1

1

In_strobe

In_strobe

clock

I

Q

122.88 MHz

24

24

receiver.vreceiver.v

//------------------------------------------------------------------------------//------------------------------------------------------------------------------

// Copyright (c) 2008 Alex Shovkoplyas, VE3NEA// Copyright (c) 2008 Alex Shovkoplyas, VE3NEA

//------------------------------------------------------------------------------//------------------------------------------------------------------------------

module receiver(module receiver(

input clock, //122.88 MHzinput clock, //122.88 MHz

input [1:0] rate, //00=48, 01=96, 10=192 kHzinput [1:0] rate, //00=48, 01=96, 10=192 kHz

input [31:0] frequency,input [31:0] frequency,

output out_strobe,output out_strobe,

input signed [15:0] in_data,input signed [15:0] in_data,

output [23:0] out_data_I,output [23:0] out_data_I,

output [23:0] out_data_Qoutput [23:0] out_data_Q

););

wire signed [21:0] cordic_outdata_I;wire signed [21:0] cordic_outdata_I;

wire signed [21:0] cordic_outdata_Q;wire signed [21:0] cordic_outdata_Q;

//------------------------------------------------------------------------------//------------------------------------------------------------------------------

// cordic// cordic

//------------------------------------------------------------------------------//------------------------------------------------------------------------------

cordic cordic_inst(cordic cordic_inst(

.clock(clock),.clock(clock),

.in_data(in_data), //16 bit .in_data(in_data), //16 bit

.frequency(frequency), //32 bit.frequency(frequency), //32 bit

.out_data_I(cordic_outdata_I), //22 bit.out_data_I(cordic_outdata_I), //22 bit

.out_data_Q(cordic_outdata_Q).out_data_Q(cordic_outdata_Q)

););

receiver.vreceiver.v

//------------------------------------------------------------------------------//------------------------------------------------------------------------------

// CIC decimator #1, decimation factor 80/160/320// CIC decimator #1, decimation factor 80/160/320

//------------------------------------------------------------------------------//------------------------------------------------------------------------------

//I channel//I channel

wire cic_outstrobe_1;wire cic_outstrobe_1;

wire signed [22:0] cic_outdata_I1;wire signed [22:0] cic_outdata_I1;

wire signed [22:0] cic_outdata_Q1;wire signed [22:0] cic_outdata_Q1;

varcic #(.STAGES(5), .DECIMATION(80), .IN_WIDTH(22), .ACC_WIDTH(64), .OUT_WIDTH(23))varcic #(.STAGES(5), .DECIMATION(80), .IN_WIDTH(22), .ACC_WIDTH(64), .OUT_WIDTH(23))

varcic_inst_I1(varcic_inst_I1(

.clock(clock),.clock(clock),

.in_strobe(1'b1),.in_strobe(1'b1),

.extra_decimation(rate),.extra_decimation(rate),

.out_strobe(cic_outstrobe_1),.out_strobe(cic_outstrobe_1),

.in_data(cordic_outdata_I),.in_data(cordic_outdata_I),

.out_data(cic_outdata_I1).out_data(cic_outdata_I1)

););

//Q channel//Q channel

varcic #(.STAGES(5), .DECIMATION(80), .IN_WIDTH(22), .ACC_WIDTH(64), .OUT_WIDTH(23))varcic #(.STAGES(5), .DECIMATION(80), .IN_WIDTH(22), .ACC_WIDTH(64), .OUT_WIDTH(23))

varcic_inst_Q1(varcic_inst_Q1(

.clock(clock),.clock(clock),

.in_strobe(1'b1),.in_strobe(1'b1),

.extra_decimation(rate),.extra_decimation(rate),

.out_strobe(),.out_strobe(),

.in_data(cordic_outdata_Q),.in_data(cordic_outdata_Q),

.out_data(cic_outdata_Q1).out_data(cic_outdata_Q1)

););

receiver.vreceiver.v

//------------------------------------------------------------------------------//------------------------------------------------------------------------------

// CIC decimator #2, decimation factor 4// CIC decimator #2, decimation factor 4

//------------------------------------------------------------------------------//------------------------------------------------------------------------------

//I channel//I channel

wire cic_outstrobe_2;wire cic_outstrobe_2;

wire signed [23:0] cic_outdata_I2;wire signed [23:0] cic_outdata_I2;

wire signed [23:0] cic_outdata_Q2;wire signed [23:0] cic_outdata_Q2;

cic #(.STAGES(11), .DECIMATION(4), .IN_WIDTH(23), .ACC_WIDTH(45), .OUT_WIDTH(24))cic #(.STAGES(11), .DECIMATION(4), .IN_WIDTH(23), .ACC_WIDTH(45), .OUT_WIDTH(24))

cic_inst_I2(cic_inst_I2(

.clock(clock),.clock(clock),

.in_strobe(cic_outstrobe_1),.in_strobe(cic_outstrobe_1),

.out_strobe(cic_outstrobe_2),.out_strobe(cic_outstrobe_2),

.in_data(cic_outdata_I1),.in_data(cic_outdata_I1),

.out_data(cic_outdata_I2).out_data(cic_outdata_I2)

););

//Q channel//Q channel

cic #(.STAGES(11), .DECIMATION(4), .IN_WIDTH(23), .ACC_WIDTH(45), .OUT_WIDTH(24))cic #(.STAGES(11), .DECIMATION(4), .IN_WIDTH(23), .ACC_WIDTH(45), .OUT_WIDTH(24))

cic_inst_Q2(cic_inst_Q2(

.clock(clock),.clock(clock),

.in_strobe(cic_outstrobe_1),.in_strobe(cic_outstrobe_1),

.out_strobe(),.out_strobe(),

.in_data(cic_outdata_Q1),.in_data(cic_outdata_Q1),

.out_data(cic_outdata_Q2).out_data(cic_outdata_Q2)

););

receiver.vreceiver.v

//------------------------------------------------------------------------------//------------------------------------------------------------------------------

// FIR coefficients and sequencing// FIR coefficients and sequencing

//------------------------------------------------------------------------------//------------------------------------------------------------------------------

wire signed [23:0] fir_coeff;wire signed [23:0] fir_coeff;

fir_coeffs fir_coeffs_inst(fir_coeffs fir_coeffs_inst(

.clock(clock),.clock(clock),

.start(cic_outstrobe_2),.start(cic_outstrobe_2),

.coeff(fir_coeff).coeff(fir_coeff)

););

//------------------------------------------------------------------------------//------------------------------------------------------------------------------

// FIR decimator// FIR decimator

//------------------------------------------------------------------------------//------------------------------------------------------------------------------

fir #(.OUT_WIDTH(24))fir #(.OUT_WIDTH(24))

fir_inst_I(fir_inst_I(

.clock(clock),.clock(clock),

.start(cic_outstrobe_2), .start(cic_outstrobe_2),

.coeff(fir_coeff),.coeff(fir_coeff),

.in_data(cic_outdata_I2),.in_data(cic_outdata_I2),

.out_data(out_data_I),.out_data(out_data_I),

.out_strobe(out_strobe).out_strobe(out_strobe)

););

fir #(.OUT_WIDTH(24))fir #(.OUT_WIDTH(24))

fir_inst_Q(fir_inst_Q(

.clock(clock),.clock(clock),

.start(cic_outstrobe_2),.start(cic_outstrobe_2),

.coeff(fir_coeff),.coeff(fir_coeff),

.in_data(cic_outdata_Q2),.in_data(cic_outdata_Q2),

.out_data(out_data_Q),.out_data(out_data_Q),

.out_strobe().out_strobe()

););

endmoduleendmodule

StagesStages

VARCIC CIC

FIR

I

Q

CORDIC

VARCIC CIC

FIR

Stages: 5Decimation: 80/160/320

Stages: 11Decimation: 4 Decimation

: 2

22

22

23

23

24

24

ADC Data

Frequency

32

rate 2

Out_strobe

Out_strobe

Out_strobe

Out_strobe

In_strobe

In_strobe

In_strobe

In_strobe

1

1

In_strobe

In_strobe

clock

I

Q

122.88 MHz

24

24

A CIC decimator has N cascaded A CIC decimator has N cascaded integrator stages clocked at fs, followed integrator stages clocked at fs, followed by a rate change factor of R, followed by by a rate change factor of R, followed by N cascaded comb stages running at fs/RN cascaded comb stages running at fs/R

CIC FiltersCIC Filters

Three Stage Decimating CIC Filter (N = 3)

I R C CCII

CIC FiltersCIC Filters

For CIC decimators, the gain G at the output of the final comb section is:

Gain = (RM)

R = decimation rateM = design parameter and is called the differential delay. M can be any positive integer, but it is usually limited to 1 or 2N = Number of Integrator /Comb stages

Assuming two's complement arithmetic, we can use this result to calculate the numberof bits required for the last comb due to bit growth. If Bin is the number of input bits, then the number of output bits, Bout, is

Bout = N log (RM) + Bin

It also turn out that Bout bits are needed for each integrator and comb stage. The inputneeds to be sign extended to Bout bits, but LSB's can either be truncated or rounded atlater stages.

N

2

Bit GainBit Gain

CIC FiltersCIC Filters

For CIC decimators, the gain G at the output of the final comb section is:

Gain = (RM)

For the Mercury receiver:

R = decimation rate = 320 (when running at 48Khz) for varcic.v and 4 for cic.vM = 1N = 5 stages for varcic.v and 11 for cic.v

Bout = N log (RM) + Bin

Bout1 = ceil(5 * 8.3219) + 22 = 42 + 22 = 64.Bout2 = ceil(11 * 2) + 23 = 22 + 23 = 45.

See ACC_WIDTH in receiver.v instantiations of varcic.v and cic.v

N

2

Bit GainBit Gain

For a CIC decimator, the normalized gain at the output of the last comb is given by

G =

G always lies in the interval (1/2 : 1]. Note that when R is a power of two, the gain is unity. This gain can be used to calculate a scale factor, S, to apply to the final shifted output.

S =

S always lies in the interval [1; 2). By doing this, the CIC decimation filter can have unity DC gain.

CIC FiltersCIC FiltersFilter Filter GainGain

R M

N.

R M

N.

N log (RM)

22. .

N log (RM)

22. .

For Mercury, the first VARCIC has N = 5 stages, M = 1, and R = 80/160/320

G = = = .762939….

G always lies in the interval (1/2 : 1]. Note that when R is a power of two, the gain is unity. This gain can be used to calculate a scale factor, S, to apply to the final shifted output.

S = = 1.31…

S always lies in the interval [1; 2). By scaling this amount, the CIC decimation filter can have unity DC gain.

CIC FiltersCIC Filters

25 log 3202320

5

242

Filter Filter GainGain

320

5

25 log 3202

320

5

module varcic( extra_decimation, clock, in_strobe, out_strobe, in_data, out_data );module varcic( extra_decimation, clock, in_strobe, out_strobe, in_data, out_data );

//design parameters//design parameters

parameter STAGES = 5;parameter STAGES = 5;

parameter DECIMATION = 320; parameter DECIMATION = 320;

parameter IN_WIDTH = 22;parameter IN_WIDTH = 22;

//computed parameters//computed parameters

//ACC_WIDTH = IN_WIDTH + Ceil(STAGES * Log2(decimation factor))//ACC_WIDTH = IN_WIDTH + Ceil(STAGES * Log2(decimation factor))

//OUT_WIDTH = IN_WIDTH + Ceil(Log2(decimation factor) / 2)//OUT_WIDTH = IN_WIDTH + Ceil(Log2(decimation factor) / 2)

parameter ACC_WIDTH = 64;parameter ACC_WIDTH = 64;

parameter OUT_WIDTH = 27;parameter OUT_WIDTH = 27;

//00 = DECIMATION*4, 01 = DECIMATION*2, 10 = DECIMATION//00 = DECIMATION*4, 01 = DECIMATION*2, 10 = DECIMATION

input [1:0] extra_decimation;input [1:0] extra_decimation;

input clock;input clock;

input in_strobe;input in_strobe;

output reg out_strobe;output reg out_strobe;

input signed [IN_WIDTH-1:0] in_data;input signed [IN_WIDTH-1:0] in_data;

output reg signed [OUT_WIDTH-1:0] out_data;output reg signed [OUT_WIDTH-1:0] out_data;

varcic.vvarcic.v

//------------------------------------------------------------------------------//------------------------------------------------------------------------------

// control// control

//------------------------------------------------------------------------------//------------------------------------------------------------------------------

reg [15:0] sample_no;reg [15:0] sample_no;

initial sample_no = 16'd0;initial sample_no = 16'd0;

always @(posedge clock)always @(posedge clock)

if (in_strobe)if (in_strobe)

beginbegin

if (sample_no == ((DECIMATION << (2-extra_decimation))-1))if (sample_no == ((DECIMATION << (2-extra_decimation))-1))

beginbegin

sample_no <= 0;sample_no <= 0;

out_strobe <= 1;out_strobe <= 1;

endend

elseelse

beginbegin

sample_no <= sample_no + 8'd1;sample_no <= sample_no + 8'd1;

out_strobe <= 0;out_strobe <= 0;

endend

endend

elseelse

out_strobe <= 0;out_strobe <= 0;

varcic.vvarcic.v

DECIMATION = 80extra_decimation sample_no2’b00 320-12’b01 160-12’b10 80-1

//------------------------------------------------------------------------------//------------------------------------------------------------------------------

// stages// stages

//------------------------------------------------------------------------------//------------------------------------------------------------------------------

wire signed [ACC_WIDTH-1:0] integrator_data [0:STAGES];wire signed [ACC_WIDTH-1:0] integrator_data [0:STAGES];

wire signed [ACC_WIDTH-1:0] comb_data [0:STAGES];wire signed [ACC_WIDTH-1:0] comb_data [0:STAGES];

assign integrator_data[0] = in_data;assign integrator_data[0] = in_data;

assign comb_data[0] = integrator_data[STAGES];assign comb_data[0] = integrator_data[STAGES];

genvar i;genvar i;

generategenerate

for (i=0; i<STAGES; i=i+1)for (i=0; i<STAGES; i=i+1)

begin : cic_stagesbegin : cic_stages

cic_integrator #(ACC_WIDTH) cic_integrator_inst(cic_integrator #(ACC_WIDTH) cic_integrator_inst(

.clock(clock),.clock(clock),

.strobe(in_strobe),.strobe(in_strobe),

.in_data(integrator_data[i]),.in_data(integrator_data[i]),

.out_data(integrator_data[i+1]).out_data(integrator_data[i+1])

););

cic_comb #(ACC_WIDTH) cic_comb_inst(cic_comb #(ACC_WIDTH) cic_comb_inst(

.clock(clock),.clock(clock),

.strobe(out_strobe),.strobe(out_strobe),

.in_data(comb_data[i]),.in_data(comb_data[i]),

.out_data(comb_data[i+1]).out_data(comb_data[i+1])

););

endend

endgenerateendgenerate

varcic.vvarcic.v

I R C CCIIII C CStages = 5

//------------------------------------------------------------------------------//------------------------------------------------------------------------------

// output rounding// output rounding

//------------------------------------------------------------------------------//------------------------------------------------------------------------------

localparam MSB0 = ACC_WIDTH - 1; //63localparam MSB0 = ACC_WIDTH - 1; //63

localparam LSB0 = ACC_WIDTH - OUT_WIDTH; //41localparam LSB0 = ACC_WIDTH - OUT_WIDTH; //41

localparam MSB1 = MSB0 - STAGES; //58localparam MSB1 = MSB0 - STAGES; //58

localparam LSB1 = LSB0 - STAGES; //36localparam LSB1 = LSB0 - STAGES; //36

localparam MSB2 = MSB1 - STAGES; //53localparam MSB2 = MSB1 - STAGES; //53

localparam LSB2 = LSB1 - STAGES; //31localparam LSB2 = LSB1 - STAGES; //31

always @(posedge clock)always @(posedge clock)

case (extra_decimation)case (extra_decimation)

0: out_data <= comb_data[STAGES][MSB0:LSB0] + comb_data[STAGES][LSB0-1];0: out_data <= comb_data[STAGES][MSB0:LSB0] + comb_data[STAGES][LSB0-1];

1: out_data <= comb_data[STAGES][MSB1:LSB1] + comb_data[STAGES][LSB1-1];1: out_data <= comb_data[STAGES][MSB1:LSB1] + comb_data[STAGES][LSB1-1];

2: out_data <= comb_data[STAGES][MSB2:LSB2] + comb_data[STAGES][LSB2-1];2: out_data <= comb_data[STAGES][MSB2:LSB2] + comb_data[STAGES][LSB2-1];

endcaseendcase

endmoduleendmodule varcic.vvarcic.v

@ 48KhzR = 320Bout = 22 + ceil(5 log2(320))Bout = 22 + 42 = 64OUT_WIDTH = 23

@ 96KhzR = 160,Bout = 22 + ceil(5 log2(160))Bout = 22 + 37 = 59

@ 192KhzR = 80Bout = 22 + ceil(5 log2(80))Bout = 22 + 32 = 54

module cic_comb( clock, strobe, in_data, out_data );module cic_comb( clock, strobe, in_data, out_data );

parameter WIDTH = 64;parameter WIDTH = 64;

input clock;input clock;

input strobe;input strobe;

input signed [WIDTH-1:0] in_data;input signed [WIDTH-1:0] in_data;

output reg signed [WIDTH-1:0] out_data;output reg signed [WIDTH-1:0] out_data;

reg signed [WIDTH-1:0] prev_data;reg signed [WIDTH-1:0] prev_data;

initial prev_data = 0;initial prev_data = 0;

always @(posedge clock) always @(posedge clock)

if (strobe) if (strobe)

beginbegin

out_data <= in_data - prev_data;out_data <= in_data - prev_data;

prev_data <= in_data;prev_data <= in_data;

endend

endmoduleendmodule

cic_comb.cic_comb.vv

Σ

D-

+

Comb Stage

X[n]

X[n-1]

y[n] = x[n]-x[n-1]

in_data prev_data

out_data+-

clock

EN

EN

strobeWIDTH

WIDTH

WIDTH

WIDTH

module cic_integrator( clock, strobe, in_data, out_data );module cic_integrator( clock, strobe, in_data, out_data );

parameter WIDTH = 64;parameter WIDTH = 64;

input clock;input clock;

input strobe;input strobe;

input signed [WIDTH-1:0] in_data;input signed [WIDTH-1:0] in_data;

output reg signed [WIDTH-1:0] out_data;output reg signed [WIDTH-1:0] out_data;

initial out_data = 0;initial out_data = 0;

always @(posedge clock)always @(posedge clock)

if (strobe) out_data <= out_data + in_data;if (strobe) out_data <= out_data + in_data;

endmoduleendmodule

cic_integratocic_integrator.vr.v

in_dataout_data+

clock

EN

strobe

WIDTH WIDTH

WIDTH

+

WIDTH

Integration Stage

Σ

D

X[n]

y[n-1]

y[n] = y[n-1] + x[n]

A FIR filter is described by the functionA FIR filter is described by the function

y(n) = x(n-i) h(i)y(n) = x(n-i) h(i)

Or a transfer functionOr a transfer function

Where N = filter OrderWhere N = filter Order

FIR FiltersFIR Filters

i= 0

N-1

N0 1 2

-1 -2 -NH(z) = a + a z + a z + …. a z

Low Pass

y(n) = x(n-i) h(i)y(n) = x(n-i) h(i)

FIR FiltersFIR Filters

i = 0

N-1

Example: N = 8

x(n) x(n-7)

XXXXXXXX

+y(n)

Filter coefficients

h(0) h(1) h(7)h(3)h(2) h(4) h(6)h(5)

FIR FiltersFIR Filters

N0 1 2

-1 -2 -NH(z) = a + a z + a z + …. a z

Do how do we calculate the coefficients?For a FIR low pass filter they could be calculated as follows:

a =

i

w = 2 w(i

).

Where w(i) is a window function.Two well known window functions are the Hamming and BlackmanHamming

:

Blackman:

w(i) = .42 - .5cos

w(i) = .54 - .46cos ). .2 nN(

+ .08cos

. )( .4 nN

Low Pass

sin(n w )

c. c(n w ).

c.

= cutoff frequencyi: 0, 1, ….

N n = i – N/2

cFcF.

). .2 nN(

FIR FiltersFIR Filters

N0 1 2

-1 -2 -NH(z) = a + a z + a z + …. a z

Do how do we calculate the coefficients?For a FIR low pass filter they could be calculated as follows:

a =

i

w = 2 w(i

).

Where w(i) is a window function.Two well known window functions are the Hamming and BlackmanHamming

:

Blackman:

w(i) = .42 - .5cos

w(i) = .54 - .46cos ). .2 nN(

+ .08cos

. )( .4 nN

Low Pass

sin(n w )

c. c(n w ).

c.

= cutoff frequencyi: 0, 1, …. N

n = i – N/2

cFcF.

). .2 nN(

5th order N = 4

i: 0, 1, 2, 3, 4n: -2, -1, 0, 1, 2

Notice symmetry: w(0) and w(4) values are identical