///////////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------------
//
//  © 2022 Microchip Technology Inc. and its subsidiaries
//  All rights reserved.
//                                                                 
//  ANY USE OR REDISTRIBUTION IN PART OR IN WHOLE MUST BE HANDLED IN
//  ACCORDANCE WITH THE MICROCHIP LICENSE AGREEMENT AND MUST BE APPROVED
//  IN ADVANCE IN WRITING.
//
//-------------------------------------------------------------------------
// Title        : wave_gen16bit.v
// Author       : <Application Team>
// Description  : For 16bit binary wave form generation
// Hierarchy    :
//               hdl           
//					led_block.v   
//					prbs_checker.v    
//					prbs_generator.v     
//					prbs_wav_sel.v
//					reset_synchronizer.v
//					uart_if.v
//					wav_gen_16bit.v         <-- This module
//					err_gen.v       
//  Target device: <Family:PolarFire> <Die:MPF300T> <Pkg:FCG484>   
//
//-------------------------------------------------------------------------


module wave_gen16bit(clk,
                     reset_n,
                     data_out,
                     wave_sel);
  //----------------------------------------------------------------------
  // Inputs
  //-----------------------------------------------------------------------
  input clk; // Clock input, 156.25 MHz
  input reset_n; // Sync reset, active low
  // Wave form selection (0 = sine,1 = square,2 = saw,3 = triangle)
  input[1 : 0] wave_sel; 
  //-----------------------------------------------------------------------
  // Outputs
  //-----------------------------------------------------------------------
  output[63 : 0] data_out; // Waveform output
  //-----------------------------------------------------------------------
  // Internal signals
  //-----------------------------------------------------------------------
  reg[63 : 0] data_out;
  reg[15 : 0] sine_data16;
  reg[15 : 0] sqr_data16;
  reg[15 : 0] saw_data16;
  reg[15 : 0] tri_data16;
  reg[5 : 0] sqr_cnt;
  reg[5 : 0] sine_cnt;
  reg tri_st;
  parameter UP = 0,
            DOWN = 1; // Constants for 16 bit Triangle wave generator
  //data output based on wave form selection
  //
  always
    @(posedge clk or
      negedge reset_n)
    begin
      if (reset_n == 0)
        begin
          data_out <= 64'h0;
        end
      else
        begin
          case (wave_sel)
            2'b00:
              data_out <= {sine_data16, sine_data16, sine_data16, sine_data16};
            2'b01:
              data_out <= { sqr_data16, sqr_data16, sqr_data16, sqr_data16 };
            2'b10:
              data_out <= { saw_data16, saw_data16, saw_data16, saw_data16 };
            2'b11:
              data_out <= { tri_data16, tri_data16, tri_data16, tri_data16 };
            default:
              data_out <= 64'b0;
          endcase
        end
    end
  //sine wave generator
  //
  always
    @(posedge clk or
      negedge reset_n)
    begin
      if (reset_n == 1'b0)
        begin
          sine_cnt <= 6'b0;
        end
      else
        begin
          if (sine_cnt == 6'd47)
            begin
              sine_cnt <= 6'b0;
            end
          else
            begin
              sine_cnt <= sine_cnt + 1'b1;
            end
        end
    end
  //sine data select
  //
  always
    @(sine_cnt)
    begin
      case (sine_cnt)
        6'd0:
          sine_data16 = 16'd32000;
        6'd1:
          sine_data16 = 16'd36080;
        6'd2:
          sine_data16 = 16'd38800;
        6'd3:
          sine_data16 = 16'd42200;
        6'd4:
          sine_data16 = 16'd43560;
        6'd5:
          sine_data16 = 16'd44580;
        6'd6:
          sine_data16 = 16'd45600;
        6'd7:
          sine_data16 = 16'd46960;
        6'd8:
          sine_data16 = 16'd47640;
        6'd9:
          sine_data16 = 16'd47980;
        6'd10:
          sine_data16 = 16'd48520;
        6'd11:
          sine_data16 = 16'd49000;
        6'd12:
          sine_data16 = 16'd49200;
        6'd13:
          sine_data16 = 16'd49000;
        6'd14:
          sine_data16 = 16'd48520;
        6'd15:
          sine_data16 = 16'd47980;
        6'd16:
          sine_data16 = 16'd47640;
        6'd17:
          sine_data16 = 16'd46960;
        6'd18:
          sine_data16 = 16'd45600;
        6'd19:
          sine_data16 = 16'd44580;
        6'd20:
          sine_data16 = 16'd43560;
        6'd21:
          sine_data16 = 16'd42200;
        6'd22:
          sine_data16 = 16'd38800;
        6'd23:
          sine_data16 = 16'd36080;
        6'd24:
          sine_data16 = 16'd32000;
        6'd25:
          sine_data16 = 16'd27920;
        6'd26:
          sine_data16 = 16'd25200;
        6'd27:
          sine_data16 = 16'd21800;
        6'd28:
          sine_data16 = 16'd20440;
        6'd29:
          sine_data16 = 16'd19420;
        6'd30:
          sine_data16 = 16'd18400;
        6'd31:
          sine_data16 = 16'd17040;
        6'd32:
          sine_data16 = 16'd16360;
        6'd33:
          sine_data16 = 16'd16020;
        6'd34:
          sine_data16 = 16'd15480;
        6'd35:
          sine_data16 = 16'd15000;
        6'd36:
          sine_data16 = 16'd14800;
        6'd37:
          sine_data16 = 16'd15000;
        6'd38:
          sine_data16 = 16'd15480;
        6'd39:
          sine_data16 = 16'd16020;
        6'd40:
          sine_data16 = 16'd16360;
        6'd41:
          sine_data16 = 16'd17040;
        6'd42:
          sine_data16 = 16'd18400;
        6'd43:
          sine_data16 = 16'd19420;
        6'd44:
          sine_data16 = 16'd20440;
        6'd45:
          sine_data16 = 16'd21800;
        6'd46:
          sine_data16 = 16'd25200;
        6'd47:
          sine_data16 = 16'd27920;
        default:
          sine_data16 = 16'd32000;
      endcase
    end
  //square wave generator
  //
  always
    @(posedge clk or
      negedge reset_n)
    begin
      if (reset_n == 0)
        begin
          sqr_data16 <= 16'd60000;
          sqr_cnt <= 6'b0;
        end
      else
        begin
          if (sqr_cnt == 6'd24)
            begin
              sqr_data16 <= 16'd5000;
              sqr_cnt <= sqr_cnt + 1'b1;
            end
          else
            if (sqr_cnt == 6'd49)
              begin
                sqr_data16 <= 16'd60000;
                sqr_cnt <= 6'b0;
              end
            else
              begin
                sqr_data16 <= sqr_data16;
                sqr_cnt <= sqr_cnt + 1'b1;
              end
        end
    end
  //sawtooth wave generator
  //
  always
    @(posedge clk or
      negedge reset_n)
    begin
      if (reset_n == 0)
        begin
          saw_data16 <= 16'd5000;
        end
      else
        begin
          if (saw_data16 >= 16'd60000)
            begin
              saw_data16 <= 16'd5000;
            end
          else
            begin
              saw_data16 <= saw_data16 + 16'd900;
            end
        end
    end
  //Triangle wave generator
  //
  always
    @(posedge clk or
      negedge reset_n)
    begin
      if (reset_n == 0)
        begin
          tri_data16 <= 16'd5000;
          tri_st <= UP;
        end
      else
        begin
          case (tri_st)
            UP:
              begin
                if (tri_data16 >= 16'd60000)
                  begin
                    tri_st <= DOWN;
                    tri_data16 <= tri_data16 - 16'd900;
                  end
                else
                  begin
                    tri_st <= UP;
                    tri_data16 <= tri_data16 + 16'd900;
                  end
              end
            DOWN:
              begin
                if (tri_data16 <= 16'd5000)
                  begin
                    tri_st <= UP;
                    tri_data16 <= tri_data16 + 16'd900;
                  end
                else
                  begin
                    tri_st <= DOWN;
                    tri_data16 <= tri_data16 - 16'd900;
                  end
              end
            default:
              tri_data16 <= 0;
          endcase
        end
    end
endmodule
