/* Verilog netlist generated by SCUBA Diamond (64-bit) 3.2.0.204 */
/* Module Version: 5.5 */
/* C:\lscc\diamond\3.2_x64\ispfpga\bin\nt64\scuba.exe -w -n deser -lang verilog -synth synplify -bus_exp 7 -bb -arch sa5p00m -type iol -mode Receive -io_type LVDS -width 4 -freq_in 400 -gear 4 -del 128 -fdc C:/FPGA_Designs/6900checkpoint4_csi2dsi/Designs/rtl/ECP3/IPExpress/ECP5/deser/deser.fdc  */
/* Mon Jun 16 18:53:45 2014 */


// ============================================================================
//                           COPYRIGHT NOTICE
// Copyright 2013 Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// This confidential and proprietary software may be used only as authorized by
// a licensing agreement from Lattice Semiconductor Corporation.
// The entire notice above must be reproduced on all authorized copies and
// copies may only be made to the extent permitted by a licensing agreement 
// from Lattice Semiconductor Corporation.
//
// Lattice Semiconductor Corporation      TEL  : 1-800-Lattice (USA and Canada)
// 5555 NE Moore Court                           408-826-6000 (other locations)
// Hillsboro, OR 97124                    web  : http://www.latticesemi.com/
// U.S.A                                  email: techsupport@latticesemi.com
// =============================================================================
// Module     : gddr_sync.v
// Description: 
//   - Code for bus synchronization
//   - Needed to tolerate large skew between stop and ddr and clkdiv reset
// =============================================================================

`timescale 1ns/1ps

module desergddr_sync (
  // inputs
  rst,             // Asynchronous reset
  sync_clk,        // oscillator clk or other constant running low speed clk.
                   // note that this clk should not be coming from clk sources 
                   // that this module will stop or reset (e.g. ECLKSYNC, CLKDIV)
  start,           // Initialize the sync process

  // outputs
  stop,            // ECLKSYNC.stop signal
  ddr_reset,       // DDR and CLKDIV reset signal
  ready            // READY signal; clock sync is done.
);

//-----------------------------------------------------------------------------
// PORTS DECLARATIONS
//----------------------------------------------------------------------------- 
// input ports
input       rst;
input       sync_clk;
input       start;

// output ports
output      stop;
output      ddr_reset;
output      ready;

//-----------------------------------------------------------------------------
// PARAMETERS
//-----------------------------------------------------------------------------        
// Local parameters: States
localparam INIT   = 3'b000;
localparam STOP   = 3'b001;
localparam RESET  = 3'b011;
localparam READY  = 3'b100;

//----------------------------------------------------------------------------- 
// SIGNAL DECLARATIONS
//-----------------------------------------------------------------------------  
wire        rst;
wire        sync_clk;
wire        start;
wire        ddr_reset;     
wire        stop;
wire        ready;

reg         ddr_reset_d;
reg   [3:0] ctrl_cnt;                                    // control counter
reg   [2:0] stop_assert;                                 // stop signal counter
reg   [2:0] cs_gddr_sync /*synthesis syn_preserve=1*/ ;  // current state
reg   [2:0] ns_gddr_sync;                                // next state
reg         reset_flag;                                  // flag signal that 
                                                         // indicates that RESET 
                                                         // is already done
  
//----------------------------------------------------------------------------- 
//  WIRE ASSIGNMENTS
//-----------------------------------------------------------------------------       
assign stop      = cs_gddr_sync[0];              
assign ddr_reset = cs_gddr_sync[1] | ddr_reset_d;
assign ready     = cs_gddr_sync[2];

//----------------------------------------------------------------------------- 
//  REGISTER ASSIGNMENTS
//-----------------------------------------------------------------------------  
always @(posedge sync_clk or posedge rst) begin
  if (rst==1'b1)
  begin
    cs_gddr_sync  <= INIT;
    ctrl_cnt      <= 4'd0;
    stop_assert   <= 3'd0;
    reset_flag    <= 1'b0;
    ddr_reset_d   <= 1'b1;
  end
  else
  begin
    cs_gddr_sync  <= ns_gddr_sync;
    ddr_reset_d   <= 1'b0;

    // CTRL_CNT for state machines        
    if (((cs_gddr_sync==INIT)&&(reset_flag==1'b0))||((ctrl_cnt == 3)
         &&(cs_gddr_sync!=INIT)))    
    begin          
      ctrl_cnt <= 'd0;
    end
    else if (ctrl_cnt < 8)
    begin          
      ctrl_cnt <= ctrl_cnt + 1;
    end
        
    // STOP signal will then be asserted 4T after rstn
    if ((!rst)&&(start)&&(stop_assert<4)&&(reset_flag==1'b0))               
    begin            
      stop_assert <= stop_assert + 1;
    end

    // Asserts the reset_flag after RESET state
    if ((cs_gddr_sync==RESET)&&(ns_gddr_sync == STOP))    
    begin
      reset_flag <= 1'b1;            
    end

    // Deasserts the reset_flag after READY state            
    if ((cs_gddr_sync==READY)&&(ns_gddr_sync == INIT))    
    begin
      reset_flag <= 1'b0;            
    end                    
  end
end

// GDDR_SYNC State machine    
always @(*) begin
  
  case (cs_gddr_sync)  /* synthesis full_case parallel_case */
    INIT:  // INIT state 0
    begin
      if ((start)&&(stop_assert==3)&&(reset_flag==1'b0))
      begin
        ns_gddr_sync = STOP;
      end
      else if ((reset_flag==1'b1)&&(ctrl_cnt == 7)&&(start))
      begin
        ns_gddr_sync = READY;
      end
      else
      begin
        ns_gddr_sync = INIT;
      end
    end
    
    STOP:  //STOP state 1
    begin
      if (ctrl_cnt == 3)
      begin
        if (reset_flag ==1'b1)
        begin
          ns_gddr_sync  = INIT;
        end
        else
        begin
          ns_gddr_sync  = RESET;
        end
      end
      else
      begin
        ns_gddr_sync = STOP;
      end
    end    
    
    RESET:  // RESET state 2
    begin
      if (ctrl_cnt == 3)
      begin
        ns_gddr_sync = STOP;
      end
      else
      begin
        ns_gddr_sync = RESET;
      end
    end
    
    READY:  // READY state 5
    begin
      if ((!start))
      begin
        ns_gddr_sync = INIT;
      end
      else
      begin
        ns_gddr_sync = READY;
      end
    end
    
    default:
    begin
      ns_gddr_sync = cs_gddr_sync;
    end
    
  endcase
end
  
endmodule // desergddr_sync


`timescale 1 ns / 1 ps
module deser (alignwd, clkin, ready, sclk, start, sync_clk, sync_reset, 
    datain, q)/* synthesis syn_noprune=1 *//* synthesis NGD_DRC_MASK=1 */;// exemplar attribute deser dont_touch true 
    input wire alignwd;
    input wire clkin;
    input wire start;
    input wire sync_clk;
    input wire sync_reset;
    input wire [3:0] datain;
    output wire ready;
    output wire sclk;
    output wire [15:0] q;

    wire stop;
    wire eclki;
    wire buf_clkin;
    wire qa3;
    wire qb3;
    wire qc3;
    wire qd3;
    wire qa2;
    wire qb2;
    wire qc2;
    wire qd2;
    wire qa1;
    wire qb1;
    wire qc1;
    wire qd1;
    wire qa0;
    wire qb0;
    wire qc0;
    wire qd0;
    wire reset;
    wire eclko;
    wire sclk_t;
    wire dataini_t3;
    wire dataini_t2;
    wire dataini_t1;
    wire dataini_t0;
    wire buf_dataini3;
    wire buf_dataini2;
    wire buf_dataini1;
    wire buf_dataini0;

    IB Inst5_IB (.I(clkin), .O(buf_clkin))
             /* synthesis IO_TYPE="LVDS" */;

    defparam Inst4_CLKDIVF.DIV = "2.0" ;
    CLKDIVF Inst4_CLKDIVF (.CLKI(eclko), .RST(reset), .ALIGNWD(alignwd), 
        .CDIVX(sclk_t));

    ECLKSYNCB Inst3_ECLKSYNCB (.ECLKI(eclki), .STOP(stop), .ECLKO(eclko));

    desergddr_sync Inst_gddr_sync (.rst(sync_reset), .sync_clk(sync_clk), 
        .start(start), .stop(stop), .ddr_reset(reset), .ready(ready));

    IDDRX2F Inst2_IDDRX2F3 (.D(dataini_t3), .SCLK(sclk_t), .ECLK(eclko), 
        .RST(reset), .ALIGNWD(alignwd), .Q3(qd3), .Q2(qc3), .Q1(qb3), .Q0(qa3));

    IDDRX2F Inst2_IDDRX2F2 (.D(dataini_t2), .SCLK(sclk_t), .ECLK(eclko), 
        .RST(reset), .ALIGNWD(alignwd), .Q3(qd2), .Q2(qc2), .Q1(qb2), .Q0(qa2));

    IDDRX2F Inst2_IDDRX2F1 (.D(dataini_t1), .SCLK(sclk_t), .ECLK(eclko), 
        .RST(reset), .ALIGNWD(alignwd), .Q3(qd1), .Q2(qc1), .Q1(qb1), .Q0(qa1));

    IDDRX2F Inst2_IDDRX2F0 (.D(dataini_t0), .SCLK(sclk_t), .ECLK(eclko), 
        .RST(reset), .ALIGNWD(alignwd), .Q3(qd0), .Q2(qc0), .Q1(qb0), .Q0(qa0));

    defparam udel_dataini3.DEL_MODE = "ECLK_CENTERED" ;
    DELAYG udel_dataini3 (.A(buf_dataini3), .Z(dataini_t3));

    defparam udel_dataini2.DEL_MODE = "ECLK_CENTERED" ;
    DELAYG udel_dataini2 (.A(buf_dataini2), .Z(dataini_t2));

    defparam udel_dataini1.DEL_MODE = "ECLK_CENTERED" ;
    DELAYG udel_dataini1 (.A(buf_dataini1), .Z(dataini_t1));

    defparam udel_dataini0.DEL_MODE = "ECLK_CENTERED" ;
    DELAYG udel_dataini0 (.A(buf_dataini0), .Z(dataini_t0));

    IB Inst1_IB3 (.I(datain[3]), .O(buf_dataini3))
             /* synthesis IO_TYPE="LVDS" */;

    IB Inst1_IB2 (.I(datain[2]), .O(buf_dataini2))
             /* synthesis IO_TYPE="LVDS" */;

    IB Inst1_IB1 (.I(datain[1]), .O(buf_dataini1))
             /* synthesis IO_TYPE="LVDS" */;

    IB Inst1_IB0 (.I(datain[0]), .O(buf_dataini0))
             /* synthesis IO_TYPE="LVDS" */;

    assign sclk = sclk_t;
    assign q[15] = qd3;
    assign q[14] = qd2;
    assign q[13] = qd1;
    assign q[12] = qd0;
    assign q[11] = qc3;
    assign q[10] = qc2;
    assign q[9] = qc1;
    assign q[8] = qc0;
    assign q[7] = qb3;
    assign q[6] = qb2;
    assign q[5] = qb1;
    assign q[4] = qb0;
    assign q[3] = qa3;
    assign q[2] = qa2;
    assign q[1] = qa1;
    assign q[0] = qa0;
    assign eclki = buf_clkin;


    // exemplar begin
    // exemplar attribute Inst5_IB IO_TYPE LVDS
    // exemplar attribute Inst1_IB3 IO_TYPE LVDS
    // exemplar attribute Inst1_IB2 IO_TYPE LVDS
    // exemplar attribute Inst1_IB1 IO_TYPE LVDS
    // exemplar attribute Inst1_IB0 IO_TYPE LVDS
    // exemplar end

endmodule
