Created
January 30, 2020 20:47
-
-
Save ZipCPU/28038cbbccccefc0025894c7c6a20acb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//////////////////////////////////////////////////////////////////////////////// | |
// | |
// 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