axi_adc_decimate: Add correction at the end of the decimation chain

The CIC filter introduces different amplifications depending on the
decimation ratio. By adding a multiplier in the decimation chain
the amplification can be compensated
main
Adrian Costina 2017-08-04 14:28:37 +03:00
parent cf25aeacf5
commit 4d6c45eb83
4 changed files with 117 additions and 27 deletions

View File

@ -35,7 +35,9 @@
`timescale 1ns/100ps
module axi_adc_decimate(
module axi_adc_decimate #(
parameter CORRECTION_DISABLE = 1) (
input adc_clk,
input adc_rst,
@ -89,18 +91,28 @@ module axi_adc_decimate(
wire [31:0] decimation_ratio;
wire [ 2:0] filter_mask;
wire adc_correction_enable_a;
wire adc_correction_enable_b;
wire [15:0] adc_correction_coefficient_a;
wire [15:0] adc_correction_coefficient_b;
// signal name changes
assign up_clk = s_axi_aclk;
assign up_rstn = s_axi_aresetn;
axi_adc_decimate_filter axi_adc_decimate_filter (
axi_adc_decimate_filter #(
.CORRECTION_DISABLE(CORRECTION_DISABLE)
) axi_adc_decimate_filter (
.adc_clk (adc_clk),
.adc_rst (adc_rst),
.decimation_ratio (decimation_ratio),
.filter_mask (filter_mask),
.adc_correction_enable_a(adc_correction_enable_a),
.adc_correction_enable_b(adc_correction_enable_b),
.adc_correction_coefficient_a(adc_correction_coefficient_a),
.adc_correction_coefficient_b(adc_correction_coefficient_b),
.adc_valid_a(adc_valid_a),
.adc_valid_b(adc_valid_b),
@ -119,6 +131,11 @@ module axi_adc_decimate(
.adc_decimation_ratio (decimation_ratio),
.adc_filter_mask (filter_mask),
.adc_correction_enable_a(adc_correction_enable_a),
.adc_correction_enable_b(adc_correction_enable_b),
.adc_correction_coefficient_a(adc_correction_coefficient_a),
.adc_correction_coefficient_b(adc_correction_coefficient_b),
.up_rstn (up_rstn),
.up_clk (up_clk),
.up_wreq (up_wreq),

View File

@ -36,22 +36,30 @@
`timescale 1ns/100ps
module axi_adc_decimate_filter (
module axi_adc_decimate_filter #(
parameter CORRECTION_DISABLE = 1) (
input adc_clk,
input adc_rst,
input [31:0] decimation_ratio,
input [ 2:0] filter_mask,
input adc_correction_enable_a,
input adc_correction_enable_b,
input [15:0] adc_correction_coefficient_a,
input [15:0] adc_correction_coefficient_b,
input adc_valid_a,
input adc_valid_b,
input [11:0] adc_data_a,
input [11:0] adc_data_b,
output reg [15:0] adc_dec_data_a,
output reg [15:0] adc_dec_data_b,
output reg adc_dec_valid_a,
output reg adc_dec_valid_b
output [15:0] adc_dec_data_a,
output [15:0] adc_dec_data_b,
output adc_dec_valid_a,
output adc_dec_valid_b
);
// internal signals
@ -63,6 +71,11 @@ module axi_adc_decimate_filter (
reg [4:0] filter_enable = 5'h00;
reg [15:0] adc_dec_data_a_r;
reg [15:0] adc_dec_data_b_r;
reg adc_dec_valid_a_r;
reg adc_dec_valid_b_r;
wire [25:0] adc_fir_data_a;
wire adc_fir_valid_a;
wire [25:0] adc_fir_data_b;
@ -109,6 +122,34 @@ module axi_adc_decimate_filter (
.filter_out(adc_fir_data_b),
.ce_out(adc_fir_valid_b));
ad_iqcor #(.Q_OR_I_N (0),
.DISABLE(CORRECTION_DISABLE),
.SCALE_ONLY(1)
) i_scale_correction_a (
.clk (adc_clk),
.valid (adc_dec_valid_a_r),
.data_in (adc_dec_data_a_r),
.data_iq (16'h0),
.valid_out (adc_dec_valid_a),
.data_out (adc_dec_data_a),
.iqcor_enable (adc_correction_enable_a),
.iqcor_coeff_1 (adc_correction_coefficient_a),
.iqcor_coeff_2 (16'h0));
ad_iqcor #(.Q_OR_I_N (0),
.DISABLE(CORRECTION_DISABLE),
.SCALE_ONLY(1)
) i_scale_correction_b (
.clk (adc_clk),
.valid (adc_dec_valid_b_r),
.data_in (adc_dec_data_b_r),
.data_iq (16'h0),
.valid_out (adc_dec_valid_b),
.data_out (adc_dec_data_b),
.iqcor_enable (adc_correction_enable_b),
.iqcor_coeff_1 (adc_correction_coefficient_b),
.iqcor_coeff_2 (16'h0));
always @(posedge adc_clk) begin
case (filter_mask)
3'h1: filter_enable <= 5'b00001;
@ -122,8 +163,8 @@ module axi_adc_decimate_filter (
always @(*) begin
case (filter_enable[0])
1'b0: adc_dec_data_a = {{4{adc_data_a[11]}},adc_data_a};
default: adc_dec_data_a = {adc_fir_data_a[25], adc_fir_data_a[25:11]};
1'b0: adc_dec_data_a_r = {{4{adc_data_a[11]}},adc_data_a};
default: adc_dec_data_a_r = {adc_fir_data_a[25], adc_fir_data_a[25:11]};
endcase
case (filter_enable[0])
@ -132,8 +173,8 @@ module axi_adc_decimate_filter (
endcase
case (filter_enable[0])
1'b0: adc_dec_data_b = {{4{adc_data_b[11]}},adc_data_b};
default adc_dec_data_b = {adc_fir_data_b[25], adc_fir_data_b[25:11]};
1'b0: adc_dec_data_b_r = {{4{adc_data_b[11]}},adc_data_b};
default adc_dec_data_b_r = {adc_fir_data_b[25], adc_fir_data_b[25:11]};
endcase
case (filter_enable[0])
@ -145,25 +186,24 @@ module axi_adc_decimate_filter (
always @(posedge adc_clk) begin
if (adc_rst == 1'b1) begin
decimation_counter <= 32'b0;
adc_dec_valid_a <= 1'b0;
adc_dec_valid_b <= 1'b0;
adc_dec_valid_a_r <= 1'b0;
adc_dec_valid_b_r <= 1'b0;
end else begin
if (adc_dec_valid_a_filter == 1'b1) begin
if (decimation_counter < decimation_ratio) begin
decimation_counter <= decimation_counter + 1;
adc_dec_valid_a <= 1'b0;
adc_dec_valid_b <= 1'b0;
adc_dec_valid_a_r <= 1'b0;
adc_dec_valid_b_r <= 1'b0;
end else begin
decimation_counter <= 0;
adc_dec_valid_a <= 1'b1;
adc_dec_valid_b <= 1'b1;
adc_dec_valid_a_r <= 1'b1;
adc_dec_valid_b_r <= 1'b1;
end
end else begin
adc_dec_valid_a <= 1'b0;
adc_dec_valid_b <= 1'b0;
adc_dec_valid_a_r <= 1'b0;
adc_dec_valid_b_r <= 1'b0;
end
end
end
endmodule

View File

@ -7,6 +7,7 @@ adi_ip_create axi_adc_decimate
adi_ip_files axi_adc_decimate [list \
"$ad_hdl_dir/library/common/up_xfer_cntrl.v" \
"$ad_hdl_dir/library/common/up_axi.v" \
"$ad_hdl_dir/library/common/ad_iqcor.v" \
"axi_adc_decimate_constr.xdc" \
"fir_decim.v" \
"cic_decim.v" \

View File

@ -42,6 +42,11 @@ module axi_adc_decimate_reg(
output [31:0] adc_decimation_ratio,
output [ 2:0] adc_filter_mask,
output adc_correction_enable_a,
output adc_correction_enable_b,
output [15:0] adc_correction_coefficient_a,
output [15:0] adc_correction_coefficient_b,
// bus interface
input up_rstn,
@ -63,12 +68,19 @@ module axi_adc_decimate_reg(
reg [31:0] up_decimation_ratio = 32'h0;
reg [ 2:0] up_filter_mask = 32'h0;
reg [ 1:0] up_config = 1'h0;
reg [15:0] up_correction_coefficient_a = 16'h0;
reg [15:0] up_correction_coefficient_b = 16'h0;
always @(negedge up_rstn or posedge up_clk) begin
if (up_rstn == 0) begin
up_wack <= 'd0;
up_scratch <= 'd0;
up_decimation_ratio <= 'd0;
up_filter_mask <= 'd0;
up_config <= 'd0;
up_correction_coefficient_a <= 'd0;
up_correction_coefficient_b <= 'd0;
end else begin
up_wack <= up_wreq;
if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'h1)) begin
@ -80,6 +92,15 @@ module axi_adc_decimate_reg(
if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'h11)) begin
up_filter_mask <= up_wdata[2:0];
end
if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'h12)) begin
up_config <= up_wdata[1:0];
end
if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'h13)) begin
up_correction_coefficient_a <= up_wdata[15:0];
end
if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'h14)) begin
up_correction_coefficient_b <= up_wdata[15:0];
end
end
end
@ -96,7 +117,10 @@ module axi_adc_decimate_reg(
5'h0: up_rdata <= up_version;
5'h1: up_rdata <= up_scratch;
5'h10: up_rdata <= up_decimation_ratio;
5'h11: up_rdata <= up_filter_mask;
5'h11: up_rdata <= { 29'h0, up_filter_mask };
5'h12: up_rdata <= { 30'h0, up_config };
5'h13: up_rdata <= { 16'h0, up_correction_coefficient_a };
5'h14: up_rdata <= { 16'h0, up_correction_coefficient_b };
default: up_rdata <= 0;
endcase
end else begin
@ -105,16 +129,24 @@ module axi_adc_decimate_reg(
end
end
up_xfer_cntrl #(.DATA_WIDTH(35)) i_xfer_cntrl (
up_xfer_cntrl #(.DATA_WIDTH(69)) i_xfer_cntrl (
.up_rstn (up_rstn),
.up_clk (up_clk),
.up_data_cntrl ({ up_decimation_ratio, // 32
.up_data_cntrl ({ up_config[1], // 1
up_config[0], // 1
up_correction_coefficient_b, // 16
up_correction_coefficient_a, // 16
up_decimation_ratio, // 32
up_filter_mask}), // 3
.up_xfer_done (),
.d_rst (1'b0),
.d_clk (clk),
.d_data_cntrl ({ adc_decimation_ratio, // 32
.d_data_cntrl ({ adc_correction_enable_b, // 1
adc_correction_enable_a, // 1
adc_correction_coefficient_b, // 16
adc_correction_coefficient_a, // 16
adc_decimation_ratio, // 32
adc_filter_mask})); // 3
endmodule