// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2003 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0

module t (/*AUTOARG*/
   // Inputs
   clk
   );

   input clk;

   reg [7:0] cyc; initial cyc = 0;
   reg [7:0] padd;
   reg       dsp_ph1, dsp_ph2, dsp_reset;

   /*AUTOWIRE*/
   // Beginning of automatic wires (for undeclared instantiated-module outputs)
   wire [7:0]           out;                    // From dspchip of t_dspchip.v
   // End of automatics

   t_dspchip dspchip (/*AUTOINST*/
                      // Outputs
                      .out              (out[7:0]),
                      // Inputs
                      .dsp_ph1          (dsp_ph1),
                      .dsp_ph2          (dsp_ph2),
                      .dsp_reset        (dsp_reset),
                      .padd             (padd[7:0]));

   always @ (posedge clk) begin
      $write("cyc %d\n",cyc);
      if (cyc == 8'd0) begin
         cyc <= 8'd1;
         dsp_reset <= 0;        // Need a posedge
         padd <= 0;
      end
      else if (cyc == 8'd20) begin
         $write("*-* All Finished *-*\n");
         $finish;
      end
      else begin
         cyc <= cyc + 8'd1;
         dsp_ph1 <= ((cyc&8'd3) == 8'd0);
         dsp_ph2 <= ((cyc&8'd3) == 8'd2);
         dsp_reset <= (cyc == 8'd1);
         padd <= cyc;
         //$write("[%0t] cyc %d  %x->%x\n", $time, cyc, padd, out);
         case (cyc)
           default: $stop;
           8'd01: ;
           8'd02: ;
           8'd03: ;
           8'd04: ;
           8'd05: ;
           8'd06: ;
           8'd07: ;
           8'd08: ;
           8'd09: if (out!==8'h04) $stop;
           8'd10: if (out!==8'h04) $stop;
           8'd11: if (out!==8'h08) $stop;
           8'd12: if (out!==8'h08) $stop;
           8'd13: if (out!==8'h00) $stop;
           8'd14: if (out!==8'h00) $stop;
           8'd15: if (out!==8'h00) $stop;
           8'd16: if (out!==8'h00) $stop;
           8'd17: if (out!==8'h0c) $stop;
           8'd18: if (out!==8'h0c) $stop;
           8'd19: if (out!==8'h10) $stop;
         endcase
      end
   end

endmodule

module t_dspchip (/*AUTOARG*/
   // Outputs
   out,
   // Inputs
   dsp_ph1, dsp_ph2, dsp_reset, padd
   );
   input dsp_ph1, dsp_ph2, dsp_reset;
   input [7:0] padd;
   output [7:0] out;

   wire         dsp_ph1, dsp_ph2;
   wire [7:0]   out;
   wire         pla_ph1, pla_ph2;
   wire         out1_r;
   wire [7:0]   out2_r, padd;
   wire         clk_en;

   t_dspcore t_dspcore (/*AUTOINST*/
                        // Outputs
                        .out1_r         (out1_r),
                        .pla_ph1        (pla_ph1),
                        .pla_ph2        (pla_ph2),
                        // Inputs
                        .dsp_ph1        (dsp_ph1),
                        .dsp_ph2        (dsp_ph2),
                        .dsp_reset      (dsp_reset),
                        .clk_en         (clk_en));
   t_dsppla t_dsppla (/*AUTOINST*/
                      // Outputs
                      .out2_r           (out2_r[7:0]),
                      // Inputs
                      .pla_ph1          (pla_ph1),
                      .pla_ph2          (pla_ph2),
                      .dsp_reset        (dsp_reset),
                      .padd             (padd[7:0]));

   assign       out = out1_r ? 8'h00 : out2_r;
   assign       clk_en = 1'b1;

endmodule

module t_dspcore (/*AUTOARG*/
   // Outputs
   out1_r, pla_ph1, pla_ph2,
   // Inputs
   dsp_ph1, dsp_ph2, dsp_reset, clk_en
   );
   input dsp_ph1, dsp_ph2, dsp_reset;
   input clk_en;
   output out1_r, pla_ph1, pla_ph2;

   wire   dsp_ph1, dsp_ph2, dsp_reset;
   wire   pla_ph1, pla_ph2;
   reg    out1_r;

   always @(posedge dsp_ph1 or posedge dsp_reset) begin
      if (dsp_reset)
        out1_r <= 1'h0;
      else
        out1_r <= ~out1_r;
   end

   assign pla_ph1 = dsp_ph1;
   assign pla_ph2 = dsp_ph2 & clk_en;

endmodule

module t_dsppla (/*AUTOARG*/
   // Outputs
   out2_r,
   // Inputs
   pla_ph1, pla_ph2, dsp_reset, padd
   );
   input pla_ph1, pla_ph2, dsp_reset;
   input [7:0] padd;
   output [7:0] out2_r;

   wire         pla_ph1, pla_ph2, dsp_reset;
   wire [7:0]   padd;
   reg [7:0]    out2_r;

   reg [7:0]    latched_r;

   always @(posedge pla_ph1 or posedge dsp_reset) begin
      if (dsp_reset)
        latched_r <= 8'h00;
      else
        latched_r <= padd;
   end

   always @(posedge pla_ph2 or posedge dsp_reset) begin
      if (dsp_reset)
        out2_r <= 8'h00;
      else
        out2_r <= latched_r;
   end

endmodule
