axi_dac_interpolate: Move processing pipeline to own sub-module

Move the processing pipeline of the axi_adc_decimate core to its own
sub-module. This makes it easier to simulate the processing independent of
the register map.

Also since the filter is two instances of the same logic, one for each
channel, let the new sub-module model one channel and instantiate it twice.
This allows to change the implementation without having to change the same
code twice.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
main
Lars-Peter Clausen 2017-04-05 14:23:14 +02:00
parent a02a763139
commit 9c2c50728c
3 changed files with 172 additions and 160 deletions

View File

@ -47,10 +47,10 @@ module axi_dac_interpolate(
input dac_valid_a, input dac_valid_a,
input dac_valid_b, input dac_valid_b,
output reg [15:0] dac_int_data_a, output [15:0] dac_int_data_a,
output reg [15:0] dac_int_data_b, output [15:0] dac_int_data_b,
output reg dac_int_valid_a, output dac_int_valid_a,
output reg dac_int_valid_b, output dac_int_valid_b,
// axi interface // axi interface
@ -94,176 +94,42 @@ module axi_dac_interpolate(
wire [31:0] filter_mask_a; wire [31:0] filter_mask_a;
wire [31:0] filter_mask_b; wire [31:0] filter_mask_b;
wire dac_fir_valid_a;
wire [35:0] dac_fir_data_a;
wire dac_fir_valid_b;
wire [35:0] dac_fir_data_b;
wire dac_cic_valid_a;
wire [109:0] dac_cic_data_a;
wire dac_cic_valid_b;
wire [109:0] dac_cic_data_b;
wire dma_transfer_suspend; wire dma_transfer_suspend;
reg dac_filt_int_valid_a;
reg dac_filt_int_valid_b;
reg [15:0] interp_rate_cic_a;
reg [15:0] interp_rate_cic_b;
reg [31:0] filter_mask_a_d1;
reg [31:0] filter_mask_b_d1;
reg cic_change_rate_a;
reg cic_change_rate_b;
reg [31:0] interpolation_counter_a;
reg [31:0] interpolation_counter_b;
// signal name changes // signal name changes
assign up_clk = s_axi_aclk; assign up_clk = s_axi_aclk;
assign up_rstn = s_axi_aresetn; assign up_rstn = s_axi_aresetn;
fir_interp fir_interpolation_a ( axi_dac_interpolate_filter i_filter_a (
.clk (dac_clk), .dac_clk (dac_clk),
.clk_enable (dac_cic_valid_a), .dac_rst (dac_rst),
.reset (dac_rst | dma_transfer_suspend),
.filter_in (dac_data_a),
.filter_out (dac_fir_data_a),
.ce_out (dac_fir_valid_a));
fir_interp fir_interpolation_b ( .dac_data (dac_data_a),
.clk (dac_clk), .dac_valid (dac_valid_a),
.clk_enable (dac_cic_valid_b),
.reset (dac_rst | dma_transfer_suspend),
.filter_in (dac_data_b),
.filter_out (dac_fir_data_b),
.ce_out (dac_fir_valid_b));
cic_interp cic_interpolation_a ( .dac_int_data (dac_int_data_a),
.clk (dac_clk), .dac_int_valid (dac_int_valid_a),
.clk_enable (dac_valid_a),
.reset (dac_rst | cic_change_rate_a | dma_transfer_suspend),
.rate (interp_rate_cic_a),
.load_rate (1'b0),
.filter_in (dac_fir_data_a[30:0]),
.filter_out (dac_cic_data_a),
.ce_out (dac_cic_valid_a));
cic_interp cic_interpolation_b ( .filter_mask (filter_mask_a),
.clk (dac_clk), .interpolation_ratio (interpolation_ratio_a),
.clk_enable (dac_valid_b), .dma_transfer_suspend (dma_transfer_suspend)
.reset (dac_rst | cic_change_rate_b | dma_transfer_suspend), );
.rate (interp_rate_cic_b),
.load_rate (1'b0),
.filter_in (dac_fir_data_b[30:0]),
.filter_out (dac_cic_data_b),
.ce_out (dac_cic_valid_b));
always @(posedge dac_clk) begin axi_dac_interpolate_filter i_filter_b (
filter_mask_a_d1 <= filter_mask_a; .dac_clk (dac_clk),
filter_mask_b_d1 <= filter_mask_b; .dac_rst (dac_rst),
if (filter_mask_a_d1 != filter_mask_a) begin
cic_change_rate_a <= 1'b1;
end else begin
cic_change_rate_a <= 1'b0;
end
if (filter_mask_b_d1 != filter_mask_b) begin
cic_change_rate_b <= 1'b1;
end else begin
cic_change_rate_b <= 1'b0;
end
end
always @(posedge dac_clk) begin .dac_data (dac_data_b),
if (interpolation_ratio_a == 0 || interpolation_ratio_a == 1) begin .dac_valid (dac_valid_b),
dac_int_valid_a <= dac_filt_int_valid_a;
end else begin
if (dac_filt_int_valid_a == 1'b1) begin
if (interpolation_counter_a < interpolation_ratio_a) begin
interpolation_counter_a <= interpolation_counter_a + 1;
dac_int_valid_a <= 1'b0;
end else begin
interpolation_counter_a <= 0;
dac_int_valid_a <= 1'b1;
end
end else begin
dac_int_valid_a <= 1'b0;
end
end
end
always @(posedge dac_clk) begin .dac_int_data (dac_int_data_b),
if (interpolation_ratio_b == 0 || interpolation_ratio_b == 1) begin .dac_int_valid (dac_int_valid_b),
dac_int_valid_b <= dac_filt_int_valid_b;
end else begin
if (dac_filt_int_valid_b == 1'b1) begin
if (interpolation_counter_b < interpolation_ratio_b) begin
interpolation_counter_b <= interpolation_counter_b + 1;
dac_int_valid_b <= 1'b0;
end else begin
interpolation_counter_b <= 0;
dac_int_valid_b <= 1'b1;
end
end else begin
dac_int_valid_b <= 1'b0;
end
end
end
always @(*) begin .filter_mask (filter_mask_b),
case (filter_mask_a) .interpolation_ratio (interpolation_ratio_b),
16'h1: dac_int_data_a = dac_cic_data_a[31:16]; .dma_transfer_suspend (dma_transfer_suspend)
16'h2: dac_int_data_a = dac_cic_data_a[31:16]; );
16'h3: dac_int_data_a = dac_cic_data_a[31:16];
16'h6: dac_int_data_a = dac_cic_data_a[31:16];
16'h7: dac_int_data_a = dac_cic_data_a[31:16];
default: dac_int_data_a = dac_data_a;
endcase
case (filter_mask_a)
16'h1: dac_filt_int_valid_a = dac_fir_valid_a;
16'h2: dac_filt_int_valid_a = dac_fir_valid_a;
16'h3: dac_filt_int_valid_a = dac_fir_valid_a;
16'h6: dac_filt_int_valid_a = dac_fir_valid_a;
16'h7: dac_filt_int_valid_a = dac_fir_valid_a;
default: dac_filt_int_valid_a = dac_valid_a & !dma_transfer_suspend;
endcase
case (filter_mask_b)
16'h1: dac_int_data_b = dac_cic_data_b[31:16];
16'h2: dac_int_data_b = dac_cic_data_b[31:16];
16'h3: dac_int_data_b = dac_cic_data_b[31:16];
16'h6: dac_int_data_b = dac_cic_data_b[31:16];
16'h7: dac_int_data_b = dac_cic_data_b[31:16];
default: dac_int_data_b = dac_data_b;
endcase
case (filter_mask_b)
16'h1: dac_filt_int_valid_b = dac_fir_valid_b;
16'h2: dac_filt_int_valid_b = dac_fir_valid_b;
16'h3: dac_filt_int_valid_b = dac_fir_valid_b;
16'h6: dac_filt_int_valid_b = dac_fir_valid_b;
16'h7: dac_filt_int_valid_b = dac_fir_valid_b;
default: dac_filt_int_valid_b = dac_valid_b & !dma_transfer_suspend;
endcase
case (filter_mask_a)
16'h1: interp_rate_cic_a = 16'd5;
16'h2: interp_rate_cic_a = 16'd50;
16'h3: interp_rate_cic_a = 16'd500;
16'h6: interp_rate_cic_a = 16'd5000;
16'h7: interp_rate_cic_a = 16'd50000;
default: interp_rate_cic_a = 16'd1;
endcase
case (filter_mask_b)
16'h1: interp_rate_cic_b = 16'd5;
16'h2: interp_rate_cic_b = 16'd50;
16'h3: interp_rate_cic_b = 16'd500;
16'h6: interp_rate_cic_b = 16'd5000;
16'h7: interp_rate_cic_b = 16'd50000;
default: interp_rate_cic_b = 16'd1;
endcase
end
axi_dac_interpolate_reg axi_dac_interpolate_reg_inst ( axi_dac_interpolate_reg axi_dac_interpolate_reg_inst (

View File

@ -0,0 +1,145 @@
// ***************************************************************************
// ***************************************************************************
// Copyright 2017(c) Analog Devices, Inc.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
// - Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// - Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in
// the documentation and/or other materials provided with the
// distribution.
// - Neither the name of Analog Devices, Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
// - The use of this software may or may not infringe the patent rights
// of one or more patent holders. This license does not release you
// from the requirement that you obtain separate licenses from these
// patent holders to use this software.
// - Use of the software either in source or binary form, must be run
// on or directly connected to an Analog Devices Inc. component.
//
// THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED.
//
// IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY
// RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ***************************************************************************
// ***************************************************************************
`timescale 1ns/100ps
module axi_dac_interpolate_filter (
input dac_clk,
input dac_rst,
input [15:0] dac_data,
input dac_valid,
output reg [15:0] dac_int_data,
output reg dac_int_valid,
input [31:0] filter_mask,
input [31:0] interpolation_ratio,
input dma_transfer_suspend
);
// internal signals
reg dac_filt_int_valid;
reg [15:0] interp_rate_cic;
reg [31:0] filter_mask_d1;
reg cic_change_rate;
reg [31:0] interpolation_counter;
wire dac_fir_valid;
wire [35:0] dac_fir_data;
wire dac_cic_valid;
wire [109:0] dac_cic_data;
fir_interp fir_interpolation (
.clk (dac_clk),
.clk_enable (dac_cic_valid),
.reset (dac_rst | dma_transfer_suspend),
.filter_in (dac_data),
.filter_out (dac_fir_data),
.ce_out (dac_fir_valid));
cic_interp cic_interpolation (
.clk (dac_clk),
.clk_enable (dac_valid),
.reset (dac_rst | cic_change_rate | dma_transfer_suspend),
.rate (interp_rate_cic),
.load_rate (1'b0),
.filter_in (dac_fir_data[30:0]),
.filter_out (dac_cic_data),
.ce_out (dac_cic_valid));
always @(posedge dac_clk) begin
filter_mask_d1 <= filter_mask;
if (filter_mask_d1 != filter_mask) begin
cic_change_rate <= 1'b1;
end else begin
cic_change_rate <= 1'b0;
end
end
always @(posedge dac_clk) begin
if (interpolation_ratio == 0 || interpolation_ratio == 1) begin
dac_int_valid <= dac_filt_int_valid;
end else begin
if (dac_filt_int_valid == 1'b1) begin
if (interpolation_counter < interpolation_ratio) begin
interpolation_counter <= interpolation_counter + 1;
dac_int_valid <= 1'b0;
end else begin
interpolation_counter <= 0;
dac_int_valid <= 1'b1;
end
end else begin
dac_int_valid <= 1'b0;
end
end
end
always @(*) begin
case (filter_mask)
16'h1: dac_int_data = dac_cic_data[31:16];
16'h2: dac_int_data = dac_cic_data[31:16];
16'h3: dac_int_data = dac_cic_data[31:16];
16'h6: dac_int_data = dac_cic_data[31:16];
16'h7: dac_int_data = dac_cic_data[31:16];
default: dac_int_data = dac_data;
endcase
case (filter_mask)
16'h1: dac_filt_int_valid = dac_fir_valid;
16'h2: dac_filt_int_valid = dac_fir_valid;
16'h3: dac_filt_int_valid = dac_fir_valid;
16'h6: dac_filt_int_valid = dac_fir_valid;
16'h7: dac_filt_int_valid = dac_fir_valid;
default: dac_filt_int_valid = dac_valid & !dma_transfer_suspend;
endcase
case (filter_mask)
16'h1: interp_rate_cic = 16'd5;
16'h2: interp_rate_cic = 16'd50;
16'h3: interp_rate_cic = 16'd500;
16'h6: interp_rate_cic = 16'd5000;
16'h7: interp_rate_cic = 16'd50000;
default: interp_rate_cic = 16'd1;
endcase
end
endmodule

View File

@ -11,6 +11,7 @@ adi_ip_files axi_dac_interpolate [list \
"cic_interp.v" \ "cic_interp.v" \
"fir_interp.v" \ "fir_interp.v" \
"axi_dac_interpolate_reg.v" \ "axi_dac_interpolate_reg.v" \
"axi_dac_interpolate_filter.v" \
"axi_dac_interpolate.v" ] "axi_dac_interpolate.v" ]
adi_ip_properties axi_dac_interpolate adi_ip_properties axi_dac_interpolate