From cbf8ab957e40c9179dccb637a1174f5384091a28 Mon Sep 17 00:00:00 2001 From: thfu <2779155576@qq.com> Date: Wed, 27 Nov 2024 16:35:27 +0800 Subject: [PATCH] v04-using DW_iir_dc_m.v;TB don't use ca_wave --- rtl/z_dsp/DW_iir_dc_m.v | 380 +++++++++++++++++++++++++++++++++++++++ rtl/z_dsp/TailCorr_top.v | 17 +- sim/files.f | 2 + tb/tb_z_dsp_en_Test.v | 168 +++++------------ 4 files changed, 433 insertions(+), 134 deletions(-) create mode 100644 rtl/z_dsp/DW_iir_dc_m.v diff --git a/rtl/z_dsp/DW_iir_dc_m.v b/rtl/z_dsp/DW_iir_dc_m.v new file mode 100644 index 0000000..d0e9540 --- /dev/null +++ b/rtl/z_dsp/DW_iir_dc_m.v @@ -0,0 +1,380 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// This confidential and proprietary software may be used only +// as authorized by a licensing agreement from Synopsys Inc. +// In the event of publication, the following notice is applicable: +// +// (C) COPYRIGHT 1995 - 2018 SYNOPSYS INC. +// ALL RIGHTS RESERVED +// +// The entire notice above must be reproduced on all authorized +// copies. +// +// AUTHOR: KB May 20, 1995 +// +// VERSION: Verilog Simulation Model for DW_iir_dc +// +// DesignWare_version: 10b10551 +// DesignWare_release: O-2018.06-DWBB_201806.1 +// +//////////////////////////////////////////////////////////////////////////////// +//----------------------------------------------------------------------------------- +// +// ABSTRACT: Verilog simulation model for IIR filter with dynamic coefficients +// +// MODIFIED: +// Doug Lee 06/02/2008 +// Fix for STAR#9000245949 +// data_out and saturation results were wrong +// compared to synthetic and VHDL simulation +// models in a specific negative number +// boundary case. Re-wrote rounding/saturation +// function to resemble VHDL simulation model +// approach. +// +// Zhijun (Jerry) Huang 02/12/2004 +// Changed interface names +// Added parameter legality check +// Added asynchronous reset signal rst_n +// Added optional output register controlled by parameter out_reg +// Added X-processing +// Fixed verilog analysis warning about zero multiconcat multiplier +// Fixed verilog analysis error about negative array index +// Fixed logic errors with saturation and negative/positive handling +// Fixed logic errors with feedback_data when feedback_width > data_out_width +// +//----------------------------------------------------------------------------------- + +module DW_iir_dc_m(clk,rst_n,init_n,enable, + A1_coef,A2_coef,B0_coef,B1_coef,B2_coef, + data_in,data_out,saturation); +parameter integer data_in_width = 8; +parameter integer data_out_width = 16; +parameter integer frac_data_out_width = 4; +parameter integer feedback_width = 12; +parameter integer max_coef_width = 8; +parameter integer frac_coef_width = 4; +parameter integer saturation_mode = 0; +parameter integer out_reg = 1; +input clk,rst_n,init_n,enable; +input [max_coef_width-1:0] A1_coef,A2_coef,B0_coef,B1_coef,B2_coef; +input [data_in_width-1:0] data_in; +output [data_out_width-1:0] data_out; +output saturation; + +parameter integer psum_width = (feedback_width-frac_data_out_width > data_in_width)? + feedback_width+max_coef_width+3 + : data_in_width+frac_data_out_width+max_coef_width+3; + + + +function [feedback_width+data_out_width:0] rnd_sat; +input [psum_width-1:0] psum0; + +reg signed [psum_width:0] psum0_shiftedby1; +reg signed [data_out_width-1:0] data_out_noreg; +reg signed [feedback_width-1:0] feedback_data; +reg signed [frac_coef_width:0] round_limit; +reg signed [frac_coef_width-1:0] psum0_frac_part; +reg signed [data_out_width-1:0] max_pos_output; +reg signed [data_out_width-1:0] max_neg_output; +reg signed [feedback_width-1:0] max_pos_feedback; +reg signed [feedback_width-1:0] max_neg_feedback; +reg signed [data_out_width-1:0] output_inc_data; +reg signed [feedback_width-1:0] feedback_inc_data; +reg output_to_big; +reg feedback_to_big; +reg saturation_internal; + +integer i, j, k, l; + +begin + for (i=0; i 0) begin + psum0_shiftedby1 = psum0 << 1; + + // Break out the frac_coef portion of psum0 + for (i=0; i= $signed({max_pos_output, 1'b1})) begin + data_out_noreg = max_pos_output; + output_to_big = 1; + end else begin + if ($signed(psum0_shiftedby1[psum_width:frac_coef_width+1]) < $signed(max_neg_output)) begin + data_out_noreg = max_neg_output; + output_to_big = 1; + end else begin + if (psum0_shiftedby1[frac_coef_width] && + (!psum0_shiftedby1[psum_width] || (($signed(psum0_frac_part)) > $signed(round_limit)))) begin + output_inc_data = psum0[data_out_width+frac_coef_width-1:frac_coef_width] + 1; + data_out_noreg = output_inc_data; + output_to_big = 0; + end else begin + data_out_noreg = psum0[data_out_width+frac_coef_width-1:frac_coef_width]; + output_to_big = 0; + end + end + end + if ($signed(psum0_shiftedby1[psum_width:frac_coef_width]) >= $signed({max_pos_feedback, 1'b1})) begin + feedback_data = max_pos_feedback; + feedback_to_big = 1; + end else begin + if ($signed(psum0_shiftedby1[psum_width:frac_coef_width+1]) < $signed(max_neg_feedback)) begin + feedback_data = max_neg_feedback; + feedback_to_big = 1; + end else begin + if (psum0_shiftedby1[frac_coef_width] && + (!psum0_shiftedby1[psum_width] || (($signed(psum0_frac_part)) > $signed(round_limit)))) begin + feedback_inc_data = psum0[feedback_width+frac_coef_width-1:frac_coef_width] + 1; + feedback_data = feedback_inc_data; + feedback_to_big = 0; + end else begin + feedback_data = psum0[feedback_width+frac_coef_width-1:frac_coef_width]; + feedback_to_big = 0; + end + end + end + end else begin + if ($signed(psum0) > $signed(max_pos_output)) begin + data_out_noreg = max_pos_output; + output_to_big = 1; + end else begin + if ($signed(psum0) < $signed(max_neg_output)) begin + data_out_noreg = max_neg_output; + output_to_big = 1; + end else begin + data_out_noreg = psum0[data_out_width-1:0]; + output_to_big = 0; + end + end + if ($signed(psum0) > $signed(max_pos_feedback)) begin + feedback_data = max_pos_feedback; + feedback_to_big = 1; + end else begin + if ($signed(psum0) < $signed(max_neg_feedback)) begin + feedback_data = max_neg_feedback; + feedback_to_big = 1; + end else begin + feedback_data = psum0[feedback_width-1:0]; + feedback_to_big = 0; + end + end + end + + saturation_internal = output_to_big || feedback_to_big; + + rnd_sat = {saturation_internal, feedback_data, data_out_noreg}; + +end +endfunction + +wire [data_in_width-1:0] gated_data_in; +wire [feedback_width-1:0] feedback_data; +wire [max_coef_width-1:0] A1_coef_wire,A2_coef_wire, + B0_coef_wire,B1_coef_wire,B2_coef_wire; +wire [data_in_width+max_coef_width-1:0] B0_product,B1_product,B2_product; +wire [feedback_width+max_coef_width-1:0] A1_product,A2_product; +wire [psum_width-3:0] psum2; +reg [psum_width-3:0] psum2_saved; +wire [psum_width-1:0] psum1,psum0; +reg [psum_width-1:0] psum1_saved; +wire [data_out_width-1:0] data_out_internal; +wire saturation_internal; +reg [data_out_width-1:0] data_out_reg; +reg saturation_reg; + +assign A1_coef_wire = A1_coef; +assign A2_coef_wire = A2_coef; +assign B0_coef_wire = B0_coef; +assign B1_coef_wire = B1_coef; +assign B2_coef_wire = B2_coef; +assign gated_data_in = (init_n == 1'b0) ? {data_in_width{1'b0}} : data_in; + + +DW02_mult #(data_in_width,max_coef_width) B0_mult(gated_data_in,B0_coef_wire,1'b1,B0_product); + +DW02_mult #(feedback_width,max_coef_width) A1_mult(feedback_data,A1_coef_wire,1'b1,A1_product); + + +assign psum1 = {{psum_width{A1_product[feedback_width+max_coef_width-1]}}, + A1_product[feedback_width+max_coef_width-2:0]}; + +assign psum0 = ({{psum_width{B0_product[data_in_width+max_coef_width-1]}}, + B0_product[data_in_width+max_coef_width-2:0]} << frac_data_out_width) + + psum1_saved; + +assign {saturation_internal,feedback_data,data_out_internal} = rnd_sat(psum0); + +always @ (posedge clk or negedge rst_n) + if (rst_n == 1'b0) begin + psum1_saved <= {psum_width{1'b0}}; + data_out_reg <= {data_out_width{1'b0}}; + saturation_reg <= 1'b0; + end + else begin + + if (init_n == 1'b0) + psum1_saved <= {psum_width{1'b0}}; + else if (enable == 1'b1) + psum1_saved <= psum1; + else + psum1_saved <= psum1_saved; + + if (init_n == 1'b0) begin + data_out_reg <= {data_out_width{1'b0}}; + saturation_reg <= 1'b0; + end + else if (enable == 1'b1) begin + data_out_reg <= data_out_internal; + saturation_reg <= saturation_internal; + end + else begin + data_out_reg <= data_out_reg; + saturation_reg <= saturation_reg; + end + end + +assign data_out = (out_reg == 0) ? data_out_internal : data_out_reg; +assign saturation = (out_reg == 0) ? saturation_internal : saturation_reg; + +// synopsys translate_off +//------------------------------------------------------------------------- +// Parameter legality check +//------------------------------------------------------------------------- + + + + initial begin : parameter_check + integer param_err_flg; + + param_err_flg = 0; + + + if (data_in_width < 2) begin + param_err_flg = 1; + $display( + "ERROR: %m :\n Invalid value (%d) for parameter data_in_width (lower bound: 2)", + data_in_width ); + end + + if ( (data_out_width < 2) || (data_out_width > psum_width-frac_coef_width) ) begin + param_err_flg = 1; + $display( + "ERROR: %m :\n Invalid value (%d) for parameter data_out_width (legal range: 2 to psum_width-frac_coef_width)", + data_out_width ); + end + + if ( (frac_data_out_width < 0) || (frac_data_out_width > data_out_width-1) ) begin + param_err_flg = 1; + $display( + "ERROR: %m :\n Invalid value (%d) for parameter frac_data_out_width (legal range: 0 to data_out_width-1)", + frac_data_out_width ); + end + + if (feedback_width < 2) begin + param_err_flg = 1; + $display( + "ERROR: %m :\n Invalid value (%d) for parameter feedback_width (lower bound: 2)", + feedback_width ); + end + + if (max_coef_width < 2) begin + param_err_flg = 1; + $display( + "ERROR: %m :\n Invalid value (%d) for parameter max_coef_width (lower bound: 2)", + max_coef_width ); + end + + if ( (frac_coef_width < 0) || (frac_coef_width > max_coef_width-1) ) begin + param_err_flg = 1; + $display( + "ERROR: %m :\n Invalid value (%d) for parameter frac_coef_width (legal range: 0 to max_coef_width-1)", + frac_coef_width ); + end + + if ( (saturation_mode < 0) || (saturation_mode > 1) ) begin + param_err_flg = 1; + $display( + "ERROR: %m :\n Invalid value (%d) for parameter saturation_mode (legal range: 0 to 1)", + saturation_mode ); + end + + if ( (out_reg < 0) || (out_reg > 1) ) begin + param_err_flg = 1; + $display( + "ERROR: %m :\n Invalid value (%d) for parameter out_reg (legal range: 0 to 1)", + out_reg ); + end + + if ( param_err_flg == 1) begin + $display( + "%m :\n Simulation aborted due to invalid parameter value(s)"); + $finish; + end + + end // parameter_check + + +//--------------------------------------------------------------------------- +// Report unknown clock inputs +//--------------------------------------------------------------------------- + + always @ (clk) begin : clk_monitor + if ( (clk !== 1'b0) && (clk !== 1'b1) && ($time > 0) ) + $display( "WARNING: %m :\n at time = %t, detected unknown value, %b, on clk input.", + $time, clk ); + end // clk_monitor + +// synopsys translate_on +endmodule + diff --git a/rtl/z_dsp/TailCorr_top.v b/rtl/z_dsp/TailCorr_top.v index 845b04e..b469746 100644 --- a/rtl/z_dsp/TailCorr_top.v +++ b/rtl/z_dsp/TailCorr_top.v @@ -92,6 +92,7 @@ wire signed [data_out_width-1:0] dout_4; wire signed [data_out_width-1:0] dout_5; wire signed [18:0] Ysum; + reg signed [15:0] dout_r; diff inst_diffRe @@ -112,7 +113,7 @@ diff inst_diffIm .dout (IIRin_im ) ); -DW_iir_dc +DW_iir_dc_m #( .data_in_width (data_in_width ), .data_out_width (data_out_width ), @@ -139,7 +140,7 @@ inst_iir_0 .saturation (saturation_0 ) ); -DW_iir_dc +DW_iir_dc_m #( .data_in_width (data_in_width ), .data_out_width (data_out_width ), @@ -166,7 +167,7 @@ inst_iir_1 .saturation (saturation_1 ) ); -DW_iir_dc +DW_iir_dc_m #( .data_in_width (data_in_width ), .data_out_width (data_out_width ), @@ -193,7 +194,7 @@ inst_iir_2 .saturation (saturation_2 ) ); -DW_iir_dc +DW_iir_dc_m #( .data_in_width (data_in_width ), .data_out_width (data_out_width ), @@ -220,7 +221,7 @@ inst_iir_3 .saturation (saturation_3 ) ); -DW_iir_dc +DW_iir_dc_m #( .data_in_width (data_in_width ), .data_out_width (data_out_width ), @@ -247,7 +248,7 @@ inst_iir_4 .saturation (saturation_4 ) ); -DW_iir_dc +DW_iir_dc_m #( .data_in_width (data_in_width ), .data_out_width (data_out_width ), @@ -448,6 +449,7 @@ reg signed [15:0] din_r1; reg signed [15:0] din_r2; reg signed [15:0] din_r3; reg signed [15:0] din_r4; +reg signed [15:0] din_r5; always @(posedge clk or negedge rstn) if (!rstn) @@ -457,6 +459,7 @@ always @(posedge clk or negedge rstn) din_r2 <= 'h0; din_r3 <= 'h0; din_r4 <= 'h0; + din_r5 <= 'h0; end else if(en) begin @@ -465,6 +468,7 @@ always @(posedge clk or negedge rstn) din_r2 <= din_r1; din_r3 <= din_r2; din_r4 <= din_r3; + din_r5 <= din_r4; end else begin @@ -473,6 +477,7 @@ always @(posedge clk or negedge rstn) din_r2 <= din_r2; din_r3 <= din_r3; din_r4 <= din_r4; + din_r5 <= din_r5; end assign Ysum = din_r4 + dout_cut0_r0 + dout_cut1_r0 + dout_cut2_r0 + dout_cut3_r0 + dout_cut4_r0 + dout_cut5_r0; diff --git a/sim/files.f b/sim/files.f index 7669144..4ba3b76 100644 --- a/sim/files.f +++ b/sim/files.f @@ -15,6 +15,8 @@ ../rtl/z_dsp/z_dsp.v ../rtl/z_dsp/MeanIntp_8.v ../rtl/z_dsp/FixRound.v +../rtl/z_dsp/DW_iir_dc_m.v + ../rtl/model/DW02_mult.v ../rtl/model/DW_iir_dc.v ../tb/clk_gen.v diff --git a/tb/tb_z_dsp_en_Test.v b/tb/tb_z_dsp_en_Test.v index 9376c59..1c4d8ac 100644 --- a/tb/tb_z_dsp_en_Test.v +++ b/tb/tb_z_dsp_en_Test.v @@ -54,6 +54,15 @@ reg clk; reg clk_div2; reg clk_div4; +//a_fix is 55007237 +//a_fix is 32690030 +//a_fix is 429516 +//a_fix is 0 +//b_fix is 2143083068 +//b_fix is 2145807236 +//b_fix is 2146812530 +//b_fix is 2147483648 + initial begin #0; @@ -64,29 +73,33 @@ begin en = 1'b0; din_im = 16'd0; - a0_re = 32'd1757225200; - a0_im = 32'd0; - b0_re = -32'd1042856; - b0_im = 32'd0; - a1_re = 32'd1045400392; - a1_im = 32'd0; - b1_re = -32'd1046395; - b1_im = 32'd0; - a2_re = 32'd13740916; - a2_im = 32'd0; - b2_re = -32'd1047703; - b2_im = 32'd0; + + a0_re = 32'd55007237 ; + a1_re = 32'd32690030 ; + a2_re = 32'd429516; a3_re = 32'd0; - a3_im = 32'd0; - b3_re = -32'd0; - b3_im = 32'd0; a4_re = 32'd0; - a4_im = 32'd0; - b4_re = -32'd0; - b4_im = 32'd0; a5_re = 32'd0; + + a0_im = 32'd0; + a1_im = 32'd0; + a2_im = 32'd0; + a3_im = 32'd0; + a4_im = 32'd0; a5_im = 32'd0; + + b0_re = -32'd2143083068; + b1_re = -32'd2145807236; + b2_re = -32'd2146812530; + b3_re = -32'd0; + b4_re = -32'd0; b5_re = -32'd0; + + b0_im = 32'd0; + b1_im = 32'd0; + b2_im = 32'd0; + b3_im = 32'd0; + b4_im = 32'd0; b5_im = 32'd0; fcw = 48'h0840_0000_0000; @@ -558,123 +571,22 @@ always@(*) wire [15:0] diff; assign diff = cs_wave1 - cs_wave; integer signed In_fid; -integer X1_fid; -integer X2_fid; -integer X4_fid; -integer X8_fid; +integer signed OrgOut_fid; initial begin - #0; - In_fid = $fopen("./in.dat"); - case (intp_mode) - 2'b00 : X1_fid = $fopen("./X1_data.dat"); - 2'b01 : X2_fid = $fopen("./X2_data.dat"); - 2'b10 : X4_fid = $fopen("./X4_data.dat"); - 2'b11 : X8_fid = $fopen("./X8_data.dat"); - - endcase + #0; + In_fid = $fopen("./in.dat") ; + OrgOut_fid = $fopen("./OrgOut.dat"); end -always@(posedge clk_div16_f) - if(cnt >= 90) - $fwrite(In_fid,"%d\n",{{{~iir_in[15]}},iir_in[14:0]}); +always@(posedge clk_div32_f) + if(cnt >= 90) begin + $fwrite(In_fid, "%d\n",$signed(TB.inst1_Z_dsp.inst_TailCorr_top.din_re)); + $fwrite(OrgOut_fid,"%d\n",$signed(TB.inst1_Z_dsp.inst_TailCorr_top.dout )); + end -always@(*) - fork - case (intp_mode) - 2'b00 : - begin - @(posedge clk_div16_e) - if(cnt >= 90) - $fwrite(X1_fid,"%d\n",{{{dout_p0[15]}},dout_p0[14:0]}); - end - 2'b01 : - begin - @(posedge clk_div16_e) - if(cnt >= 90) - $fwrite(X2_fid,"%d\n",{{{dout_p0[15]}},dout_p0[14:0]}); - @(posedge clk_div16_6) - if(cnt >= 90) - $fwrite(X2_fid,"%d\n",{{{dout_p1[15]}},dout_p1[14:0]}); - end - 2'b10 : - begin - @(posedge clk_div16_e) - if(cnt >= 90) - $fwrite(X4_fid,"%d\n",{{{dout_p0[15]}},dout_p0[14:0]}); - @(posedge clk_div16_a) - if(cnt >= 90) - $fwrite(X4_fid,"%d\n",{{{dout_p1[15]}},dout_p1[14:0]}); - @(posedge clk_div16_6) - if(cnt >= 90) - $fwrite(X4_fid,"%d\n",{{{dout_p2[15]}},dout_p2[14:0]}); - @(posedge clk_div16_2) - if(cnt >= 90) - $fwrite(X4_fid,"%d\n",{{{dout_p3[15]}},dout_p3[14:0]}); - end - 2'b11 : - begin - @(posedge clk_div32_f) - if(cnt >= 90) - $fwrite(X8_fid,"%d\n",{{{dout_p0[15]}},dout_p0[14:0]}); - @(posedge clk_div32_d) - if(cnt >= 90) - $fwrite(X8_fid,"%d\n",{{{dout_p1[15]}},dout_p1[14:0]}); - @(posedge clk_div32_b) - if(cnt >= 90) - $fwrite(X8_fid,"%d\n",{{{dout_p2[15]}},dout_p2[14:0]}); - @(posedge clk_div32_9) - if(cnt >= 90) - $fwrite(X8_fid,"%d\n",{{{dout_p3[15]}},dout_p3[14:0]}); - @(posedge clk_div32_7) - if(cnt >= 90) - $fwrite(X8_fid,"%d\n",{{{dout_p4[15]}},dout_p4[14:0]}); - @(posedge clk_div32_5) - if(cnt >= 90) - $fwrite(X8_fid,"%d\n",{{{dout_p5[15]}},dout_p5[14:0]}); - @(posedge clk_div32_3) - if(cnt >= 90) - $fwrite(X8_fid,"%d\n",{{{dout_p6[15]}},dout_p6[14:0]}); - @(posedge clk_div32_1) - if(cnt >= 90) - $fwrite(X8_fid,"%d\n",{{{dout_p7[15]}},dout_p7[14:0]}); - - end - - endcase - join - -/* -always@(posedge clk_div16_e) - if(cnt >= 90) - $fwrite(In_fid,"%d\n",{{~{iir_in[15]}},iir_in[14:0]}); - -always@(posedge clk_div16_e) - if(cnt >= 90) - $fwrite(X1_fid,"%d\n",{{~{dout_p3[15]}},dout_p3[14:0]}); - -always@(posedge clk_div16_e) - if(cnt >= 90) - $fwrite(X2_fid,"%d\n",{{~{dout_p1[15]}},dout_p1[14:0]}); -always@(posedge clk_div16_6) - if(cnt >= 90) - $fwrite(X2_fid,"%d\n",{{~{dout_p3[15]}},dout_p3[14:0]}); - -always@(posedge clk_div16_e) - if(cnt >= 90) - $fwrite(X4_fid,"%d\n",{{~{dout_p0[15]}},dout_p0[14:0]}); -always@(posedge clk_div16_a) - if(cnt >= 90) - $fwrite(X4_fid,"%d\n",{{~{dout_p1[15]}},dout_p1[14:0]}); -always@(posedge clk_div16_6) - if(cnt >= 90) - $fwrite(X4_fid,"%d\n",{{~{dout_p2[15]}},dout_p2[14:0]}); -always@(posedge clk_div16_2) - if(cnt >= 90) - $fwrite(X4_fid,"%d\n",{{~{dout_p3[15]}},dout_p3[14:0]}); -*/ endmodule