module TB();

initial
begin
     $fsdbDumpfile("TB.fsdb");
     $fsdbDumpvars(0, TB);
end


reg             clk;
reg             rstn;
reg     [15:0]  din_im; 

reg     [31:0]  a0_re;
reg     [31:0]  a0_im;
reg     [31:0]  b0_re;
reg     [31:0]  b0_im;
reg     [31:0]  a1_re;
reg     [31:0]  a1_im;
reg     [31:0]  b1_re;
reg     [31:0]  b1_im;
reg     [31:0]  a2_re;
reg     [31:0]  a2_im;
reg     [31:0]  b2_re;
reg     [31:0]  b2_im;
reg     [31:0]  a3_re;
reg     [31:0]  a3_im;
reg     [31:0]  b3_re;
reg     [31:0]  b3_im;
reg     [31:0]  a4_re;
reg     [31:0]  a4_im;
reg     [31:0]  b4_re;
reg     [31:0]  b4_im;
reg     [31:0]  a5_re;
reg     [31:0]  a5_im;
reg     [31:0]  b5_re;
reg     [31:0]  b5_im;

reg     [47:0]          fcw;

reg     [21:0]  cnt;
reg     [15:0]  din_imp;
reg     [15:0]  din_rect;
reg     [15:0]  din_cos;
reg     [15:0]  iir_in;

wire    [1 :0]  source_mode;
wire    [15:0]  cos;
wire    [15:0]  sin;
wire    [15:0]  dout_p0;

reg             en;

initial 
begin
                #0;
                rstn    =         1'b0;
                clk     =         1'b0;
                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;
                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;
                a5_im   =        32'd0;
                b5_re   =       -32'd0;
                b5_im   =        32'd0;

                fcw     =       48'h0840_0000_0000;

                din_imp   =      16'd0; 
                din_rect  =      16'd0; 
                din_cos   =      16'd0; 

                #300;
                rstn      =      1'b1;
                #16600300;
//              din_imp   =      16'd30000; 
//              din_rect  =      16'd30000; 
//              en  =   1'b1; 
                #6400;
//              din_imp   =      16'd0; 
                #64000;
//              din_rect  =      16'd0; 

end

always #200 clk = ~clk;

wire            clk_div16_0;
wire            clk_div16_1;
wire            clk_div16_2;
wire            clk_div16_3;
wire            clk_div16_4;
wire            clk_div16_5;
wire            clk_div16_6;
wire            clk_div16_7;
wire            clk_div16_8;
wire            clk_div16_9;
wire            clk_div16_a;
wire            clk_div16_b;
wire            clk_div16_c;
wire            clk_div16_d;
wire            clk_div16_e;
wire            clk_div16_f;


clk_gen inst_clk_gen(
                                        .rstn                   (rstn                           ),
                                        .clk                    (clk                            ),
                                        .clk_div16_0            (clk_div16_0                    ),
                                        .clk_div16_1            (clk_div16_1                    ),
                                        .clk_div16_2            (clk_div16_2                    ),
                                        .clk_div16_3            (clk_div16_3                    ),
                                        .clk_div16_4            (clk_div16_4                    ),
                                        .clk_div16_5            (clk_div16_5                    ),
                                        .clk_div16_6            (clk_div16_6                    ),
                                        .clk_div16_7            (clk_div16_7                    ),
                                        .clk_div16_8            (clk_div16_8                    ),
                                        .clk_div16_9            (clk_div16_9                    ),
                                        .clk_div16_a            (clk_div16_a                    ),
                                        .clk_div16_b            (clk_div16_b                    ),
                                        .clk_div16_c            (clk_div16_c                    ),
                                        .clk_div16_d            (clk_div16_d                    ),
                                        .clk_div16_e            (clk_div16_e                    ),
                                        .clk_div16_f            (clk_div16_f                    ),
                                        .clk_h                  (clk_h                          ),
                                        .clk_l                  (clk_l                          )
                );

always@(posedge clk_div16_f or negedge rstn)
                if(!rstn)
                        cnt     <=      22'd0;
                else
                        cnt     <=      cnt + 22'd1;

initial 
begin
        wait(cnt[16]==1'b1)
                        $finish(0);
end
                  
always@(posedge clk_div16_f or negedge rstn)
                if(!rstn)
                        din_imp <=      22'd0;
                else if(cnt == 100)
                    begin
                        din_imp <=      16'd32767;
                        //en    <=      1'b1;
                    end
                else 
                        din_imp <=      'h0;

always@(posedge clk_div16_f or negedge rstn)
                if(!rstn)
                        din_rect        <=      22'd0;
                else if(cnt >= 100 && cnt <=10100)
                    begin
                        din_rect        <=      16'd30000;
                    end
                else 
                    begin
                        din_rect        <=      16'd0;
                    end

always@(posedge clk_div16_f or negedge rstn)
                if(!rstn)
                        en      <=      22'd0;
                else if(cnt >= 100 )
                    begin
                        en      <=      1'b1;
                    end

always@(posedge clk_div16_f or negedge rstn)
                if(!rstn)
                        begin
                                din_cos   <=    16'd0;
                                iir_in    <=    16'd0;
                        end
                else
                        din_cos   <=    cos;

assign source_mode = 2'b01;

always @(*)

        case(source_mode)
                2'b00 :   iir_in = din_imp;
                2'b01 :   iir_in = din_rect;
                2'b10 :   iir_in = din_cos;
        endcase




NCO     inst_nco_0(
                                .clk                            (clk_div16_f            ),
                                .rstn                           (rstn           ),
                                .phase_manual_clr               (1'b0           ),
                                .phase_auto_clr                 (1'b0           ),
                                .fcw                            (fcw            ),
                                .pha                            (16'd0          ),
                                .cos                            (cos            ),
                                .sin                            (sin            )
                        );


wire    [15:0]  dout_p0;
wire    [15:0]  dout_p1;
wire    [15:0]  dout_p2;
wire    [15:0]  dout_p3;

wire    [1:0]  intp_mode;
assign intp_mode = 2'b10;

wire    [1:0]  dac_mode_sel;
assign dac_mode_sel = 2'b00;

z_dsp           inst_Z_dsp
               (
                        .clk                    (clk_div16_f                    ),
                        .rstn                   (rstn                   ),
                        .en                     (en                     ),
                        .dac_mode_sel           (dac_mode_sel           ),
                        .intp_mode              (intp_mode              ),
                        .din_re                 (iir_in & {16{en}}      ),
                        .din_im                 (din_im                 ),
                        .a0_re                  (a0_re                  ),
                        .a0_im                  (a0_im                  ),
                        .b0_re                  (b0_re                  ),
                        .b0_im                  (b0_im                  ),
                        .a1_re                  (a1_re                  ),
                        .a1_im                  (a1_im                  ),
                        .b1_re                  (b1_re                  ),
                        .b1_im                  (b1_im                  ), 
                        .a2_re                  (a2_re                  ),
                        .a2_im                  (a2_im                  ),
                        .b2_re                  (b2_re                  ),
                        .b2_im                  (b2_im                  ),  
                        .a3_re                  (a3_re                  ),
                        .a3_im                  (a3_im                  ),
                        .b3_re                  (b3_re                  ),
                        .b3_im                  (b3_im                  ),
                        .a4_re                  (a4_re                  ),
                        .a4_im                  (a4_im                  ),
                        .b4_re                  (b4_re                  ),
                        .b4_im                  (b4_im                  ), 
                        .a5_re                  (a5_re                  ),
                        .a5_im                  (a5_im                  ),
                        .b5_re                  (b5_re                  ),
                        .b5_im                  (b5_im                  ),                         
                        .dout0                  (dout_p0                ),
                        .dout1                  (dout_p1                ),
                        .dout2                  (dout_p2                ),
                        .dout3                  (dout_p3                )
                );


reg     [15:0]  cs_wave = 0;

always@(*)
  fork
        case (intp_mode)
        2'b00 : 
                begin
                        @(posedge clk_div16_e)  cs_wave         = dout_p0;
                end
        2'b01 : 
                begin
                        @(posedge clk_div16_e)  cs_wave         = dout_p0;
                        @(posedge clk_div16_6)  cs_wave         = dout_p1;
                end
        2'b10 : 
                begin
                        @(posedge clk_div16_e)  cs_wave         = dout_p0;
                        @(posedge clk_div16_a)  cs_wave         = dout_p1;
                        @(posedge clk_div16_6)  cs_wave         = dout_p2;
                        @(posedge clk_div16_2)  cs_wave         = dout_p3;
                end
        endcase
  join

integer signed In_fid;
integer X1_fid;
integer X2_fid;
integer X4_fid;

initial begin
        #0;
        In_fid  =       $fopen("./in");
        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");
        endcase
end


always@(posedge clk_div16_f)
          if(cnt >= 90)
                $fwrite(In_fid,"%d\n",{{{iir_in[15]}},iir_in[14:0]});


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
        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                                                                               
                                                                                        
                                                                                        

