Skip to content

Instantly share code, notes, and snippets.

@ZipCPU
Created January 30, 2020 20:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ZipCPU/28038cbbccccefc0025894c7c6a20acb to your computer and use it in GitHub Desktop.
Save ZipCPU/28038cbbccccefc0025894c7c6a20acb to your computer and use it in GitHub Desktop.
////////////////////////////////////////////////////////////////////////////////
//
// Filename: cicfil.v
//
// Project: SDR, a basic Soft(Gate)ware Defined Radio architecture
//
// Purpose: Perform some number of CIC integrate and dump stages, followed
// by a downsample by half the number of averages given. Hence,
// if we integrate 4 samples and output, we'll downsample by two (4 / 2).
//
// Further, we need to shift by the log_2 of our downsample rate times
// the number of stages.
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2020, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. (It's in the $(ROOT)/doc directory. Run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
`default_nettype none
//
module cicfil(i_clk, i_reset, i_navg, i_ce, i_val, o_ce, o_val);
parameter IW=16, OW=32, LGMEM=32, SHIFT=0, STAGES=7;
input wire i_clk, i_reset;
//
// Watch the gain here: the gain of STAGES CICs is i_navg * STAGES
// Easiest way to handle it is to set i_navg to 2^n, and STAGES to 2^m
// then the gain can be removed with a simple shift
input wire [(LGMEM-1):0] i_navg;
input wire i_ce;
input wire [(IW-1):0] i_val;
output reg o_ce;
output wire [(OW-1):0] o_val;
genvar k;
reg [(IW+LGMEM-1):0] acc[0:STAGES];
reg [(LGMEM-2):0] ctr;
reg bistate;
// Decimation memory
reg [(IW+LGMEM-1):0] r_dmem0[0:STAGES];
reg [(IW+LGMEM-1):0] r_dmem1[0:STAGES];
reg [(IW+LGMEM-1):0] dec[0:STAGES-1];
initial acc[0] = 0;
always @(posedge i_clk)
if (i_reset)
acc[0] <= { {(LGMEM){i_val[IW-1]}}, i_val };
else if (i_ce)
acc[0] <= { {(LGMEM){i_val[IW-1]}}, i_val };
// The integration section
generate for(k=1; k<STAGES+1; k=k+1)
begin : CIC_INTEGRATION_GEN_LOOP
initial acc[k] = 0;
always @(posedge i_clk)
if (i_reset)
acc[k] <= 0;
else if (i_ce)
acc[k] <= acc[k] + acc[k-1];
end endgenerate
// Calculate our new clock
//
// For i_navg = 4
// ctr = 0, 1, 0, 1, 0, 1, 0, 1, 0, 1
// o_ce = 1, 0, 1, 0, 1, 0, 1, 0, 1, 0
// For i_navg = 8
// ctr = 0, 1, 2, 3, 0, 1, 2, 3, 0, 1
// o_ce = 1, 0, 0, 0, 1, 0, 0, 0, 1, 0
// For i_navg = 16
// ctr = 0, 1, 2, 3, 4, 5, 6, 7, 0, 1
// o_ce = 1, 0, 0, 0, 0, 0, 0, 0, 1, 0
initial { o_ce, ctr } = 0;
always @(posedge i_clk)
if (i_reset)
{ o_ce, ctr } <= 0;
else if (i_ce)
begin
if (ctr+{{(LGMEM-2){1'b0}},1'b1} < i_navg[(LGMEM-1):1])
begin
ctr <= ctr + 1;
o_ce <= 1'b0;
end else begin
ctr <= 0;
o_ce <= 1'b1;
end
end else
o_ce <= 1'b0;
initial bistate = 0;
always @(posedge i_clk)
if (i_reset)
bistate <= 1'b0;
else if (o_ce)
bistate <= !bistate;
initial r_dmem0[0] = 0;
initial r_dmem1[0] = 0;
always @(posedge i_clk)
if (i_reset)
begin
r_dmem0[0] <= 0;
r_dmem1[0] <= 0;
end else if (o_ce)
begin
if (bistate)
r_dmem0[0] <= acc[STAGES];
else
r_dmem1[0] <= acc[STAGES];
end
generate for(k=1; k<STAGES+1; k=k+1)
begin : CIC_DECIMATION_GEN_LOOP
initial r_dmem0[k] = 0;
initial r_dmem1[k] = 0;
always @(posedge i_clk)
if (i_reset)
begin
r_dmem0[k] <= 0;
r_dmem1[k] <= 0;
dec[k-1] <= 0;
end else if (o_ce)
begin
if (bistate)
begin
dec[k-1] <= r_dmem0[k-1] - r_dmem0[k];
r_dmem0[k] <= r_dmem0[k-1];
end else begin
dec[k-1] <= r_dmem1[k-1] - r_dmem1[k];
r_dmem1[k] <= r_dmem1[k-1];
end
end
end endgenerate
// convround #(IW+LGMEM,OW,SHIFT)
// mkresult(i_clk,o_ce,dec[STAGES-1],o_val);
initial o_val = 0;
always @(posedge i_clk)
if (i_reset)
o_val <= 0;
else if (o_ce)
o_val <= dec[STAGES-1][IW+LGMEM-1:IW+LGMEM-OW];
// Verilator lint_off UNUSED
wire unused;
assign unused = &{ 1'b0, i_navg[0], dec[STAGES-1][IW+LGMEM-OW-1:0] };
// Verilator lint_on UNUSED
endmodule
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment