From 7176a99cf5b7ad637256554465371a11a6191d35 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Mar 2019 09:18:13 -0700 Subject: [PATCH 1/3] WIP --- bench/cpp/Makefile | 5 +- bench/cpp/slowfil_srl_tb.cpp | 245 ++++++++++++++++++++++++++++++++++ rtl/Makefile | 6 +- rtl/slowfil_srl.v | 251 +++++++++++++++++++++++++++++++++++ 4 files changed, 505 insertions(+), 2 deletions(-) create mode 100644 bench/cpp/slowfil_srl_tb.cpp create mode 100644 rtl/slowfil_srl.v diff --git a/bench/cpp/Makefile b/bench/cpp/Makefile index 19b7cbb..bdafb72 100644 --- a/bench/cpp/Makefile +++ b/bench/cpp/Makefile @@ -52,7 +52,7 @@ export $(VERILATOR) VROOT := $(VERILATOR_ROOT) VDEFS := $(shell ./vversion.sh) INCS := -I$(RTLD)/obj_dir/ -I$(VROOT)/include -I../rtl/obj_dir -PROGRAMS := slowsymf_tb genericfir_tb fastfir_tb boxcar_tb lfsr_gal_tb lfsr_fib_tb delayw_tb slowfil_tb shalfband_tb lfsr_tb # symfil_tb +PROGRAMS := slowsymf_tb genericfir_tb fastfir_tb boxcar_tb lfsr_gal_tb lfsr_fib_tb delayw_tb slowfil_tb slowfil_srl_tb shalfband_tb lfsr_tb # symfil_tb SOURCES := $(addsuffix .cpp,$(PROGRAMS)) filtertb.cpp VOBJDR := $(RTLD)/obj_dir SYSVDR := $(VROOT)/include @@ -78,6 +78,9 @@ fastfir_tb: $(OBJDIR)/fastfir_tb.o $(VLIB) $(VOBJDR)/Vfastfir__ALL.a slowfil_tb: $(OBJDIR)/slowfil_tb.o $(VLIB) $(VOBJDR)/Vslowfil__ALL.a $(CXX) $(CFLAGS) $(INCS) $^ -o $@ +slowfil_srl_tb: $(OBJDIR)/slowfil_srl_tb.o $(VLIB) $(VOBJDR)/Vslowfil_srl__ALL.a + $(CXX) $(CFLAGS) $(INCS) $^ -o $@ + slowsymf_tb: $(OBJDIR)/slowsymf_tb.o $(VLIB) $(VOBJDR)/Vslowsymf__ALL.a $(CXX) $(CFLAGS) $(INCS) $^ -o $@ diff --git a/bench/cpp/slowfil_srl_tb.cpp b/bench/cpp/slowfil_srl_tb.cpp new file mode 100644 index 0000000..eeba885 --- /dev/null +++ b/bench/cpp/slowfil_srl_tb.cpp @@ -0,0 +1,245 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: slowfil_srl_tb.cpp +// +// Project: DSP Filtering Example Project +// +// Purpose: +// +// Creator: Dan Gisselquist, Ph.D. +// Gisselquist Technology, LLC +// +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017-2018, Gisselquist Technology, LLC +// +// This file is part of the DSP filtering set of designs. +// +// The DSP filtering designs are free RTL designs: you can redistribute them +// and/or modify any of them under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// The DSP filtering designs are distributed in the hope that they will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser +// General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with these designs. (It's in the $(ROOT)/doc directory. Run make +// with no target there if the PDF file isn't present.) If not, see +// for a copy. +// +// License: LGPL, v3, as defined and found on www.gnu.org, +// http://www.gnu.org/licenses/lgpl.html +// +//////////////////////////////////////////////////////////////////////////////// +// +// +#include +#include +#include +#include +#include +#include + +#include "verilated.h" +#include "verilated_vcd_c.h" +#include "Vslowfil_srl.h" +#include "testb.h" + +// #define FILTER_HAS_O_CE +#include "filtertb.h" +#include "filtertb.cpp" +#include "twelvebfltr.h" + +const unsigned IW = 16, + TW = 16, + OW = IW+TW+7, + NTAPS = 110, + DELAY = 2, + CKPCE = NTAPS; + +static int nextlg(int vl) { + int r; + + for(r=1; r { +public: + bool m_done; + + SLOWFIL_SRL_TB(void) { + IW(::IW); + TW(::TW); + OW(::OW); + NTAPS(::NTAPS); + DELAY(::DELAY); + CKPCE(::CKPCE); + } + + void test(int nlen, int64_t *data) { + clear_filter(); + FILTERTB::test(nlen, data); + } + + void load(int nlen, int64_t *data) { + reset(); + FILTERTB::load(nlen, data); + } + + void clear_filter(void) { + m_core->i_tap_wr = 0; + + // This filter requires running NTAPS worth of data through + // it to fully clear it. The reset isn't sufficient. + m_core->i_ce = 1; + m_core->i_sample = 0; + for(int k=0; ki_ce = 0; + for(int k=0; kopentrace("trace.vcd"); + tb->reset(); + + printf("Impulse tests\n"); + for(unsigned k=0; ktestload(NTAPS, tapvec); + + // Then test whether or not the filter overflows + tb->test_overflow(); + } + + printf("Block Fil, Impulse input\n"); + + // + // Block filter, impulse input + // + for(unsigned i=0; itestload(NTAPS, tapvec); + + for(unsigned i=0; i<2*NTAPS; i++) + ivec[i] = 0; + ivec[0] = IMPULSE; + + tb->test(2*NTAPS, ivec); + + for(unsigned i=0; itest(2*NTAPS, ivec); + + for(unsigned i=0; itest_overflow()); + + { + double fp, // Passband frequency cutoff + fs, // Stopband frequency cutoff, + depth, // Depth of the stopband + ripple; // Maximum deviation within the passband + + tb->measure_lowpass(fp, fs, depth, ripple); + printf("FP = %f\n", fp); + printf("FS = %f\n", fs); + printf("DEPTH = %6.2f dB\n", depth); + printf("RIPPLE = %.2g\n", ripple); + + // The depth of the filter should be between -14 and -13. + // assert() that here. + assert(depth < -13); + assert(depth > -14); + } + + assert(NCOEFFS < NTAPS); + for(int i=0; itestload(NTAPS, tapvec); + + { + double fp, // Passband frequency cutoff + fs, // Stopband frequency cutoff, + depth, // Depth of the stopband + ripple; // Maximum deviation within the passband + + tb->measure_lowpass(fp, fs, depth, ripple); + printf("FP = %f\n", fp); + printf("FS = %f\n", fs); + printf("DEPTH = %6.2f dB\n", depth); + printf("RIPPLE = %.2g\n", ripple); + + // The depth of this stopband should be between -55 and -54 dB + assert(depth < -54); + assert(depth > -55); + } + printf("SUCCESS\n"); + + exit(0); +} + diff --git a/rtl/Makefile b/rtl/Makefile index b030a7f..56c6407 100644 --- a/rtl/Makefile +++ b/rtl/Makefile @@ -47,7 +47,7 @@ VDIRFB:= $(FBDIR)/obj_dir VERILATOR := verilator VFLAGS := -O3 -Wall -MMD -trace -cc SUBMAKE := make --no-print-directory -C -CORES := smplfir iiravg genericfir fastfir boxcar lfsr_gal lfsr_fib delayw lfsr slowfil slowsymf shalfband +CORES := smplfir iiravg genericfir fastfir boxcar lfsr_gal lfsr_fib delayw lfsr slowfil slowfil_srl slowsymf shalfband .PHONY: all $(CORES) all: $(CORES) # symfil @@ -55,6 +55,7 @@ genericfir: $(VDIRFB)/Vgenericfir__ALL.a fastfir: $(VDIRFB)/Vfastfir__ALL.a symfil: $(VDIRFB)/Vsymfil__ALL.a slowfil: $(VDIRFB)/Vslowfil__ALL.a +slowfil_srl: $(VDIRFB)/Vslowfil_srl__ALL.a slowsymf: $(VDIRFB)/Vslowsymf__ALL.a shalfband: $(VDIRFB)/Vshalfband__ALL.a smplfir: $(VDIRFB)/Vsmplfir__ALL.a @@ -83,6 +84,9 @@ $(VDIRFB)/Vsymfil__ALL.a: $(VDIRFB)/Vsymfil.mk $(VDIRFB)/Vslowfil__ALL.a: $(VDIRFB)/Vslowfil.mk $(SUBMAKE) $(VDIRFB)/ -f Vslowfil.mk Vslowfil__ALL.a +$(VDIRFB)/Vslowfil_srl__ALL.a: $(VDIRFB)/Vslowfil_srl.mk + $(SUBMAKE) $(VDIRFB)/ -f Vslowfil_srl.mk Vslowfil_srl__ALL.a + $(VDIRFB)/Vslowsymf__ALL.a: $(VDIRFB)/Vslowsymf.mk $(SUBMAKE) $(VDIRFB)/ -f Vslowsymf.mk Vslowsymf__ALL.a diff --git a/rtl/slowfil_srl.v b/rtl/slowfil_srl.v new file mode 100644 index 0000000..aa89141 --- /dev/null +++ b/rtl/slowfil_srl.v @@ -0,0 +1,251 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: slowfil_srl.v +// +// Project: DSP Filtering Example Project +// +// Purpose: Unlike fastfir.v and genericfir.v, both of which require one +// hardware multiply element per tap, this slowfil design requires +// only one multiply element in total. It is useful for those times and +// cases when there are fewer taps than there are clock intervals between +// incoming samples. In all other respects, however, it remains quite +// generic. +// +// Creator: Dan Gisselquist, Ph.D. +// Gisselquist Technology, LLC +// +// Note: This is a modified version of slowfil.v by Dan Gisselquist that +// uses a shift-register based approach, over a memory-based one. +// +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2017-2018, Gisselquist Technology, LLC +// +// This file is part of the DSP filtering set of designs. +// +// The DSP filtering designs are free RTL designs: you can redistribute them +// and/or modify any of them under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// The DSP filtering designs are distributed in the hope that they will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser +// General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with these designs. (It's in the $(ROOT)/doc directory. Run make +// with no target there if the PDF file isn't present.) If not, see +// for a copy. +// +// License: LGPL, v3, as defined and found on www.gnu.org, +// http://www.gnu.org/licenses/lgpl.html +// +//////////////////////////////////////////////////////////////////////////////// +// +// +`default_nettype none +// +module slowfil_srl(i_clk, i_reset, i_tap_wr, i_tap, i_ce, i_sample, o_ce, o_result); + parameter LGNTAPS = 7, IW=16, TW=16, OW = IW+TW+LGNTAPS; + parameter [LGNTAPS:0] NTAPS = 110; // (1< Date: Thu, 21 Mar 2019 09:29:31 -0700 Subject: [PATCH 2/3] Fix spacing --- rtl/slowfil_srl.v | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/rtl/slowfil_srl.v b/rtl/slowfil_srl.v index 7544869..2f73747 100644 --- a/rtl/slowfil_srl.v +++ b/rtl/slowfil_srl.v @@ -79,9 +79,9 @@ module slowfil_srl(i_clk, i_reset, i_tap_wr, i_tap, i_ce, i_sample, o_ce, o_resu reg signed [(TW-1):0] tap; // Value read from coef memory reg [(LGNTAPS-1):0] tidx; // Coefficient read index - /* Verilator lint_off LITENDIAN */ + /* Verilator lint_off LITENDIAN */ reg [0:(MEMSZ-1)] dsrl [(IW-1):0]; // Data memory - /* Verilator lint_on LITENDIAN */ + /* Verilator lint_on LITENDIAN */ reg signed [(IW-1):0] data; // Data value read from memory // Traveling CE values @@ -204,10 +204,10 @@ module slowfil_srl(i_clk, i_reset, i_tap_wr, i_tap, i_ce, i_sample, o_ce, o_resu initial data = 0; generate - for (i=0; i < IW; i=i+1) begin - always @(posedge i_clk) - data[i] <= dsrl[i][tidx[(LGNTAPS-1):0]]; - end + for (i=0; i < IW; i=i+1) begin + always @(posedge i_clk) + data[i] <= dsrl[i][tidx[(LGNTAPS-1):0]]; + end endgenerate // d_ce is valid when the first data from memory is read/valid From b2c7ebd1e06b985437c5fb3b505366c874bfff2f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Mar 2019 10:53:08 -0700 Subject: [PATCH 3/3] Revert changes, tidy up --- rtl/slowfil_srl.v | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/rtl/slowfil_srl.v b/rtl/slowfil_srl.v index 2f73747..c082b70 100644 --- a/rtl/slowfil_srl.v +++ b/rtl/slowfil_srl.v @@ -79,9 +79,7 @@ module slowfil_srl(i_clk, i_reset, i_tap_wr, i_tap, i_ce, i_sample, o_ce, o_resu reg signed [(TW-1):0] tap; // Value read from coef memory reg [(LGNTAPS-1):0] tidx; // Coefficient read index - /* Verilator lint_off LITENDIAN */ - reg [0:(MEMSZ-1)] dsrl [(IW-1):0]; // Data memory - /* Verilator lint_on LITENDIAN */ + reg [(IW-1):0] dsrl [0:(MEMSZ-1)]; // Data memory reg signed [(IW-1):0] data; // Data value read from memory // Traveling CE values @@ -136,12 +134,15 @@ module slowfil_srl(i_clk, i_reset, i_tap_wr, i_tap, i_ce, i_sample, o_ce, o_resu // Notice how this data writing section is *independent* of the reset, // depending only upon new sample data. + always @(posedge i_clk) + if (i_ce) + dsrl[0] <= i_sample; generate genvar i; - for (i = 0; i < IW; i=i+1) begin + for (i = 1; i < MEMSZ; i=i+1) begin always @(posedge i_clk) if (i_ce) - dsrl[i] <= { i_sample[i], dsrl[i][0:(MEMSZ-2)] }; + dsrl[i] <= dsrl[i-1]; end endgenerate @@ -203,12 +204,8 @@ module slowfil_srl(i_clk, i_reset, i_tap_wr, i_tap, i_ce, i_sample, o_ce, o_resu tap <= tapmem[tidx[(LGNTAPS-1):0]]; initial data = 0; - generate - for (i=0; i < IW; i=i+1) begin - always @(posedge i_clk) - data[i] <= dsrl[i][tidx[(LGNTAPS-1):0]]; - end - endgenerate + always @(posedge i_clk) + data <= dsrl[tidx[(LGNTAPS-1):0]]; // d_ce is valid when the first data from memory is read/valid initial d_ce = 0;