mirror of
https://github.com/EttusResearch/uhd.git
synced 2026-10-25 17:36:10 +00:00
fpga: dsp: distribute reset and clear through DSP paths
This commit is contained in:
parent
d394ae626a
commit
efa47018e4
@ -27,13 +27,19 @@
|
||||
// ACCUM_WIDTH - Accumulator width
|
||||
// COEFFS_VEC - Vector of NUM_COEFFS values, each of width COEFF_WIDTH to
|
||||
// initialize coeffs. Defaults to an impulse.
|
||||
// RELOADABLE_COEFFS - Enable (1) or disable (0) reloading coefficients at runtime (via reload bus)
|
||||
// BLANK_OUTPUT - Disable (1) or enable (0) output when initially filling internal pipeline
|
||||
// USE_EMBEDDED_REGS_COEFFS - Reduce register usage by only using embedded registers in DSP slices.
|
||||
// Updating taps while streaming will cause temporary output corruption!
|
||||
//
|
||||
// RELOADABLE_COEFFS - Enable (1) or disable (0) reloading coefficients
|
||||
// at runtime (via reload bus)
|
||||
// BLANK_OUTPUT - Disable (1) or enable (0) output when initially filling internal
|
||||
// pipeline
|
||||
// USE_EMBEDDED_REGS_COEFFS - Reduce register usage by only using embedded registers in DSP
|
||||
// slices. Updating taps while streaming will cause temporary output
|
||||
// corruption!
|
||||
// RESET_DATA_PATH - Reset FIR arithmetic pipeline registers when
|
||||
// reset or clear assert.
|
||||
//
|
||||
// Notes:
|
||||
// - If using USE_EMBEDDED_REGS_COEFFS, coefficients must be written at least once as COEFFS_VEC is ignored!
|
||||
// - If using USE_EMBEDDED_REGS_COEFFS, coefficients must be written at least once as COEFFS_VEC is
|
||||
// ignored!
|
||||
// - If using RELOADABLE_COEFFS, coefficients must be written in reverse order!
|
||||
// - Optimizations: For static coefficients (RELOADABLE_COEFFS = 0), zero and symmetric coefficient
|
||||
// optimizations are automatically enabled to reduce DSP slice utilization.
|
||||
@ -52,7 +58,8 @@ module axi_fir_multisample_filter #(
|
||||
bit [COEFF_WIDTH-1:0] COEFFS_VEC [NUM_COEFFS] = '{0: (1 << (COEFF_WIDTH-1)) - 1, default: 0},
|
||||
bit RELOADABLE_COEFFS = 1,
|
||||
bit BLANK_OUTPUT = 1,
|
||||
bit USE_EMBEDDED_REGS_COEFFS = 1
|
||||
bit USE_EMBEDDED_REGS_COEFFS = 1,
|
||||
bit RESET_DATA_PATH = 1
|
||||
)(
|
||||
// clocks and control signals
|
||||
input logic clk,
|
||||
@ -112,7 +119,8 @@ module axi_fir_multisample_filter #(
|
||||
? check_coeffs_symmetric() : 0;
|
||||
localparam int NUM_SLICES = OPTIMIZE_FOR_SYMMETRIC_COEFFS
|
||||
? NUM_COEFFS/2 + NUM_COEFFS[0] : NUM_COEFFS;
|
||||
localparam int PIPELINE_DELAY = NUM_SLICES + 5 // +4 pipeline depth in fir_filter_slice.v, +1 of shift register
|
||||
// +4 pipeline depth in fir_filter_slice.v, +1 of shift register
|
||||
localparam int PIPELINE_DELAY = NUM_SLICES + 5
|
||||
- (OPTIMIZE_FOR_ZERO_COEFFS ? count_zeros_up_to_index(NUM_SLICES) : 0);
|
||||
localparam int SHIFT_REG_WIDTH = (NUM_SPC + 1) * NUM_COEFFS; // length of shift register
|
||||
|
||||
@ -262,7 +270,8 @@ module axi_fir_multisample_filter #(
|
||||
end else begin
|
||||
localparam int GAP = OPTIMIZE_FOR_ZERO_COEFFS ? count_zeros_up_to_index(j) : 0;
|
||||
localparam bit APPLY_SYMMETRY = (OPTIMIZE_FOR_SYMMETRIC_COEFFS == 1) // enabled?
|
||||
&& !((NUM_COEFFS[0] == 1) && (j == NUM_SLICES-1)); // not the center tap for odd NUM_COEFFS
|
||||
&& !((NUM_COEFFS[0] == 1) && (j == NUM_SLICES-1));
|
||||
// not the center tap for odd NUM_COEFFS
|
||||
|
||||
fir_filter_slice #(
|
||||
.IN_WIDTH(IN_WIDTH),
|
||||
@ -271,8 +280,8 @@ module axi_fir_multisample_filter #(
|
||||
.OUT_WIDTH(ACCUM_WIDTH))
|
||||
fir_filter_slice (
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.clear(clear),
|
||||
.reset(RESET_DATA_PATH ? (reset | clear) : 1'b0),
|
||||
.clear(1'b0),
|
||||
.sample_in_stb(s_axis_data_tvalid & s_axis_data_tready),
|
||||
// NUM_SPC is added j times due to the pipeline delay.
|
||||
// +1 for selecting the next index for the FIR result calculation
|
||||
@ -287,10 +296,13 @@ module axi_fir_multisample_filter #(
|
||||
// Mirror index is NUM_COEFFS-1-j, since sample_in_b inside fir_filter_slice
|
||||
// has one cycle delay less that sample_in_a, we need to take it one cycle
|
||||
// later such that both values are in-sync. Thus we add another NUM_SPC to the index.
|
||||
.sample_in_b(APPLY_SYMMETRY ? data_shift_reg[ (NUM_COEFFS-1-j) + (j-GAP+1)*NUM_SPC + K_FLIPPED ] : '0),
|
||||
.sample_in_b(APPLY_SYMMETRY ?
|
||||
data_shift_reg[ (NUM_COEFFS-1-j) + (j-GAP+1)*NUM_SPC + K_FLIPPED ] : '0),
|
||||
.sample_forward(),
|
||||
// For proper coeffient loading, coeff_forward must be shifted in backwards. coeffs[] is already backwards
|
||||
.coeff_in(((USE_EMBEDDED_REGS_COEFFS == 1) && (RELOADABLE_COEFFS == 1)) ? coeff_forward[j] : coeffs[j]),
|
||||
// For proper coeffient loading, coeff_forward must be shifted in backwards.
|
||||
// coeffs[] is already backwards
|
||||
.coeff_in(((USE_EMBEDDED_REGS_COEFFS == 1) && (RELOADABLE_COEFFS == 1)) ?
|
||||
coeff_forward[j] : coeffs[j]),
|
||||
.coeff_forward(coeff_forward[j+1]),
|
||||
.coeff_load_stb(coeff_load_stb),
|
||||
.sample_accum(sample_accum[j]),
|
||||
|
||||
@ -149,6 +149,7 @@ module axis_fir_ms_preload #(
|
||||
//----------------------------------------------------------------------------
|
||||
// Wrapped FIR instance
|
||||
//----------------------------------------------------------------------------
|
||||
localparam bit RESET_DATA_PATH = !PRELOAD_ZEROES;
|
||||
|
||||
axi_fir_multisample_filter #(
|
||||
.IN_WIDTH (IN_WIDTH),
|
||||
@ -161,7 +162,8 @@ module axis_fir_ms_preload #(
|
||||
.COEFFS_VEC (COEFFS_VEC),
|
||||
.RELOADABLE_COEFFS (RELOADABLE_COEFFS),
|
||||
.BLANK_OUTPUT (BLANK_OUTPUT),
|
||||
.USE_EMBEDDED_REGS_COEFFS(USE_EMBEDDED_REGS_COEFFS)
|
||||
.USE_EMBEDDED_REGS_COEFFS(USE_EMBEDDED_REGS_COEFFS),
|
||||
.RESET_DATA_PATH (RESET_DATA_PATH)
|
||||
) fir_inst (
|
||||
.clk (clk),
|
||||
.reset (reset),
|
||||
|
||||
@ -212,8 +212,6 @@ module cic_interpolator #(
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst) begin
|
||||
input_busy <= 1'b0;
|
||||
input_last <= 'X;
|
||||
input_samps <= 'X;
|
||||
end else begin
|
||||
if (data_in.tvalid && data_in.tready) begin
|
||||
// Accepted a new input word; busy until end of interpolation group.
|
||||
@ -280,14 +278,13 @@ module cic_interpolator #(
|
||||
logic [1:0] tlast_pipe;
|
||||
logic [1:0][SPC-1:0][SAMP_W-1:0] tdata_pipe;
|
||||
always_ff @(posedge clk) begin
|
||||
tlast_pipe <= {tlast_pipe[0], gen_tlast };
|
||||
tdata_pipe <= {tdata_pipe[0], input_samps};
|
||||
|
||||
if (rst) begin
|
||||
tvalid_pipe <= 2'b00;
|
||||
tlast_pipe <= 'X;
|
||||
tdata_pipe <= 'X;
|
||||
end else if (gen_tready) begin
|
||||
tvalid_pipe <= {tvalid_pipe[0], gen_tvalid};
|
||||
tlast_pipe <= {tlast_pipe[0], gen_tlast };
|
||||
tdata_pipe <= {tdata_pipe[0], input_samps};
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -87,7 +87,7 @@ module dsp48_prefix_accum #(
|
||||
if (k == 0) begin : gen_first
|
||||
dsp48_add3 #(.AB_CASCADE(0), .USE_PCIN(0)) dsp_inst (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.rst (1'b0),
|
||||
.en (en),
|
||||
.ab (accu_in),
|
||||
.c (data_in[0]),
|
||||
@ -99,7 +99,7 @@ module dsp48_prefix_accum #(
|
||||
end else begin : gen_chain
|
||||
dsp48_add3 #(.AB_CASCADE(1), .USE_PCIN(USE_PCIN)) dsp_inst (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.rst (1'b0),
|
||||
.en (en),
|
||||
.ab (abcout_cas[k-1]),
|
||||
.c (data_in[k]),
|
||||
|
||||
@ -114,9 +114,7 @@ module axis_upsamp_x2_ser #(
|
||||
|
||||
always_ff @(posedge clk) begin : ser_state_proc
|
||||
if (rst || clr) begin
|
||||
state <= IDLE_ST;
|
||||
data_buf <= '0;
|
||||
last_buf <= 1'b0;
|
||||
state <= IDLE_ST;
|
||||
end else begin
|
||||
unique case (state)
|
||||
IDLE_ST : begin
|
||||
|
||||
@ -178,6 +178,13 @@ module ddc_ms
|
||||
.rst (reset)
|
||||
);
|
||||
|
||||
// Delay reset/clear by one cycle so updated configuration settles before
|
||||
// the DSP pipelines are cleared.
|
||||
logic reset_or_clear;
|
||||
always_ff @(posedge clk) begin
|
||||
reset_or_clear <= reset | clear;
|
||||
end
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Latch configuration during burst processing to avoid corrupted data caused
|
||||
// by changing the decimation rate or scaling factor mid-burst.
|
||||
@ -265,7 +272,7 @@ module ddc_ms
|
||||
localparam int DDS_LATENCY = 6; // matches MULTIPLY_LATENCY in dds_ms
|
||||
logic [DDS_LATENCY-1:0] dds_drain_mask;
|
||||
always_ff @(posedge clk) begin
|
||||
if (reset || clear)
|
||||
if (reset_or_clear)
|
||||
dds_drain_mask <= {DDS_LATENCY{1'b1}}; // arm: block next 6 beats
|
||||
else if (dds_out_tready)
|
||||
dds_drain_mask <= {1'b0, dds_drain_mask[DDS_LATENCY-1:1]}; // drain one per cycle
|
||||
@ -284,8 +291,8 @@ module ddc_ms
|
||||
.ORDER (4)
|
||||
) cic_filter_decim_i (
|
||||
.clk (clk),
|
||||
.rst (reset),
|
||||
.clear (clear),
|
||||
.rst (reset_or_clear),
|
||||
.clear ('0),
|
||||
.data_in (decim_in),
|
||||
.data_out (decim_out),
|
||||
.decim_factor (cic_rate),
|
||||
@ -303,8 +310,8 @@ module ddc_ms
|
||||
.PRELOAD_ZEROES (1)
|
||||
) hbf_cascade_i (
|
||||
.clk (clk),
|
||||
.rst (reset),
|
||||
.clear (clear),
|
||||
.rst (reset_or_clear),
|
||||
.clear ('0),
|
||||
.s_axis_tdata (decim_out.tdata),
|
||||
.s_axis_tvalid (decim_out.tvalid),
|
||||
.s_axis_tready (decim_out.tready),
|
||||
|
||||
@ -161,6 +161,13 @@ module duc_ms
|
||||
.rst (reset)
|
||||
);
|
||||
|
||||
// Delay reset/clear by one cycle so updated configuration settles before
|
||||
// the DSP pipelines are cleared.
|
||||
logic reset_or_clear;
|
||||
always_ff @(posedge clk) begin
|
||||
reset_or_clear <= reset | clear;
|
||||
end
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Latch configuration during burst processing to avoid corrupted data caused
|
||||
@ -211,8 +218,8 @@ module duc_ms
|
||||
.PRELOAD_ZEROES (1)
|
||||
) hbf_cascade_i (
|
||||
.clk (clk),
|
||||
.rst (reset),
|
||||
.clear (clear),
|
||||
.rst (reset_or_clear),
|
||||
.clear ('0),
|
||||
.s_axis_tdata (sample_in_tdata),
|
||||
.s_axis_tvalid (sample_in_tvalid),
|
||||
.s_axis_tready (sample_in_tready),
|
||||
@ -241,8 +248,8 @@ module duc_ms
|
||||
.ORDER (4)
|
||||
) cic_filter_interp_i (
|
||||
.clk (clk),
|
||||
.rst (reset),
|
||||
.clear (clear),
|
||||
.rst (reset_or_clear),
|
||||
.clear ('0),
|
||||
.data_in (cic_in),
|
||||
.data_out (cic_out),
|
||||
.interp_factor (cic_rate),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user