浏览代码

Изменил структуру CIC-фильтра. Добавил скрипты

Anatoliy Chigirinskiy 4 月之前
父节点
当前提交
42baa3d5a9

+ 22 - 2
src/src/ExtDspInterface/DspInterface.v

@@ -117,6 +117,9 @@ module	DspInterface
 	
 	wire	signed	[31:0]	filteredDecimData;
 	wire	signed	[31:0]	filteredDecimDataQ;
+
+	wire 	signed [31:0]	afterFirData;
+	wire 					afterFirVal;
 	wire	filteredDecimDataVal;
 //================================================================================
 //	ASSIGNMENTS
@@ -257,6 +260,23 @@ CicFilterNewWrapperNoIntDiff DecimFilter
 	.DataVal_o		(filteredDecimDataVal)
 );
 
+FirFilter #(
+	.DATA_WIDTH		(16),
+	.COEFF_WIDTH	(16),
+	.NUM_TAPS		(32)
+)
+FirFilterInst (
+	.Clk_i			(Clk_i),
+	.Rst_i			(Rst_i),
+	.DecimFactor_i	(DecimFactor_i),
+	.Data_i			(filteredDecimData),
+	.Val_i			(filteredDecimDataVal),
+
+	.Data_o			(afterFirData),
+	.Val_o			(afterFirVal)
+);
+
+
 reg [15:0] currDecimFactor;
 reg [15:0] currDecimFactorR;
 
@@ -378,8 +398,8 @@ OscDataFormer	DecimDataFormer
 	.OscWind_i			(OscWind_i),
 	.MeasNum_i			(MeasNum_i),
 
-	.AdcDataVal_i		(filteredDecimDataVal),
-	.AdcData_i			(filteredDecimData),	
+	.AdcDataVal_i		(afterFirVal),
+	.AdcData_i			(afterFirData),	
 	
 	.OscDataBus_o		(decimDataBus),
 	.OscDataBusVal_o	(decimDataBusVal)

+ 16 - 14
src/src/FftDataFiltering/TestCicFilter/CicDecimator.sv

@@ -1,32 +1,34 @@
 module CicDecimator #
 (
-    parameter InDataWidth = 18
+    parameter InDataWidth = 18,
+    parameter DECIM_WIDTH = 4 // Decimation factor width
 )
 (
-    input logic                                 Clk_i,
-    input logic                                 Rst_i,
-    input logic     [2:0]                       DecimFactor_i, // Decimation factor (1, 2, 4, 8)
-    input logic     signed [InDataWidth-1:0]    Data_i,
-    input logic                                 DataVal_i,
+    input logic                                 	Clk_i,
+    input logic                                 	Rst_i,
+    input logic            [DECIM_WIDTH-1:0]    	DecimFactor_i, 
+    input logic     signed [InDataWidth-1:0]    	Data_i,
+    input logic                                 	DataVal_i,
 
-    output logic    signed [InDataWidth-1:0]    Data_o,
-    output logic                                DataVal_o
+    output logic    signed [InDataWidth-1:0]    	Data_o,
+    output logic                                	DataVal_o
 );
 
 //================================================================================
 //								REG/WIRE
 //================================================================================
-logic           [3:0]                   decimCnt;
-logic           [2:0]                   decimFactor;
+logic           [DECIM_WIDTH -1 : 0 ]                  	decimCnt;
+logic           [DECIM_WIDTH-1  : 0 ]                	decimFactor;
 
-logic signed    [InDataWidth - 1 : 0]   decimDataReg;
-logic                                   decimDataValReg;
+logic signed    [InDataWidth - 1 : 0]   			decimDataReg;
+logic                                   			decimDataValReg;
 
 //================================================================================
 //								ASSIGNMENTS
 //================================================================================
-assign Data_o = decimDataReg;
-assign DataVal_o = decimDataValReg;
+ /* If decimation factor is 1, just pass the data through */
+assign Data_o       = (DecimFactor_i <= 1) ? Data_i     :   decimDataReg;
+assign DataVal_o    = (DecimFactor_i <= 1) ? DataVal_i  :   decimDataValReg;
 
 //================================================================================
 //								CODING

+ 7 - 5
src/src/FftDataFiltering/TestCicFilter/CicFilterNewWrapperNoIntDiff.sv

@@ -1,12 +1,13 @@
 module CicFilterNewWrapperNoIntDiff #(
     parameter InDataWidth = 14,
-    parameter N = 6, // Number of stages
-    parameter M = 4, // Differential delay
-    parameter OutDataWidth = 17
+    parameter N             = 6, // Number of stages
+    parameter M             = 4, // Differential delay
+    parameter DECIM_WIDTH   = 4, // Decimation factor width
+    parameter OutDataWidth  = 17
 )
 (
     input logic 								    Clk_i,
-    input logic 			[2:0]                   DecimFactor_i, // Decimation factor (1, 2, 4, 8)
+    input logic 			[DECIM_WIDTH-1:0]       DecimFactor_i, // Decimation factor (1, 2, 4, 8)
 	input logic                     			    Rst_i,
 
     input logic                     			    DataVal_i,
@@ -70,7 +71,8 @@ endgenerate
 
 /* Decimation */
 CicDecimator #(
-    .InDataWidth			(OutDataWidth)
+    .InDataWidth			(OutDataWidth),
+    .DECIM_WIDTH			(DECIM_WIDTH)
 ) decimator_inst (
     .Clk_i          		(Clk_i),
     .Rst_i          		(Rst_i),

+ 74 - 0
src/src/FirFilter/CoeffsR2pkg.sv

@@ -0,0 +1,74 @@
+package CoeffsR2pkg;
+
+// localparam signed [15:0] COEFFS[32] = '{
+//     16'shFFFD, // -1.321922e-02
+//     16'sh0007, //  6.792858e-02
+//     16'shFFEB, // -1.293875e-01
+//     16'shFFF6, // -6.335347e-02
+//     16'sh0066, //  7.969766e-01
+//     16'shFEFA, // -1.025350e+00
+//     16'shFDDE, // -2.195201e+00
+//     16'sh0742, //  7.051171e+00
+//     16'sh0803, //  8.034728e+00
+//     16'shAA44, // -8.737157e+01
+//     16'sh0FDE, //  2.522708e+02
+//     16'sh9D13, // -4.038411e+02
+//     16'sh0F9C, //  2.497294e+02
+//     16'sh25BC, //  6.051987e+02
+//     16'sh70DC, // -2.283021e+03
+//     16'sh5BAE, //  3.510809e+03
+//     16'sh5BAE, //  3.510809e+03
+//     16'sh70DC, // -2.283021e+03
+//     16'sh25BC, //  6.051987e+02
+//     16'sh0F9C, //  2.497294e+02
+//     16'sh9D13, // -4.038411e+02
+//     16'sh0FDE, //  2.522708e+02
+//     16'shAA44, // -8.737157e+01
+//     16'sh0803, //  8.034728e+00
+//     16'sh0742, //  7.051171e+00
+//     16'shFDDE, // -2.195201e+00
+//     16'shFEFA, // -1.025350e+00
+//     16'sh0066, //  7.969766e-01
+//     16'shFFF6, // -6.335347e-02
+//     16'shFFEB, // -1.293875e-01
+//     16'sh0007, //  6.792858e-02
+//     16'shFFFD  // -1.321922e-02
+// };
+
+localparam signed [15:0] COEFFS[32] = '{
+    16'sh0000,
+    16'shFFFC,
+    16'sh0017,
+    16'sh000E,
+    16'shFEF0,
+    16'sh018B,
+    16'sh035D,
+    16'shF5D9,
+    16'shF8D9,
+    16'sh3B1C,
+    16'shC34C,
+    16'sh9B0F,
+    16'sh7FFF,
+    16'sh7FFF,
+    16'sh8000,
+    16'sh7FFF,
+    16'sh7FFF,
+    16'sh8000,
+    16'sh7FFF,
+    16'sh7FFF,
+    16'sh9B0F,
+    16'shC34C,
+    16'sh3B1C,
+    16'shF8D9,
+    16'shF5D9,
+    16'sh035D,
+    16'sh018B,
+    16'shFEF0,
+    16'sh000E,
+    16'sh0017,
+    16'shFFFC,
+    16'sh0000
+};
+
+
+endpackage

+ 74 - 0
src/src/FirFilter/CoeffsR4pkg.sv

@@ -0,0 +1,74 @@
+package CoeffsR4pkg;
+
+// localparam signed [15:0] COEFFS[32] = '{
+//     16'shFFFD, // -1.321922e-02
+//     16'sh0007, //  6.792858e-02
+//     16'shFFEB, // -1.293875e-01
+//     16'shFFF6, // -6.335347e-02
+//     16'sh0066, //  7.969766e-01
+//     16'shFEFA, // -1.025350e+00
+//     16'shFDDE, // -2.195201e+00
+//     16'sh0742, //  7.051171e+00
+//     16'sh0803, //  8.034728e+00
+//     16'shAA44, // -8.737157e+01
+//     16'sh0FDE, //  2.522708e+02
+//     16'sh9D13, // -4.038411e+02
+//     16'sh0F9C, //  2.497294e+02
+//     16'sh25BC, //  6.051987e+02
+//     16'sh70DC, // -2.283021e+03
+//     16'sh5BAE, //  3.510809e+03
+//     16'sh5BAE, //  3.510809e+03
+//     16'sh70DC, // -2.283021e+03
+//     16'sh25BC, //  6.051987e+02
+//     16'sh0F9C, //  2.497294e+02
+//     16'sh9D13, // -4.038411e+02
+//     16'sh0FDE, //  2.522708e+02
+//     16'shAA44, // -8.737157e+01
+//     16'sh0803, //  8.034728e+00
+//     16'sh0742, //  7.051171e+00
+//     16'shFDDE, // -2.195201e+00
+//     16'shFEFA, // -1.025350e+00
+//     16'sh0066, //  7.969766e-01
+//     16'shFFF6, // -6.335347e-02
+//     16'shFFEB, // -1.293875e-01
+//     16'sh0007, //  6.792858e-02
+//     16'shFFFD  // -1.321922e-02
+// };
+
+localparam signed [15:0] COEFFS[32] = '{
+    16'sh0000,
+    16'shFFFC,
+    16'sh0017,
+    16'sh000E,
+    16'shFEF0,
+    16'sh018B,
+    16'sh035D,
+    16'shF5D9,
+    16'shF8D9,
+    16'sh3B1C,
+    16'shC34C,
+    16'sh9B0F,
+    16'sh7FFF,
+    16'sh7FFF,
+    16'sh8000,
+    16'sh7FFF,
+    16'sh7FFF,
+    16'sh8000,
+    16'sh7FFF,
+    16'sh7FFF,
+    16'sh9B0F,
+    16'shC34C,
+    16'sh3B1C,
+    16'shF8D9,
+    16'shF5D9,
+    16'sh035D,
+    16'sh018B,
+    16'shFEF0,
+    16'sh000E,
+    16'sh0017,
+    16'shFFFC,
+    16'sh0000
+};
+
+
+endpackage

+ 39 - 0
src/src/FirFilter/CoeffsR8pkg.sv

@@ -0,0 +1,39 @@
+package CoeffsR8pkg;
+
+localparam signed [15:0] COEFFS[32] = '{
+    16'shFFFD, // -1.321922e-02
+    16'sh0007, //  6.792858e-02
+    16'shFFEB, // -1.293875e-01
+    16'shFFF6, // -6.335347e-02
+    16'sh0066, //  7.969766e-01
+    16'shFEFA, // -1.025350e+00
+    16'shFDDE, // -2.195201e+00
+    16'sh0742, //  7.051171e+00
+    16'sh0803, //  8.034728e+00
+    16'shAA44, // -8.737157e+01
+    16'h0FDE, //  2.522708e+02
+    16'h9D13, // -4.038411e+02
+    16'h0F9C, //  2.497294e+02
+    16'h25BC, //  6.051987e+02
+    16'h70DC, // -2.283021e+03
+    16'h5BAE, //  3.510809e+03
+    16'h5BAE, //  3.510809e+03
+    16'h70DC, // -2.283021e+03
+    16'h25BC, //  6.051987e+02
+    16'h0F9C, //  2.497294e+02
+    16'h9D13, // -4.038411e+02
+    16'h0FDE, //  2.522708e+02
+    16'hAA44, // -8.737157e+01
+    16'h0803, //  8.034728e+00
+    16'h0742, //  7.051171e+00
+    16'hFDDE, // -2.195201e+00
+    16'hFEFA, // -1.025350e+00
+    16'h0066, //  7.969766e-01
+    16'hFFF6, // -6.335347e-02
+    16'hFFEB, // -1.293875e-01
+    16'h0007, //  6.792858e-02
+    16'hFFFD  // -1.321922e-02
+};
+
+
+endpackage

+ 172 - 0
src/src/FirFilter/FirFilter.sv

@@ -0,0 +1,172 @@
+import CoeffsR2pkg::*;
+import CoeffsR4pkg::*;
+import CoeffsR8pkg::*;
+module FirFilter #(
+    parameter DATA_WIDTH = 16,
+    parameter COEFF_WIDTH = 16,
+    parameter NUM_TAPS = 32,
+    parameter RESULT_WIDTH = DATA_WIDTH + COEFF_WIDTH + $clog2(NUM_TAPS) - 1
+)
+(
+    input logic                     Clk_i,
+    input logic                     Rst_i,
+    input logic [3:0]               DecimFactor_i,               
+    input logic [DATA_WIDTH-1:0]    Data_i,
+    input logic                     Val_i,
+
+    output logic [RESULT_WIDTH-1:0] Data_o,
+    output logic                    Val_o
+);
+//================================================================================
+//								REG/WIRE
+//================================================================================
+logic signed [DATA_WIDTH-1:0]   shiftReg        [0:NUM_TAPS-1];
+/* MAC */
+logic signed [RESULT_WIDTH-1:0] macResult;
+/* Coeffs */
+logic signed [COEFF_WIDTH-1:0]  coeffs          [0:NUM_TAPS - 1];
+
+/* Phase Counter */
+logic        [$clog2(8)-1:0]    phaseCounter;
+
+/* 2 Cycle Val_i */
+logic                           val2Cycle;
+
+/* Delayed Val_i and Data_i */
+logic signed [DATA_WIDTH-1:0]   delayedData;
+logic                           delayedVal;
+logic                           delayedValR;
+//================================================================================
+//								ASSIGNMENTS
+//================================================================================
+assign Data_o = macResult;
+//================================================================================
+//								CODING
+//================================================================================
+/* Delayed Data_i */
+always_ff @(posedge Clk_i) begin 
+    if (Rst_i) begin 
+        delayedData <= '0;
+        delayedVal <= 1'b0;
+    end
+    else begin 
+        if (Val_i) begin
+            delayedData <= Data_i;
+            delayedVal <= Val_i;
+        end
+        else begin 
+            delayedData <= delayedData;
+            delayedVal <= 1'b0;
+        end
+    end
+end
+
+// MAC-операция, разделенная на два такта
+always_ff @(posedge Clk_i) begin 
+    if (Rst_i) begin
+        macResult <= '0;
+    end
+    else begin 
+        if (val2Cycle) begin
+            if (phaseCounter == 0) begin
+                macResult <= '0;
+                /* Первая четверть коэффициентов */
+                for (int j = 0; j < NUM_TAPS/4; j++) begin
+                    logic signed [DATA_WIDTH:0] symSum;
+                    symSum = shiftReg[j] + shiftReg[NUM_TAPS-1-j];
+                    macResult += symSum * coeffs[j];
+                end
+            end
+            else begin
+                /* Вторая четверть коэффициентов */
+                for (int j = NUM_TAPS/4; j < NUM_TAPS/2; j++) begin
+                    logic signed [DATA_WIDTH:0] symSum;
+                    symSum = shiftReg[j] + shiftReg[NUM_TAPS-1-j];
+                    macResult += symSum * coeffs[j];
+                end
+                /* Если количество коэффициентов нечетное, добавляем остальные коэффициенты */
+                if (NUM_TAPS % 2 == 1) begin
+                    macResult += shiftReg[NUM_TAPS/2] * coeffs[NUM_TAPS/2];
+                end
+            end
+        end
+    end
+end
+
+/* Shift Register */
+always_ff @(posedge Clk_i) begin 
+    if (Rst_i) begin 
+        shiftReg <= '{default : '0};
+    end
+    else begin 
+        if (delayedVal) begin
+            for (int i = 1; i < NUM_TAPS; i++) begin
+                shiftReg[i] <= shiftReg[i-1];
+            end
+            shiftReg[0] <= delayedData;
+        end
+    end
+end
+
+/* Prolong Val_i for two cycles */
+always_ff @(posedge Clk_i) begin 
+    if (Rst_i) begin 
+        val2Cycle <= 1'b0;
+    end
+    else begin 
+        if (Val_i) begin
+            val2Cycle <= 1'b1;
+        end
+        else if (phaseCounter == 1) begin 
+            val2Cycle <= 1'b0;
+        end
+    end
+end
+
+/* Phase Counter */
+always_ff @(posedge Clk_i) begin 
+    if (Rst_i) begin 
+        phaseCounter <= '0;
+    end
+    else begin 
+        if (val2Cycle) begin 
+            if (phaseCounter == 1) begin 
+                phaseCounter <= '0;
+            end
+            else begin 
+                phaseCounter <= phaseCounter + 1;
+            end
+        end
+    end
+end
+
+always_ff @(posedge Clk_i) begin 
+    if (Rst_i) begin 
+        delayedValR <= 1'b0;
+    end
+    else begin 
+        delayedValR <= delayedVal;
+    end
+end
+
+/* Val_o */
+always_ff @(posedge Clk_i) begin 
+    if (Rst_i) begin 
+        Val_o <= 1'b0;
+    end
+    else begin 
+        Val_o <= delayedValR;
+    end
+end
+
+/* Choose the right set of coeffs */
+always_comb begin
+    case (DecimFactor_i) 
+        2: coeffs = CoeffsR2pkg::COEFFS;
+        4: coeffs = CoeffsR4pkg::COEFFS;
+        8: coeffs = CoeffsR8pkg::COEFFS;
+        default: coeffs = '{default:'0}; 
+    endcase
+end
+        
+endmodule

+ 512 - 0
src/src/Sim/AfterFir.txt

@@ -0,0 +1,512 @@
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+     -16479
+      28159
+     421517
+     844246
+     781469
+     318354
+    -634122
+    -467959
+    4309982
+   14548922
+   29928013
+   49055434
+   66076865
+   77960175
+   84344085
+   82099693
+   72563535
+   58197977
+   39374074
+   21512941
+    8818258
+    1219862
+    -980959
+     -92074
+     608130
+     835837
+     693118
+     193445
+     -34305
+      -1831
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0

+ 129 - 11
src/src/Sim/DecimFilterWrapperTb.v

@@ -6,13 +6,15 @@ module DecimFilterWrapperTb	();
 //	PARAMETERS
 //================================================================================
 
-parameter	N	=   6; // Order of the filter
-parameter	M	=	8;// Delay in CIC filter
+parameter	N	=   4; // Order of the filter
+parameter	M	=	4;// Delay in CIC filter
 parameter	InDataWidth	=	14;
+parameter	integer DECIM_WIDTH	=	$ceil($clog2(2*M)) + 4; // Decimation factor width
 
 parameter	K = N*20*($log10(M));
 parameter	BitGworth = $ceil(2**(K/20));
-parameter	integer MaxWidth = InDataWidth+BitGworth + 15;
+parameter	integer BitGrowth = $ceil($clog2(((M/2*M)**N)/(M/2)));
+parameter	integer MaxWidth = InDataWidth+BitGrowth+5;
 
 // parameter	[31:0]	Nco1PhaseInc	=	32'h40000000;//12.5 MHz 
 parameter	[31:0]	Nco1PhaseInc	=	32'h23d70a3d;//7 MHz 
@@ -28,11 +30,11 @@ parameter	[31:0]	Nco2PhaseInc	=	32'h0f5c28f6;// 3 MHz
 reg		Clk50;
 reg		Rst;
 
-reg		[2:0]	decimFactor;
+reg		[DECIM_WIDTH-1:0]	decimFactor;
 
 reg		[31:0]	tbCnt;
 
-wire	oscWind	=	(tbCnt>=100&tbCnt<=299)?	1'b1:1'b0;
+wire	oscWind	=	(tbCnt>=100&tbCnt<=(1123 + 1024*1))?1'b1:1'b0;
 
 wire	resultVal;
 wire	impResponseVal;
@@ -43,7 +45,10 @@ wire	signed	[InDataWidth-1:0]	ncoSin2;
 wire	signed	[InDataWidth-1:0]	ncoSin3;
 
 wire	signed	[MaxWidth-1:0]		filteredDataOut;
+logic 	signed	[MaxWidth-1:0]		firDataOut;
 wire	signed	[MaxWidth-1:0]		impResponse;
+wire 	signed	[31:0]				impResp32;
+assign 	impResp32 = impResponse[53:53-32]; // Cut to 32 bits
 
 wire	signed	[InDataWidth*2-1:0]	adcDataMixed	=	(ncoSin1*ncoSin2);
 wire	signed	[InDataWidth-1:0]	adcDataMixedCut	=	adcDataMixed[26-:14];
@@ -54,7 +59,34 @@ wire	signed	[InDataWidth-1:0]	sinMult =	sinMultFull[(2*InDataWidth-1)-:InDataWid
 
 wire	signed	[InDataWidth-1:0]	singlePulse	=	(tbCnt==100)?	14'h1fff:14'h0;
 
-integer inSignal,filteredData, impResp;
+// wire signed [(MaxWidth < 32 ? MaxWidth : InDataWidth+18)-1:0] impRespCut;
+// assign impRespCut = MaxWidth < 32 ? impResponse : 
+//                                    impResponse[MaxWidth-1:MaxWidth-(InDataWidth+18)];
+wire signed [InDataWidth -1 : 0] impRespCut = impResponse [MaxWidth-1:MaxWidth-InDataWidth];
+
+longint inSignal,filteredData, impResp, afterFir;
+
+/* 2nd CIC */
+wire signed [2*MaxWidth-1:0] impResponse2nd;
+
+// wire signed [(MaxWidth < 32 ? MaxWidth : InDataWidth+18)-1:0] impResp2ndCut;
+// assign impResp2ndCut = MaxWidth < 32 ? impResponse2nd : 
+//                                    impResponse2nd[MaxWidth-1:MaxWidth-(InDataWidth+18)];
+wire signed [31:0] impResp2ndCut = impResponse2nd [39:39-32]; // 32 bits for 2nd stage
+// wire signed [InDataWidth -1 : 0] impResp2ndCut = impResponse2nd [MaxWidth-1:MaxWidth-InDataWidth];
+wire impResp2ndVal;
+
+/* 3rd CIC */
+wire signed [MaxWidth-1:0] impResponse3rd;
+
+wire signed [(MaxWidth < 32 ? MaxWidth : InDataWidth+18)-1:0] impResp3rdCut;
+assign impResp3rdCut = MaxWidth < 32 ? impResponse3rd : 
+                                   impResponse3rd[MaxWidth-1:MaxWidth-(InDataWidth+18)];
+wire impResp3rdVal;
+
+/* FIR Filt */
+wire signed [31:0] firFiltTestData;
+wire 					firFiltVal;  
 
 //================================================================================
 //	CLK GEN
@@ -84,7 +116,7 @@ end
 always	@(posedge	Clk50)	begin
 	if	(!Rst)	begin
 		if (tbCnt == 100) begin
-			decimFactor	<= 4;
+			decimFactor	<= M/1;
 		end
 		// end else if (tbCnt == 5400) begin
 			// decimFactor	<= 1;
@@ -102,7 +134,7 @@ always	@(posedge	Clk50)	begin
 			// decimFactor	<= 7;
 		// end
 	end else begin
-	 decimFactor <= 4;
+	 decimFactor <= M/1; // 
 	end 
 end
 
@@ -153,7 +185,8 @@ CicFilterNewWrapperNoIntDiff
 	.InDataWidth	(InDataWidth),
 	.N	(N),
 	.M	(M),
-	.OutDataWidth	(MaxWidth)
+	.DECIM_WIDTH	(DECIM_WIDTH),
+	.OutDataWidth	(MaxWidth+20)
 )
 DecimFilter
 (
@@ -173,6 +206,7 @@ CicFilterNewWrapperNoIntDiff
 	.InDataWidth	(InDataWidth),
 	.N	(N),
 	.M	(M),
+	.DECIM_WIDTH	(DECIM_WIDTH),
 	.OutDataWidth	(MaxWidth)
 )
 ImpulseResponseFilter
@@ -188,6 +222,65 @@ ImpulseResponseFilter
 	.DataVal_o		(impResponseVal)
 );
 
+CicFilterNewWrapperNoIntDiff	
+#(
+	.InDataWidth	(MaxWidth),
+	.N	(N),
+	.M	(M),
+	.DECIM_WIDTH	(DECIM_WIDTH),
+	.OutDataWidth	(2*MaxWidth)
+)
+ImpulseResponseFilter2ndStage
+(
+	.Clk_i			(Clk50),
+	.DecimFactor_i	(decimFactor),
+	.Rst_i			(Rst),
+	.DataVal_i		(impResponseVal),
+
+	.Data_i			(impResponse),
+	
+	.Data_o			(impResponse2nd),
+	.DataVal_o		(impResp2ndVal)
+);
+
+// CicFilterNewWrapperNoIntDiff	
+// #(
+// 	.InDataWidth	(InDataWidth),
+// 	.N	(N),
+// 	.M	(M),
+// 	.DECIM_WIDTH	(DECIM_WIDTH),
+// 	.OutDataWidth	(MaxWidth)
+// )
+// ImpulseResponseFilter3rdStage
+// (
+// 	.Clk_i			(Clk50),
+// 	.DecimFactor_i	(decimFactor),
+// 	.Rst_i			(Rst),
+// 	.DataVal_i		(impResp2ndVal),
+
+// 	.Data_i			(impResp2ndCut),
+
+// 	.Data_o			(impResponse3rd),
+// 	.DataVal_o		(impResp3rdVal)
+// );
+
+FirFilter #(
+	.DATA_WIDTH 	(16),
+	.COEFF_WIDTH 	(16),
+	.NUM_TAPS		(32)
+)
+FirFiltTest
+(
+	.Clk_i			(Clk50),
+	.Rst_i			(Rst),
+	.DecimFactor_i	(decimFactor),
+	.Data_i			(impResponse[MaxWidth-1:MaxWidth-16]), // 16 bits for FIR filter
+	.Val_i			(impResponseVal),
+
+	.Data_o			(firFiltTestData),
+	.Val_o			(firFiltVal)
+);
+
 CicFilterNewWrapperNoIntDiff
 #(
 	.InDataWidth	(InDataWidth),
@@ -205,6 +298,18 @@ CicFilterInst
 	.Data_o				(),
 	.DataVal_o			()
 );
+
+always_ff @(posedge Clk50) begin
+	if (Rst) begin 
+		firDataOut <= '0;
+	end
+	else begin 
+		if (firFiltVal) begin
+			firDataOut <= firFiltTestData;
+		end
+	end
+end
+
 	
 always	@(posedge	Clk50)	begin
 	if	(tbCnt==32'd1)	begin
@@ -240,13 +345,26 @@ always	@(posedge	Clk50)	begin
 			$fwrite(impResp,"%d\n",   impResponse);
 		end	
 	end
-end 
+end
+
+always @(posedge Clk50) begin 
+	if (tbCnt == 32'd1) begin
+		afterFir  <= $fopen("C:/S5243_FFT_REPO/src/src/Sim/AfterFir.txt","w");
+	end
+	else begin 
+		if (firFiltVal) begin
+			$fwrite(afterFir,"%d\n",   firFiltTestData);
+		end
+	end
+end
+
 
 always @(posedge Clk50) begin
-	if (tbCnt == 32'd1000) begin 
+	if (tbCnt == 32'd1500 + (1024*1)) begin
 		$fclose(inSignal);
 		$fclose(filteredData);
 		$fclose(impResp);
+		$fclose(afterFir);
 		$finish;
 	end
 end

+ 512 - 50
src/src/Sim/FilteredData.txt

@@ -1,50 +1,512 @@
-                 134360
-                2151862
-               12043849
-               41287865
-              108183306
-              240485089
-              476834120
-              867907764
-             1478200296
-             2378782480
-             3632538722
-             5289192107
-             7379143406
-             9898575315
-            12803212041
-            16003478878
-            19351857136
-            22657402578
-            25721380807
-            28341869354
-            30324623273
-            31519546794
-            31829025993
-            31214535370
-            29730112438
-            27505456142
-            24696458040
-            21494999216
-            18119539691
-            14762904617
-            11595819356
-             8765878008
-             6346713166
-             4356035544
-             2801272577
-             1647003314
-              822409860
-              272783678
-              -66585542
-             -274557327
-             -390179550
-             -438893908
-             -463164144
-             -474885280
-             -470418460
-             -470466854
-             -476101743
-             -471325369
-             -469768178
-             -475852480
+      52614
+     340882
+     966072
+    1974220
+    3328546
+    4415334
+    4866590
+    4660596
+    3556237
+    2210656
+    1228213
+     389224
+       8472
+      61972
+     -46207
+    -102056
+      49001
+     -22523
+    -111037
+      36032
+      -2141
+    -117706
+      19697
+      19697
+    -117706
+      -2141
+      36032
+    -111037
+     -22523
+      49001
+    -102056
+     -45801
+      58518
+     -84915
+     -67202
+      59370
+     -67202
+     -84915
+      58518
+     -45801
+    -102056
+      49001
+     -22523
+    -111037
+      36032
+      -2141
+    -117706
+      19697
+      19697
+    -117706
+      -2141
+      36032
+    -111037
+     -22523
+      49001
+    -102056
+     -45801
+      58518
+     -84915
+     -67202
+      59370
+     -67202
+     -84915
+      58518
+     -45801
+    -102056
+      49001
+     -22523
+    -111037
+      36032
+      -2141
+    -117706
+      19697
+      19697
+    -117706
+      -2141
+      36032
+    -111037
+     -22523
+      49001
+    -102056
+     -45801
+      58518
+     -84915
+     -67202
+      59370
+     -67202
+     -84915
+      58518
+     -45801
+    -102056
+      49001
+     -22523
+    -111037
+      36032
+      -2141
+    -117706
+      19697
+      19697
+    -117706
+      -2141
+      36032
+    -111037
+     -22523
+      49001
+    -102056
+     -45801
+      58518
+     -84915
+     -67202
+      59370
+     -67202
+     -84915
+      58518
+     -45801
+    -102056
+      49001
+     -22523
+    -111037
+      36032
+      -2141
+    -117706
+      19697
+      19697
+    -117706
+      -2141
+      36032
+    -111037
+     -22523
+      49001
+    -102056
+     -45801
+      58518
+     -84915
+     -67202
+      59370
+     -67202
+     -84915
+      58518
+     -45801
+    -102056
+      49001
+     -22523
+    -111037
+      36032
+      -2141
+    -117706
+      19697
+      19697
+    -117706
+      -2141
+      36032
+    -111037
+     -22523
+      49001
+    -102056
+     -45801
+      58518
+     -84915
+     -67202
+      59370
+     -67202
+     -84915
+      58518
+     -45801
+    -102056
+      49001
+     -22523
+    -111037
+      36032
+      -2141
+    -117706
+      19697
+      19697
+    -117706
+      -2141
+      36032
+    -111037
+     -22523
+      49001
+    -102056
+     -45801
+      58518
+     -84915
+     -67202
+      59370
+     -67202
+     -84915
+      58518
+     -45801
+    -102056
+      49001
+     -22523
+    -111037
+      36032
+      -2141
+    -117706
+      19697
+      19697
+    -117706
+      -2141
+      36032
+    -111037
+     -22523
+      49001
+    -102056
+     -45801
+      58518
+     -84915
+     -67202
+      59370
+     -67202
+     -84915
+      58518
+     -45801
+    -102056
+      49001
+     -22523
+    -111037
+      36032
+      -2141
+    -117706
+      19697
+      19697
+    -117706
+      -2141
+      36032
+    -111037
+     -22523
+      49001
+    -102056
+     -45801
+      58518
+     -84915
+     -67202
+      59370
+     -67202
+     -84915
+      58518
+     -45801
+    -102056
+      49001
+     -22523
+    -111037
+      36032
+      -2141
+    -117706
+      19697
+      19697
+    -117706
+      -2141
+      36032
+    -111037
+     -22523
+      49001
+    -102056
+     -45801
+      58518
+     -84915
+     -67202
+      59370
+     -67202
+     -84915
+      58518
+     -45801
+    -102056
+      49001
+     -22523
+    -111037
+      36032
+      -2141
+    -117706
+      19697
+      19697
+    -117706
+      -2141
+      36032
+    -111037
+     -22523
+      49001
+    -102056
+     -45801
+      58518
+     -84915
+     -67202
+      59370
+     -67202
+     -84915
+      58518
+     -45801
+    -102056
+      49001
+     -22523
+    -111037
+      36032
+      -2141
+    -117706
+      19697
+      19697
+    -117706
+      -2141
+      36032
+    -111037
+     -22523
+      49001
+    -102056
+     -45801
+      58518
+     -84915
+     -67202
+      59370
+     -67202
+     -84915
+      58518
+     -45801
+    -102056
+      49001
+     -22523
+    -111037
+      36032
+      -2141
+    -117706
+      19697
+      19697
+    -117706
+      -2141
+      36032
+    -111037
+     -22523
+      49001
+    -102056
+     -45801
+      58518
+     -84915
+     -67202
+      59370
+     -67202
+     -84915
+      58518
+     -45801
+    -102056
+      49001
+     -22523
+    -111037
+      36032
+      -2141
+    -117706
+      19697
+      19697
+    -117706
+      -2141
+      36032
+    -111037
+     -22523
+      49001
+    -102056
+     -45801
+      58518
+     -84915
+     -67202
+      59370
+     -67202
+     -84915
+      58518
+     -45801
+    -102056
+      49001
+     -22523
+    -111037
+      36032
+      -2141
+    -117706
+      19697
+      19697
+    -117706
+      -2141
+      36032
+    -111037
+     -22523
+      49001
+    -102056
+     -45801
+      58518
+     -84915
+     -67202
+      59370
+     -67202
+     -84915
+      58518
+     -45801
+    -102056
+      49001
+     -22523
+    -111037
+      36032
+      -2141
+    -117706
+      19697
+      19697
+    -117706
+      -2141
+      36032
+    -111037
+     -22523
+      49001
+    -102056
+     -45801
+      58518
+     -84915
+     -67202
+      59370
+     -67202
+     -84915
+      58518
+     -45801
+    -102056
+      49001
+     -22523
+    -111037
+      36032
+      -2141
+    -117706
+      19697
+      19697
+    -117706
+      -2141
+      36032
+    -111037
+     -22523
+      49001
+    -102056
+     -45801
+      58518
+     -84915
+     -67202
+      59370
+     -67202
+     -84915
+      58518
+     -45801
+    -102056
+      49001
+     -22523
+    -111037
+      36032
+      -2141
+    -117706
+      19697
+      19697
+    -117706
+      -2141
+      36032
+    -111037
+     -22523
+      49001
+    -102056
+     -45801
+      58518
+     -84915
+     -67202
+      59370
+     -67202
+     -84915
+      58518
+     -45801
+    -102056
+      49001
+     -22523
+    -111037
+      36032
+      -2141
+    -117706
+      19697
+      19697
+    -117706
+      -2141
+      36032
+    -111037
+     -22523
+      49001
+    -102056
+     -45801
+      58518
+     -84915
+     -67202
+      59370
+     -67202
+     -84915
+      58518
+     -45801
+    -102056
+      49001
+     -22523
+    -111037
+      36032
+      -2141
+    -117706
+      19697
+      19697
+    -117706
+      -2141
+      36032
+    -111037
+     -22523
+      49001
+    -102056
+     -45801
+      58518
+     -84915
+     -67202
+      59370
+     -67202

+ 32 - 0
src/src/Sim/FirFilt.txt

@@ -0,0 +1,32 @@
+-1.321922e-02
+6.792858e-02
+-1.293875e-01
+-6.335347e-02
+7.969766e-01
+-1.025350e+00
+-2.195201e+00
+7.051171e+00
+8.034728e+00
+-8.737157e+01
+2.522708e+02
+-4.038411e+02
+2.497294e+02
+6.051987e+02
+-2.283021e+03
+3.510809e+03
+3.510809e+03
+-2.283021e+03
+6.051987e+02
+2.497294e+02
+-4.038411e+02
+2.522708e+02
+-8.737157e+01
+8.034728e+00
+7.051171e+00
+-2.195201e+00
+-1.025350e+00
+7.969766e-01
+-6.335347e-02
+-1.293875e-01
+6.792858e-02
+-1.321922e-02

+ 58 - 1
src/src/Sim/FreqDomainCicFilt.py

@@ -84,7 +84,8 @@ def main():
     # plot the frequency response of the CIC filter in dB
     plt.figure(figsize=(10, 6))
     plt.plot(freq_axis[:half_len], 20 * np.log10(np.abs(cic_filter_frequency_response[:half_len])), label='CIC Filter Frequency Response (dB)')
-    plt.title('CIC Filter Frequency Response')
+    # Show the current R   
+    plt.title(f'CIC Filter Frequency Response (R={R})')
     plt.xlabel('Frequency (MHz)')
     plt.ylabel('Magnitude (dB)')
     plt.ylim(-300, 10) 
@@ -93,6 +94,62 @@ def main():
     plt.xlim(0, fs/(2*R*1e6))
     plt.show()
 
+    # fir_filter_impulse_response = read_impulse_response('C:\S5243_FFT_REPO\src\src\Sim\AfterFir.txt')
+    # fir_filter_frequency_response = convert_to_frequency_domain(fir_filter_impulse_response)
+    # # plot the frequency response of the FIR filter in dB
+    # plt.figure(figsize=(10, 6))
+    # plt.plot(freq_axis[:half_len], 20 * np.log10(np.abs(fir_filter_frequency_response[:half_len])), label='FIR Filter Frequency Response (dB)')
+    # plt.title('FIR Filter Frequency Response')
+    # plt.xlabel('Frequency (MHz)')
+    # plt.ylabel('Magnitude (dB)')
+    # plt.ylim(-300, 10)
+    # plt.grid()
+    # plt.legend()
+    # plt.xlim(0, fs/(2*R*1e6))
+    # plt.show()
+
+    fir_comp_resp = read_impulse_response('C:\S5243_FFT_REPO\src\src\Sim\FirFilt.txt')
+    # Plot in time domain
+    plt.figure(figsize=(10, 6))
+    plt.plot(fir_comp_resp, label='FIR Compensator Impulse Response')
+    plt.title('FIR Compensator Impulse Response')
+    plt.xlabel('Sample Index')
+    plt.ylabel('Amplitude')
+    plt.grid()
+    plt.legend()
+    plt.xlim(0, len(fir_comp_resp))
+    plt.show()
+
+    # After FIR time domain
+    after_fir_resp = read_impulse_response('C:\S5243_FFT_REPO\src\src\Sim\AfterFir.txt')
+    plt.figure(figsize=(10, 6))
+    plt.plot(after_fir_resp, label='After FIR Impulse Response')
+    plt.title('After FIR Impulse Response')
+    plt.xlabel('Sample Index')
+    plt.ylabel('Amplitude')
+    plt.grid()
+    plt.legend()
+    plt.xlim(0, len(after_fir_resp))
+    plt.show()
+    # Plot the frequency response of the FIR compensator
+    fir_compensation_response = convert_to_frequency_domain(after_fir_resp)
+    plt.figure(figsize=(10, 6))
+    plt.plot(freq_axis[:half_len], 20 * np.log10(np.abs(fir_compensation_response[:half_len])), label='FIR Compensation Frequency Response (dB)')
+    plt.title('FIR Compensation Frequency Response')
+    plt.xlabel('Frequency (MHz)')
+    plt.ylabel('Magnitude (dB)')
+    plt.ylim(-300, 10)
+    plt.grid()
+    plt.legend()
+    plt.xlim(0, fs/(2*R*1e6))
+    plt.show()
+
+
+    # # FIR compensation filter
+    # Order = 64  # FIR filter order
+    # fir_compensation_response = fir_compensation_filt(cic_filter_frequency_response, Order)
+    # print("FIR compensation filter created successfully.")
+
     
     
 if __name__ == "__main__":

+ 512 - 50
src/src/Sim/ImpResp.txt

@@ -1,50 +1,512 @@
-                 458696
-                6487272
-               35778288
-              126993264
-              348150264
-              805011480
-             1649470816
-             3087941472
-             5386991352
-             8856567896
-            13810812336
-            20526121776
-            29199211272
-            39905175912
-            52555552896
-            66856383616
-            82273156176
-            98051774352
-           113295552992
-           127049093856
-           138382161456
-           146473558896
-           150695003712
-           150695003712
-           146473558896
-           138382161456
-           127049093856
-           113295552992
-            98051774352
-            82273156176
-            66856383616
-            52555552896
-            39905175912
-            29199211272
-            20526121776
-            13810812336
-             8856567896
-             5386991352
-             3087941472
-             1649470816
-              805011480
-              348150264
-              126993264
-               35778288
-                6487272
-                 458696
-                      0
-                      0
-                      0
-                      0
+     163820
+     982920
+    2981524
+    6683856
+   11958860
+   17364920
+   21329364
+   22279520
+   19625636
+   14743800
+    9206684
+    4586960
+    1802020
+     458696
+      32764
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0
+          0

文件差异内容过多而无法显示
+ 1848 - 0
src/src/Sim/InputSignal.txt


+ 35 - 0
src/src/Sim/fir_filter.coe

@@ -0,0 +1,35 @@
+Radix = 10;
+Coefficient_Width = 16;
+Coefdata =
+-3.146938e-03,
+-1.637730e-02,
+9.263435e-02,
+5.488382e-02,
+-1.063949e+00,
+1.545263e+00,
+3.364367e+00,
+-1.015506e+01,
+-7.154154e+00,
+5.911076e+01,
+-6.070495e+01,
+-1.009447e+02,
+2.094813e+02,
+5.751169e+02,
+-3.197977e+03,
+6.421861e+03,
+6.421861e+03,
+-3.197977e+03,
+5.751169e+02,
+2.094813e+02,
+-1.009447e+02,
+-6.070495e+01,
+5.911076e+01,
+-7.154154e+00,
+-1.015506e+01,
+3.364367e+00,
+1.545263e+00,
+-1.063949e+00,
+5.488382e-02,
+9.263435e-02,
+-1.637730e-02,
+-3.146938e-03;

+ 34 - 0
src/src/Sim/fir_filter_signed.coe

@@ -0,0 +1,34 @@
+Radix = 16;
+Coefficient_Width = 16;
+Coefdata =
+0000,
+FFFC,
+0017,
+000E,
+FEF0,
+018B,
+035D,
+F5D9,
+F8D9,
+3B1C,
+C34C,
+9B0F,
+7FFF,
+7FFF,
+8000,
+7FFF,
+7FFF,
+8000,
+7FFF,
+7FFF,
+9B0F,
+C34C,
+3B1C,
+F8D9,
+F5D9,
+035D,
+018B,
+FEF0,
+000E,
+0017,
+FFFC;

+ 95 - 10
src/src/Sim/СicFilter.py

@@ -40,35 +40,94 @@ class CICFilter:
 
         return output_signal
     
-    def get_filter_freq_resp(self, num_points=1024):
+    def cascade_multiple_cic_filters(self, input_signal, num_filters):
+        output_signal = input_signal
+        for _ in range(num_filters):
+            output_signal = self.filter(output_signal)
+        return output_signal
+    
+
+    
+    def get_filter_freq_resp(self, num_points=1024, is_cascade=False, num_filters=1):
         # Подаём дельта-функцию на вход фильтру
         impulse = np.zeros(num_points)
         impulse[0] = 1.0  # Дельта-функция
-        output_signal = self.filter(impulse)
+        if is_cascade:
+            output_signal = self.cascade_multiple_cic_filters(impulse, num_filters)
+        else:
+            output_signal = self.filter(impulse)
         # Вычисляем частотную характеристику с помощью БПФ
         freq_response = np.fft.fft(output_signal, num_points)
         # Нормализуем частотную характеристику
         freq_response /= np.max(np.abs(freq_response))
         # Создаем массив частот
-        freq = np.fft.fftfreq(num_points, d=1/(50e6/self.decimation_factor))
+        if is_cascade:
+            freq = np.fft.fftfreq(num_points, d=1/(50e6/self.decimation_factor * num_filters))
+        else:
+            freq = np.fft.fftfreq(num_points, d=1/(50e6/self.decimation_factor))
         # Возвращаем частоты и амплитуду частотной характеристики
         return freq, np.abs(freq_response)
     
     # # Calculate coefficients for the FIR filter to compensate the CIC frequency response
     # def get_compensation_coefficients(self, cic_freq_response, target_freq_response):
 
+    def calculate_fir_compensator_coeffs(self, cic_freq_response, order, fs=50e6, compensation_factor=0.95):
+        """
+        Synthesizes FIR compensator coefficients for the CIC filter
+        
+        Args:
+            cic_freq_response: frequency response of the CIC filter
+            order: order of the compensator filter
+            fs: sampling frequency in Hz
+            compensation_factor: degree of compensation (0-1)
+        """
+        # Create ideal frequency response for the compensator filter
+        half_len = len(cic_freq_response) // 2
+        desired_response = np.ones(len(cic_freq_response), dtype=complex)
+        
+        # Define passband edge up to which compensation is needed (approximately 0.4*fs/R)
+        passband_edge = int(0.4 * half_len)
+        
+        # Apply compensation only in the passband
+        min_magnitude = 1e-12
+        for i in range(passband_edge):
+            if np.abs(cic_freq_response[i]) > min_magnitude:
+                desired_response[i] = (1.0 / cic_freq_response[i]) ** compensation_factor
+            else:
+                desired_response[i] = (1.0 / min_magnitude) ** compensation_factor
+        
+        # Symmetry for real filter
+        for i in range(1, passband_edge):
+            desired_response[len(cic_freq_response) - i] = np.conj(desired_response[i])
+        
+           # Get impulse response
+        imp_resp = np.real(np.fft.ifft(desired_response))
+
+        # Center and trim to the required length
+        imp_resp = np.roll(imp_resp, -len(imp_resp) // 2)[:order + 1]
+
+        # Apply window function
+        window = np.hamming(len(imp_resp))
+        imp_resp = imp_resp * window
+
+        # Normalize for unity gain
+        imp_resp /= np.sum(imp_resp)
+
+        return imp_resp
+
+
 
 def main():
-    decimation_factor = 4
-    delay = 8
-    order = 6
-    num_samples = 100000
+    decimation_factor = 10
+    delay = 2*decimation_factor
+    order = 4
+    num_samples = 100
     # Input signal - multiplication of a 3 MHz sine and 6 MHz sine
     fs = 50e6  # Sampling frequency
     f1 = 7e6  # Frequency of first sine wave
     f2 = 3e6  # Frequency of second sine wave
     t = np.arange(num_samples) / fs
-    input_signal = np.sin(2 * np.pi * f1 * t) * np.sin(2 * np.pi * f2 * t)
+    input_signal = (np.sin(2 * np.pi * f1 * t) * np.sin(2 * np.pi * f2 * t))
     # Plot the input signal in the frequency domain
     plt.figure(figsize=(10, 6))
     plt.magnitude_spectrum(input_signal, Fs=fs, scale='dB', color='C0')
@@ -81,7 +140,7 @@ def main():
     # Create CIC filter instance
     cic_filter = CICFilter(decimation_factor, delay, order)
     # Filter the input signal
-    output_signal = cic_filter.filter(input_signal)
+    output_signal = cic_filter.cascade_multiple_cic_filters(input_signal, 1)
     # Plot the output signal in the frequency domain
     plt.magnitude_spectrum(output_signal, Fs=fs/decimation_factor, scale='dB', color='C1')
     plt.title('Output Signal in Frequency Domain')
@@ -91,7 +150,7 @@ def main():
     plt.tight_layout()
     plt.show()
     # Get frequency response of the CIC filter
-    freq, freq_response = cic_filter.get_filter_freq_resp()
+    freq, freq_response = cic_filter.get_filter_freq_resp(is_cascade=False, num_filters=1)
     # Plot the frequency response
     plt.figure(figsize=(10, 6))
     # Normalize frequency axis to 1
@@ -104,6 +163,32 @@ def main():
     plt.legend()
     plt.tight_layout()
     plt.show()
+
+    # # Calculate FIR compensator coefficients
+    # fir_coeffs = cic_filter.calculate_fir_compensator_coeffs(freq_response, 64, fs=fs, compensation_factor=0.95)
+
+    # fir_freq_response = np.fft.fft(fir_coeffs, len(freq_response))
+    # plt.figure(figsize=(10, 6))
+    # plt.plot(freq_normalized, 20 * np.log10(np.abs(fir_freq_response[:len(freq)//2])), label='FIR Compensator Frequency Response (Normalized)')
+    # plt.title('FIR Compensator Frequency Response')
+    # plt.xlabel('Frequncy [Hz]')
+    # plt.ylabel('Magnitugde [dB]')
+    # plt.grid()
+    # plt.tight_layout()
+    # plt.show()
+
+    # # Final Response 
+    # final_response = fir_freq_response * freq_response
+    # plt.figure(figsize=(10, 6))
+    # plt.plot(freq_normalized, 20 * np.log10(np.abs(final_response[:len(freq)//2])), label='Final Response (CIC + FIR Compensator)')
+
+    # plt.title('Final Response of CIC Filter with FIR Compensator')
+    # plt.xlabel('Frequency [Hz]')
+    # plt.ylabel('Magnitude [dB]')
+    # plt.grid()
+    # plt.legend()
+    # plt.tight_layout()
+    # plt.show()
     
 if __name__ == "__main__":
     main()