//--------------------------------------------------------------------------
//                                                                        --
//  OneWireMaster                                                         --
//   A synthesizable 1-wire master peripheral                             --
//   Copyright 1999-2005 Dallas Semiconductor Corporation                 --
//                                                                        --
//--------------------------------------------------------------------------
//                                                                        --
//  Purpose:  Provides timing and control of Dallas 1-wire bus            --
//            through a memory-mapped peripheral                          --
//  File:     OneWireMaster.v                                             --
//  Date:     February 1, 2005                                            --
//  Version:  v2.100                                                      --
//  Authors:  Rick Downs and Charles Hill,                                --
//            Dallas Semiconductor Corporation                            --
//                                                                        --
//  Note:     This source code is available for use without license.      --
//            Dallas Semiconductor is not responsible for the             --
//            functionality or utility of this product.                   --
//                                                                        --
//  REV:      Updated 1-Wire timings to match App Note 126 - SKH          --
//            Added in Async MR of DQ_CONTROL - GAG                       --
//            Changed WriteZero TimeSlotCnt to 60 instead of only 30 to   --
//            match OneWire Spec. - GAG                                   --
//            Added in bit control mode, left dqz for other function - GAG--
//            Added strong pullup enable signal - GAG                     --
//            Modified pd so it will not fire until the entire PD routine --
//            has completed - GAG                                         --
//            Added OW_LOW interrupt and OW_SHORT interrupt - GAG         --
//            Added PPM and LLM for long line situations - GAG            --
//            Changed logic for rsrf and rbf int flags - GAG              --
//            Significant changes to improve synthesis - English          --
//            Ported to Verilog - Sandelin                                --
//--------------------------------------------------------------------------

 module onewiremaster (
   BIT_CTL, clk, clk_1us_en, clr_activate_intr, DQ_IN, EN_FOW, EOWL,
   EOWSH, epd, erbf, ersf, etbe, etmt, FOW, ias, LLM, MR, OD,
   owr, pd, PPM, rbf_reset, sr_a, STP_SPLY, STPEN, tbe, xmit_buffer,
   clear_interrupts, DQ_CONTROL, FSM_CLK, INTR,
   OneWireIO_eq_Load, OW_LOW, OW_SHORT, pdr, rbf, rcvr_buffer, reset_owr,
   rsrf, STPZ, temt);

   input       BIT_CTL;         // enable only single bit transmitions
   input 	   clk;				//Master clk; much faster than 1us
   input       clk_1us_en;         // 1us reference clock
   input       clr_activate_intr;
   input       DQ_IN;           // OW data input
   input       EN_FOW;          // enable force OW functionality
   input       EOWL;            // enable One wire bus low interrupt
   input       EOWSH;           // enable One Wire bus short interrupt
   input       epd;             // enable presence detect interrupt
   input       erbf;            // enable receive buffer full interrupt
   input       ersf;            // enable receive shift register full int.
   input       etbe;            // enable transmit buffer empty interrupt
   input       etmt;            // enable transmit shift inputister empty int.
   input       FOW;             // Force OW value low
   input       ias;             // INTR active state
   input       LLM;             // long line mode enable
   input       MR;              // master reset
   input       OD;              // enable overdrive
   input       owr;             // one wire reset ???
   input       pd;              // presence detect interrupt
   input       PPM;             // presence pulse masking enable
   input       rbf_reset;       // clear for receive buffer full interrupt
   input       sr_a;            // search rom accelorator enable
   input       STP_SPLY;        // enable strong pull up supply mode
   input       STPEN;           // enable strong pull up output
   input       tbe;             // transmit buffer empty interrupt
   input [7:0] xmit_buffer;     // transmit buffer


   output       clear_interrupts;
   output       DQ_CONTROL;     // OW pulldown control
   output       FSM_CLK;        // state machine clk
   output       INTR;           // One wire master interrupt output signal
   output       OneWireIO_eq_Load;
   output       OW_LOW;         // One wire low interrupt
   output       OW_SHORT;       // One wire short interrupt
   output       pdr;            // presence detect result
   output       rbf;            // receive buffer full int
   output [7:0] rcvr_buffer;    // receive register
   output       reset_owr;      //
   output       rsrf;           // receive shift reg full interrupt
   output       STPZ;           // Strong pullup control (active low)
   output       temt;           // transmit shift reg empty interrupt

   //
   // Define the states
   //
   parameter [2:0] Idle       = 3'b000,  // Idle
                   CheckOWR   = 3'b001,  // Check for shorted OW
                   Reset_Low  = 3'b010,  // Start reset
                   PD_Wait    = 3'b011,  // release line for 1T
                   PD_Sample  = 3'b100,  // sample line after slowest 1T over
                   Reset_High = 3'b101,  // recover OW line level
                   PD_Force   = 3'b110,  // mask the presence pulse
                   PD_Release = 3'b111;  // recover OW line level

  parameter [4:0] IdleS=      5'b00000, // Idle state
                  Load=       5'b00001, // Load byte
                  CheckOW=    5'b00010, // Check for shorted line
                  DQLOW=      5'b00011, // Start of timeslot
                  WriteZero=  5'b00100, // Write a zero to the 1-wire
                  WriteOne=   5'b00101, // Write a one to the 1-wire
                  ReadBit=    5'b00110, // Search Rom Accelerator read bit
                  FirstPassSR=5'b00111, // Used by SRA
                  WriteBitSR= 5'b01000, // Decide what bit value to write in SRA
                  WriteBit=   5'b01001, // Writes the chosen bit in SRA
                  WaitTS=     5'b01010, // Wait for end of time slot
                  IndexInc=   5'b01011, // Increments bit index
                  UpdateBuff= 5'b01100, // Updates states of rbf
                  ODWriteZero=5'b01101, // Write a zero @ OD speed to OW
                  ODWriteOne= 5'b01110, // Write a one @ OD speed to OW
                  ClrLowDone= 5'b01111; // disable stpupz before pulldown


   // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   // micro-second count for bit transitions and sample
   parameter [6:0]                      // Standard speed
      bit_ts_writeone_high    = 7'b0000110, // release-1  @6 us
      bit_ts_writeone_high_ll = 7'b0001000, // rel-1-LLM  @8 us
      bit_ts_sample           = 7'b0001111, // sample     @15 us
      bit_ts_sample_ll        = 7'b0011000, // sample/llm @24 us
      bit_ts_writezero_high   = 7'b0111100, // release-0  @60 us
      bit_ts_end              = 7'b1000110, // end        @70 us
      bit_ts_end_ll           = 7'b1010000, // end        @80 us
   // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                        // Overdrive speed
      // note that due to the state machine architecture, the
      // writeone_high_od and sample_od must be 1 and 2 us.
      // writezero_high_od and end_od are adjustable, so long
      // as writezero_high_od does not exceed a particular 
      // 1-Wire device max low time.
      bit_ts_writeone_high_od  = 7'b0000001, // release-1 @1 us
      bit_ts_sample_od         = 7'b0000010, // sample    @2 us
      bit_ts_writezero_high_od = 7'b0001000, // release-0 @8 us
      bit_ts_end_od            = 7'b0001001; // end       @10 us
   // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   // micro-second count for reset transitions
   parameter [10:0]                     // Standard speed
      reset_ts_release = 11'b01001011000,    // release @600 us
      reset_ts_no_stpz = 11'b01001100010,    // stpz=1  @610 us
      reset_ts_ppm     = 11'b01001101100,    // pp-mask @620 us
      reset_ts_sample  = 11'b01010011110,    // sample  @670 us
      reset_ts_llsample= 11'b01010101101,    // sample  @685 us
      reset_ts_ppm_end = 11'b01010110010,    // ppm-end @690 us
      reset_ts_stpz    = 11'b01110110110,    // stpz    @950 us
      reset_ts_recover = 11'b01111000000,    // recover @960 us
      reset_ts_end     = 11'b10000111000,    // end     @1080 us
                                        // Overdrive speed
      reset_ts_release_od = 11'b00001000110, // release @70 us
      reset_ts_no_stpz_od = 11'b00001001011, // stpz=1  @75 us
      reset_ts_sample_od  = 11'b00001001111, // sample  @79 us
      reset_ts_stpz_od    = 11'b00001101001, // stpz    @105 us
      reset_ts_recover_od = 11'b00001110011, // recover @115 us
      reset_ts_end_od     = 11'b00010000000; // end     @128 us
   // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


   wire            owr;         // 1W reset command
   wire            sr_a;        // search ROM accelerator command

   // interrupt register
   wire            pd;          // presence detect done flag
   reg             pdr;         // presence detect result
   wire            tbe;         // transmit buffer empty flag
   reg             temt;        // transmit shift register empty flag
   wire            temt_ext;    // temt extended flag
   reg             rbf;         // receive buffer full flag
   reg             rsrf;        // receive shift register full flag
   reg             OW_SHORT;    // OW line shorted interrupt
   reg             OW_LOW;      // OW line low interrupt
   reg             INTR;

   //wire            rsrf_reset;  // clear signal for rsrf
   reg             set_rbf;     // set signal for rbf

   // interrupt enable register
   wire            epd;         // enable presence detect interrupt
   wire            ias;         // INTR active state
   wire            etbe;        // enable transmit buffer empty interrupt
   wire            etmt;        // enable transmit shift register empty int.
   wire            erbf;        // enable receive buffer full interrupt
   wire            ersf;        // enable receive shift register full int.
   wire            EOWSH;       // enable ow shorted interrupt
   wire            EOWL;        // enable ow low interrupt

   wire            clr_activate_intr;
   reg             reset_owr;

   reg             activate_intr;
   reg             dly_clr_activate_intr;
   reg             clear_interrupts;

   reg             SET_RSHRT;      // set ow_short prior to ow reset
   reg             SET_IOSHRT;     // set ow_short prior to tx a bit

   wire [7:0]      xmit_buffer;    // transmit buffer
   reg [7:0]       xmit_shiftreg;  // transmit shift register

   reg [7:0]       rcvr_buffer;    // receive buffer
   reg [7:0]       rcvr_shiftreg;  // receive shift register

   reg             last_rcvr_bit;  // active on index = 7 to begin shift to rbe
   reg             byte_done;
   reg             byte_done_flag, bdext1;  // signals to stretch byte_done

   reg             First;          // for Search ROM accelerator
   reg             BitRead1;
   reg             BitRead2;
   reg             BitWrite;

   reg [2:0]       OneWireReset;
   reg [4:0]       OneWireIO;

   reg [10:0]      count;
   //reg [4:0]       smCnt;
   reg [3:0]       index;
   reg [6:0]       TimeSlotCnt;

   reg             PD_READ;
   reg             LOW_DONE;
   reg             DQ_CONTROL_F;
   wire            DQ_CONTROL;
   wire            STPZ;
   reg             DQ_IN_HIGH;
   reg             OD_DQH;
	reg             rbf_set;
	reg             rsrf_reset;

   reg             ROW;

//   wire FSM_CLK = clk_1us;
   wire FSM_CLK = clk;

   //
   //  1 wire control
   //
   assign DQ_CONTROL = MR ? 1'b1 : DQ_CONTROL_F;  //GAG added in asynch RESET

   always @(posedge clk)                      //GAG added in ODWriteZero
	begin
		if(clk_1us_en)
		begin
		  DQ_CONTROL_F <=
					   (EN_FOW == 1) && (FOW == 1)?0:
					   OneWireReset == Reset_Low?0:
					   OneWireReset == PD_Wait?1:
					   OneWireReset == PD_Force?0:
					   OneWireIO == DQLOW?0:
					   OneWireIO == WriteZero?0:
					   OneWireIO == ODWriteZero?0:
					   OneWireIO == WriteBit?0:
					   1;
		end
	end

   wire OneWireIO_eq_Load = OneWireIO == Load;

   //
   // Strong Pullup control section - GAG
   // not pulling line low, not checking for pres detect, and
   // OW has recovered from read
   // SPLY is only for enabling STP when a slave requires high current
   //   and STP_SPLY is enabled
   //
   wire   SPLY = (STP_SPLY && (OneWireReset == Idle) && (OneWireIO == IdleS));
   assign STPZ = !(STPEN && DQ_CONTROL && DQ_IN_HIGH
                   && (PD_READ || LOW_DONE || SPLY));

   always @(posedge MR or posedge FSM_CLK)
	begin
     if (MR)
       begin
         DQ_IN_HIGH <= 0;
         OD_DQH <=0;
       end
		else if(clk_1us_en)
		begin
		 if (OD)
		   if(DQ_IN && !DQ_IN_HIGH && !OD_DQH)
			 begin
			   DQ_IN_HIGH <= 1;
			   OD_DQH <=1;
			 end
		   else if(OD_DQH && DQ_IN)
			 DQ_IN_HIGH <= 0;
		   else
			 begin
			   OD_DQH <=0;
			   DQ_IN_HIGH <= 0;
			 end
		 else
		   begin
			 if(DQ_IN && !DQ_IN_HIGH)
			   DQ_IN_HIGH <= 1;
			 else if (DQ_IN && DQ_IN_HIGH)
			   DQ_IN_HIGH <= DQ_IN_HIGH;
			 else
			   DQ_IN_HIGH <= 0;
		   end
	  end
    end

   //
   // Update receive buffer and the rsrf and rbf int flags
   //
	always @(posedge MR or posedge rbf_reset or posedge rbf_set)
     if (MR)
      rbf <= 0;
     else if (rbf_reset)  //note that rbf resets at the beginning of the RX buff read
      rbf <= 0;
     else
      rbf <= 1;

   always @(posedge MR or posedge FSM_CLK)
     if (MR)
       rsrf <= 1'b0;
	else if(clk_1us_en)
	begin
		 if (last_rcvr_bit || BIT_CTL)
		   begin
			 if (OneWireIO == IndexInc)
			   rsrf <= 1'b1;
			 else if (rsrf_reset)
			   rsrf <= 1'b0;
		   end
		 else if (rsrf_reset || (OneWireIO == DQLOW))
		   rsrf <= 1'b0;
	end
	
   always @(posedge FSM_CLK or posedge MR)
     if (MR)
       begin
         rcvr_buffer <= 0;
         rbf_set <= 0;
       end
     else if(clk_1us_en)
       if (rsrf && !rbf)
         begin
           rcvr_buffer <= rcvr_shiftreg;
           rbf_set <= 1'b1;
           rsrf_reset <= 1'b1;
         end
       else
         begin
           rbf_set <= 1'b0;
           if (!rsrf)
             rsrf_reset <= 1'b0;
         end

   //
   // Update OW shorted interrupt
   //
   always @(posedge MR or posedge FSM_CLK)
     begin
       if(MR)
         OW_SHORT <= 1'b0;
	   else if(clk_1us_en)
	   begin
		   if (SET_RSHRT || SET_IOSHRT)
			 OW_SHORT <= 1'b1;
		   else if (clr_activate_intr)
			 OW_SHORT <= 1'b0;
		   else
			 OW_SHORT <= OW_SHORT;
		 end
	  end
   //
   // Update OW bus low interrupt
   //
   always @(posedge MR or posedge FSM_CLK)
     begin
       if (MR)
         OW_LOW <= 0;
	   else if(clk_1us_en)
	   begin
		   if (!DQ_IN && (OneWireReset == Idle) && (OneWireIO == IdleS))
			 OW_LOW <= 1;
		   else if (clr_activate_intr)
			 OW_LOW <= 0;
		   else
			 OW_LOW <= OW_LOW;
	   end
     end

   ///////////////////////////////////////////////////////////////
   // The following section handles the interrupt itself
   ///////////////////////////////////////////////////////////////

   //
   // Create clear interrupts
   //
   always @(posedge MR or posedge FSM_CLK)
      if (MR)
         begin
            //dly_clr_activate_intr <= 1'b0;
            clear_interrupts <= 1'b0;
         end // if (MR)
      else if(clk_1us_en)
         begin
            //dly_clr_activate_intr<=clr_activate_intr;
            clear_interrupts<=clr_activate_intr;
            //clear_interrupts <= dly_clr_activate_intr ;
         end

   wire acint_reset = MR || clr_activate_intr;

   //
   // Check for active interrupt
   //
   always @(posedge acint_reset or posedge FSM_CLK)
     if(acint_reset)
        activate_intr <= 1'b0;
      else if(clk_1us_en)
        case(1)
          pd && epd:
             activate_intr <= 1'b1;
          tbe && etbe && !temt:
             activate_intr <= 1'b1;
          temt_ext && etmt:
             activate_intr <= 1'b1;
          rbf && erbf:
             activate_intr <= 1'b1;
          rsrf && ersf:
             activate_intr <= 1'b1;
          OW_LOW && EOWL:
             activate_intr <= 1'b1;
          OW_SHORT && EOWSH:
             activate_intr <= 1'b1;
        endcase // case(1)

   //
   // Create INTR signal by checking for active interrupt and active
   // state of INTR
   //
   always @(activate_intr or ias)
      case({activate_intr,ias})
        2'b11:
           INTR <= 1'b1;
        2'b01:
           INTR <= 1'b0;
        2'b10:
           INTR <= 1'b1; // shughes - 8-16-04 - was 1'b0
        default:
           INTR <= 1'b0; // shughes - 8-16-04 - was 1'b1
      endcase // case({activate_intr,ias})



   //--------------------------------------------------------------------------
   //
   //  OneWireReset
   //
   //  this state machine performs the 1-wire reset and presence detect
   //  - Added OD for overdrive speed presence detect
   //  - Added PD_LOW bit for strong pullup control
   //
   //  Idle       : OW high - waiting to issue a PD
   //  CheckOWR   : OW high - checks for shorted OW line
   //  Reset_Low  : OW low - held down for GT8 OW osc periods
   //  PD_Wait    : OW high - released and waits for 1T
   //  PD_Sample  : OW high - checks to see if a slave is out there pulling
   //                         OW low for 4T
   //  Reset_High : OW high - slave, if any, release OW and host lets it recover
   //--------------------------------------------------------------------------

   always @(posedge FSM_CLK or posedge MR)
      if(MR) begin
         pdr <= 1'b1;        // Added default state to conform to spec - SDS
         OneWireReset <= Idle;
         //smCnt <= 0;         // added to init simulations
         count <= 0;
         PD_READ <= 0;       // Added PD_READ - GAG
         reset_owr <= 0;
         SET_RSHRT <= 0;     //
			ROW <= 0;
      end
      else if(clk_1us_en)
      begin
       if(!owr)
       begin
         count <= 0;
			ROW <= 0;
         reset_owr <= 0;
         OneWireReset <= Idle;
       end
           else
              case(OneWireReset)
                Idle: begin
                   if (ROW)
			              reset_owr <= 1;
			          else
						   begin
							  count <= 0;
                       SET_RSHRT <=0;
                       reset_owr <= 0;
                       OneWireReset <= CheckOWR;
                     end
					  end

                CheckOWR: begin
                   OneWireReset <= Reset_Low;
                   if(!DQ_IN)
                     SET_RSHRT <= 1;
                   end

                Reset_Low: begin
                   count <= count + 1;
                   PD_READ <= 0;                // Added PD_READ - GAG
                   if(OD)                       // Added OD - GAG
                     begin
                       // tRSTL - OD
                       if(count == reset_ts_release_od)
                         begin
                           OneWireReset <= PD_Wait;
                           PD_READ <= 1;
                         end
                     end
                   // tRSTL - STD
                   else if(count == reset_ts_release)
                     begin
                       OneWireReset <= PD_Wait;
                       PD_READ <= 1;
                     end
                end

                PD_Wait: begin
                   SET_RSHRT <= 0;
                   count <= count + 1;
                   if(!DQ_IN & DQ_CONTROL_F) begin
                      OneWireReset <= PD_Sample;
                      //smCnt <= 0;
                   end
                   else if(OD)
                     begin
                       // (tRSTL + pull-up time) - OD
                       if(count==reset_ts_no_stpz_od)
                         // disables stp_sply
                         PD_READ <= 0;       // Be sure to turn off 4 MPD mode
                       // tMSP - OD
                       else if(count == reset_ts_sample_od)
                         begin
                           OneWireReset <= PD_Sample;
                           //smCnt <= 0;
                         end
                     end
                   // (tRSTL + pull-up time) - STD
                   else if(count == reset_ts_no_stpz)
                     // disables stp_sply
                     PD_READ <= 0; // Be sure to turn off 4 MPD mode
                   // tPPM1 - STD
                   else if((count == reset_ts_ppm) && PPM)
                     OneWireReset <= PD_Force;
                   // tMSP - STD
                   else if(count == reset_ts_llsample && !LLM)
                     begin
                       OneWireReset <= PD_Sample;
                       //smCnt <= 0;
                     end
                   else if(count == reset_ts_sample && LLM)
                     begin
                       OneWireReset <= PD_Sample;
                       //smCnt <= 0;
                     end
                end

                PD_Sample: begin
                   PD_READ <= 0;
                   count <= count + 1;
                   //smCnt <= smCnt + 1;
                   //if (OD)                      // Added OD - GAG
                   //  begin
                   //    if(smCnt == 3-1)
                   //      begin
                           pdr <= DQ_IN;
                           OneWireReset <= Reset_High;
                   //      end
                   //  end
                   //else
                   //  if(smCnt == 30-1)
                   //    begin
                   //      pdr <= DQ_IN;
                   //      OneWireReset <= Reset_High;
                   //    end
                end

                Reset_High: begin
                   count <= count + 1;
                   if (OD)                      // Added OD - GAG
                     begin
                       if (count == reset_ts_stpz_od)
                         begin
                           if (DQ_IN)
                              PD_READ <= 1;
                         end
                       else if (count == reset_ts_recover_od)
                         begin
                           PD_READ <= 0;
                         end
                       else if (count == reset_ts_end_od)
                         begin
                           PD_READ <= 0;
                           OneWireReset <= Idle;
                           ROW <= 1;
                         end
                     end
                   else
                     begin
                       if(count == reset_ts_stpz)
                         begin
                           if (DQ_IN)
                             PD_READ <= 1;
                         end
                       else if (count == reset_ts_recover)
                         begin
                           PD_READ <= 0;
                         end
                       else if (count == reset_ts_end)
                         begin
                           PD_READ <= 0;
                           OneWireReset <= Idle;
                           ROW <= 1;
                         end
                     end
                end

                PD_Force:  begin
                  count <= count + 1;
                  // tPPM2
                  if (count == reset_ts_ppm_end)
                    begin
                      OneWireReset <= PD_Release;
                    end
                end

                PD_Release: begin
                  count <= count + 1;
                  pdr <= 0;              //force valid result
                  if(count == reset_ts_stpz)
                    begin
                      if (DQ_IN)
                        PD_READ <= 1;
                    end
                  else if (count == reset_ts_recover)
                    begin
                      PD_READ <= 0;
                    end
                  else if (count == reset_ts_end)
                    begin
                      PD_READ <= 0;
                      OneWireReset <= Idle;
                      ROW <= 1;
                    end
                end

              endcase
	end

   //--------------------------------------------------------------------------
   //
   //  OneWireIO
   //
   //  this state machine performs the 1-wire writing and reading
   //  - Added ODWriteZero and ODWriteOne for overdrive timing
   //
   //  IdleS       : Waiting for transmit byte to be loaded
   //  ClrLowDone  : Disables strong pullup before pulldown turns on
   //  Load        : Loads byte to shift reg
   //  CheckOW     : Checks for OW short
   //  DQLOW       : Starts time slot with OW = 0
   //  ODWriteZero : Completes write of 0 bit / read bit in OD speed
   //  ODWriteOne  : Completes write of 1 bit / read bit in OD speed
   //  WriteZero   : Completes write of 0 bit / read bit in standard speed
   //  WriteOne    : Completes write of 1 bit / read bit in standard speed
   //  ReadBit     : AutoSearchRom : Reads the first bit value
   //  FirstPassSR : AutoSearchRom : Decides to do another read or the write
   //  WriteBitSR  : AutoSearchRom : Determines the bit to write
   //  WriteBit    : AutoSearchRom : Writes the bit
   //  WatiTS      : Allows OW to recover for the remainder of the time slot
   //  IndexInc    : Increment the index to send out next bit (in byte)
   //  UpdateBuff  : Allows other signals to update following finished byte/bit
   //--------------------------------------------------------------------------

   // The following 2 registers are to stretch the temt signal to catch the
   // temt interrupt source - SDS

   always @(posedge MR or posedge FSM_CLK)
      if(MR)
         bdext1 <= 1'b0;
      else if(clk_1us_en)
         bdext1 <= byte_done;

   always @(posedge MR or posedge FSM_CLK)
      if(MR)
         byte_done_flag <= 1'b0;
      else if(clk_1us_en)
         byte_done_flag <= bdext1;

   assign temt_ext = temt && byte_done_flag;

   // The index variable has been decoded explicitly in this state machine
   // so that the code would compile on the Cypress warp compiler - SDS
   always @(posedge FSM_CLK or posedge MR)
      if(MR) begin
         index <= 0;
         TimeSlotCnt <= 0;
         temt <= 1'b1;
         last_rcvr_bit <= 1'b0;
         rcvr_shiftreg <= 0;
         OneWireIO <= IdleS;
         BitRead1<=0;
         BitRead2<=0;
         BitWrite<=0;
         First <= 1'b0;
         byte_done <= 1'b0;
         xmit_shiftreg<=0;
         LOW_DONE <= 0;
         SET_IOSHRT <= 0;
      end
      else if(clk_1us_en)
         case(OneWireIO)

           // IdleS state clears variables and waits for something to be
           // deposited in the transmit buffer. When something is there,
           // the next state is Load.
           IdleS:
              begin
                 byte_done <= 1'b0;
                 index <= 0;
                 last_rcvr_bit <= 1'b0;
                 First <= 1'b0;
                 TimeSlotCnt <= 0;
                 LOW_DONE <= 0;
                 SET_IOSHRT <= 0;
                 temt <= 1'b1;
                 if(!tbe)
                   begin
                     if(STPEN)
                       OneWireIO <= ClrLowDone;
                     else
                       OneWireIO <= Load;
                   end
                 else
                    OneWireIO <= IdleS;
              end

           // New state added to be sure the strong pullup will be disabled
           // before the OW pulldown turns on
           ClrLowDone:
              begin
                 LOW_DONE <= 0;
                 if (!LOW_DONE)
                   OneWireIO <= Load;
              end

           // Load transfers the transmit buffer to the transmit shift register,
           // then clears the transmit shift register empty interrupt. The next
           // state is then DQLOW.
           Load:
              begin
                 xmit_shiftreg <= xmit_buffer;
                 rcvr_shiftreg <= 0;
                 temt <= 1'b0;
                 LOW_DONE <= 0;
                 OneWireIO <= CheckOW;
              end

           // Checks OW value before sending out every bit to see if line
           // was forced low by some other means at an incorrect time
           CheckOW:
             begin
               OneWireIO <= DQLOW;
               //TimeSlotCnt <= TimeSlotCnt + 1;
               if (!DQ_IN)
                 SET_IOSHRT <= 1;
             end

           // DQLOW pulls the DQ line low for 1us, beginning a timeslot.
           // If sr_a is 0, it is a normal write/read operation. If sr_a
           // is a 1, then you must go into Search ROM accelerator mode.
           // If OD is 1, the part is in overdrive and must perform
           // ODWrites instead of normal Writes while OD is 0.
           DQLOW:
             begin
              TimeSlotCnt <= TimeSlotCnt + 1;
              LOW_DONE <= 0;
              if (OD)
               begin
                  //if(TimeSlotCnt==bit_ts_writeone_high_od)
                  //begin
                   if(!sr_a)
                     begin
                       case(index)
                         0:
                            if(!xmit_shiftreg[0])
                               OneWireIO <= ODWriteZero;
                            else
                               OneWireIO <= ODWriteOne;
                         1:
                            if(!xmit_shiftreg[1])
                               OneWireIO <= ODWriteZero;
                            else
                               OneWireIO <= ODWriteOne;
                         2:
                            if(!xmit_shiftreg[2])
                               OneWireIO <= ODWriteZero;
                            else
                               OneWireIO <= ODWriteOne;
                         3:
                            if(!xmit_shiftreg[3])
                               OneWireIO <= ODWriteZero;
                            else
                               OneWireIO <= ODWriteOne;
                         4:
                            if(!xmit_shiftreg[4])
                               OneWireIO <= ODWriteZero;
                            else
                               OneWireIO <= ODWriteOne;
                         5:
                            if(!xmit_shiftreg[5])
                               OneWireIO <= ODWriteZero;
                            else
                               OneWireIO <= ODWriteOne;
                         6:
                            if(!xmit_shiftreg[6])
                               OneWireIO <= ODWriteZero;
                            else
                               OneWireIO <= ODWriteOne;
                         7:
                            if(!xmit_shiftreg[7])
                               OneWireIO <= ODWriteZero;
                            else
                               OneWireIO <= ODWriteOne;
                       endcase // case(index)
                     end
                   else         // Search Rom Accelerator mode
                     OneWireIO <= ReadBit;
                  end
               //end
              else if(((TimeSlotCnt==bit_ts_writeone_high) && !LLM) || 
                      ((TimeSlotCnt==bit_ts_writeone_high_ll) && LLM))
              begin
                 if(!sr_a)                  // Normal write
                   begin
                      case(index)
                        0:
                           if(!xmit_shiftreg[0])
                              OneWireIO <= WriteZero;
                           else
                              OneWireIO <= WriteOne;
                        1:
                           if(!xmit_shiftreg[1])
                              OneWireIO <= WriteZero;
                           else
                              OneWireIO <= WriteOne;
                        2:
                           if(!xmit_shiftreg[2])
                              OneWireIO <= WriteZero;
                           else
                              OneWireIO <= WriteOne;
                        3:
                           if(!xmit_shiftreg[3])
                              OneWireIO <= WriteZero;
                           else
                              OneWireIO <= WriteOne;
                        4:
                           if(!xmit_shiftreg[4])
                              OneWireIO <= WriteZero;
                           else
                              OneWireIO <= WriteOne;
                        5:
                           if(!xmit_shiftreg[5])
                              OneWireIO <= WriteZero;
                           else
                              OneWireIO <= WriteOne;
                        6:
                           if(!xmit_shiftreg[6])
                              OneWireIO <= WriteZero;
                           else
                              OneWireIO <= WriteOne;
                        7:
                           if(!xmit_shiftreg[7])
                              OneWireIO <= WriteZero;
                           else
                              OneWireIO <= WriteOne;
                      endcase // case(index)
                  end
                  else         // Search Rom Accelerator mode
                     OneWireIO <= ReadBit;
                  end
               end

           // WriteZero and WriteOne are identical, except for what they do to
           // DQ (assigned in concurrent assignments). They both read DQ after
           // 15us, then move on to wait for the end of the timeslot, unless
           // running in Long Line mode which extends the sample time out to 22
           WriteZero:
             begin
              TimeSlotCnt <= TimeSlotCnt + 1;
              if(((TimeSlotCnt==bit_ts_sample) && !sr_a && !LLM) ||
                 ((TimeSlotCnt==bit_ts_sample_ll) && !sr_a &&  LLM))
                 case(index)
                   0:
                      rcvr_shiftreg[0] <= DQ_IN;
                   1:
                      rcvr_shiftreg[1] <= DQ_IN;
                   2:
                      rcvr_shiftreg[2] <= DQ_IN;
                   3:
                      rcvr_shiftreg[3] <= DQ_IN;
                   4:
                      rcvr_shiftreg[4] <= DQ_IN;
                   5:
                      rcvr_shiftreg[5] <= DQ_IN;
                   6:
                      rcvr_shiftreg[6] <= DQ_IN;
                   7:
                      rcvr_shiftreg[7] <= DQ_IN;
                 endcase
              if(TimeSlotCnt == bit_ts_writezero_high)            //62 7_25_01
                 OneWireIO <= WaitTS;
              if(DQ_IN)
                 LOW_DONE <= 1;
             end

           WriteOne:
             begin
              TimeSlotCnt <= TimeSlotCnt + 1;
              if(((TimeSlotCnt==bit_ts_sample) && !sr_a && !LLM) ||
                 ((TimeSlotCnt==bit_ts_sample_ll) && !sr_a &&  LLM))
                 case(index)
                   0:
                      rcvr_shiftreg[0] <= DQ_IN;
                   1:
                      rcvr_shiftreg[1] <= DQ_IN;
                   2:
                      rcvr_shiftreg[2] <= DQ_IN;
                   3:
                      rcvr_shiftreg[3] <= DQ_IN;
                   4:
                      rcvr_shiftreg[4] <= DQ_IN;
                   5:
                      rcvr_shiftreg[5] <= DQ_IN;
                   6:
                      rcvr_shiftreg[6] <= DQ_IN;
                   7:
                      rcvr_shiftreg[7] <= DQ_IN;
                 endcase
              if(TimeSlotCnt == bit_ts_writezero_high)             //62 7_25_01
                 OneWireIO <= WaitTS;
              if(DQ_IN)
                 LOW_DONE <= 1;
             end

           // ADDED ODWRITE states here GAG
           // ODWriteZero and ODWriteOne are identical, except for what they
           // do to DQ (assigned in concurrent assignments). They both read
           // DQ after 3us, then move on to wait for the end of the timeslot.
           ODWriteZero:
             begin
              TimeSlotCnt <= TimeSlotCnt + 1;
              if((TimeSlotCnt == bit_ts_sample_od) && !sr_a)
                 case(index)
                   0:
                      rcvr_shiftreg[0] <= DQ_IN;
                   1:
                      rcvr_shiftreg[1] <= DQ_IN;
                   2:
                      rcvr_shiftreg[2] <= DQ_IN;
                   3:
                      rcvr_shiftreg[3] <= DQ_IN;
                   4:
                      rcvr_shiftreg[4] <= DQ_IN;
                   5:
                      rcvr_shiftreg[5] <= DQ_IN;
                   6:
                      rcvr_shiftreg[6] <= DQ_IN;
                   7:
                      rcvr_shiftreg[7] <= DQ_IN;
                 endcase
              if(TimeSlotCnt == bit_ts_writezero_high_od)
                 OneWireIO <= WaitTS;
              if(DQ_IN)
                 LOW_DONE <= 1;
             end

           ODWriteOne:
             begin
              TimeSlotCnt <= TimeSlotCnt + 1;
              if((TimeSlotCnt == bit_ts_sample_od) && !sr_a)
                 case(index)
                   0:
                      rcvr_shiftreg[0] <= DQ_IN;
                   1:
                      rcvr_shiftreg[1] <= DQ_IN;
                   2:
                      rcvr_shiftreg[2] <= DQ_IN;
                   3:
                      rcvr_shiftreg[3] <= DQ_IN;
                   4:
                      rcvr_shiftreg[4] <= DQ_IN;
                   5:
                      rcvr_shiftreg[5] <= DQ_IN;
                   6:
                      rcvr_shiftreg[6] <= DQ_IN;
                   7:
                      rcvr_shiftreg[7] <= DQ_IN;
                 endcase
              if(TimeSlotCnt == bit_ts_writezero_high_od)
                OneWireIO <= WaitTS;
              if(DQ_IN)
                 LOW_DONE <= 1;
             end

           // ReadBit used by the SRA to do the required bit reads
           ReadBit:
             begin
              TimeSlotCnt <= TimeSlotCnt + 1;
              if(DQ_IN)
                LOW_DONE <= 1;
              if(OD)
                begin
                  if(TimeSlotCnt == bit_ts_sample_od)
                    if(!First)
                      BitRead1 <= DQ_IN;
                    else
                      BitRead2 <= DQ_IN;
                  if(TimeSlotCnt == bit_ts_writezero_high_od)     //7 7_25_01
                    OneWireIO <= FirstPassSR;
                end
              else
                begin
                  if(((TimeSlotCnt == bit_ts_sample)&&!LLM) || ((TimeSlotCnt == bit_ts_sample_ll)&&LLM))
                    if(!First)
                      BitRead1 <= DQ_IN;
                    else
                      BitRead2 <= DQ_IN;
                  if(TimeSlotCnt == bit_ts_writezero_high)
                    OneWireIO <= FirstPassSR;
                end
             end

           // FirstPassSR decides whether to do another read or to do the
           // bit write.
           FirstPassSR:
             begin
              TimeSlotCnt <= TimeSlotCnt + 1;
              LOW_DONE <= 0;
              if(OD)
                begin
                  if(TimeSlotCnt == bit_ts_end_od)
                    begin
                      TimeSlotCnt <= 0;
                      if(!First)
                        begin
                          First <= 1'b1;
                          OneWireIO <= DQLOW;
                        end
                      else
                        begin
                          OneWireIO <= WriteBitSR;
                        end
                    end
                end
              else
                begin
                  if(((TimeSlotCnt==bit_ts_end) && !LLM) || ((TimeSlotCnt==bit_ts_end_ll) && LLM))
                    begin
                      TimeSlotCnt <= 0;
                      if(!First)
                        begin
                          First <= 1'b1;
                          OneWireIO <= DQLOW;
                        end
                      else
                        begin
                          OneWireIO <= WriteBitSR;
                        end // else: !if(!First)
                    end
                end
             end

           // WriteBitSR will now determine the bit necessary to write
           // for the Search ROM to proceed.
           WriteBitSR:
             begin
               case({BitRead1,BitRead2})
                 2'b00: begin
                    case(index)
                      0: begin
                         BitWrite <= xmit_shiftreg[1];
                         rcvr_shiftreg[0] <= 1'b1;
                      end
                      1: begin
                         BitWrite <= xmit_shiftreg[2];
                         rcvr_shiftreg[1] <= 1'b1;
                      end
                      2: begin
                         BitWrite <= xmit_shiftreg[3];
                         rcvr_shiftreg[2] <= 1'b1;
                      end
                      3: begin
                         BitWrite <= xmit_shiftreg[4];
                         rcvr_shiftreg[3] <= 1'b1;
                      end
                      4: begin
                         BitWrite <= xmit_shiftreg[5];
                         rcvr_shiftreg[4] <= 1'b1;
                      end
                      5: begin
                         BitWrite <= xmit_shiftreg[6];
                         rcvr_shiftreg[5] <= 1'b1;
                      end
                      6: begin
                         BitWrite <= xmit_shiftreg[7];
                         rcvr_shiftreg[6] <= 1'b1;
                      end
                      7: begin
                         BitWrite <= xmit_shiftreg[0];
                         rcvr_shiftreg[7] <= 1'b1;
                      end
                    endcase
                 end
                 2'b01: begin
                    BitWrite <= 1'b0;
                    case(index)
                      0:
                         rcvr_shiftreg[0] <= 1'b0;
                      1:
                         rcvr_shiftreg[1] <= 1'b0;
                      2:
                         rcvr_shiftreg[2] <= 1'b0;
                      3:
                         rcvr_shiftreg[3] <= 1'b0;
                      4:
                         rcvr_shiftreg[4] <= 1'b0;
                      5:
                         rcvr_shiftreg[5] <= 1'b0;
                      6:
                         rcvr_shiftreg[6] <= 1'b0;
                      7:
                         rcvr_shiftreg[7] <= 1'b0;
                    endcase
                 end
                 2'b10: begin
                    BitWrite <= 1'b1;
                    case(index)
                      0:
                         rcvr_shiftreg[0] <= 1'b0;
                      1:
                         rcvr_shiftreg[1] <= 1'b0;
                      2:
                         rcvr_shiftreg[2] <= 1'b0;
                      3:
                         rcvr_shiftreg[3] <= 1'b0;
                      4:
                         rcvr_shiftreg[4] <= 1'b0;
                      5:
                         rcvr_shiftreg[5] <= 1'b0;
                      6:
                         rcvr_shiftreg[6] <= 1'b0;
                      7:
                         rcvr_shiftreg[7] <= 1'b0;
                    endcase
                 end
                 2'b11: begin
                    BitWrite <= 1'b1;
                    case(index)
                      0: begin
                         rcvr_shiftreg[0] <= 1'b1;
                         rcvr_shiftreg[1] <= 1'b1;
                      end
                      1: begin
                         rcvr_shiftreg[1] <= 1'b1;
                         rcvr_shiftreg[2] <= 1'b1;
                      end
                      2: begin
                         rcvr_shiftreg[2] <= 1'b1;
                         rcvr_shiftreg[3] <= 1'b1;
                      end
                      3: begin
                         rcvr_shiftreg[3] <= 1'b1;
                         rcvr_shiftreg[4] <= 1'b1;
                      end
                      4: begin
                         rcvr_shiftreg[4] <= 1'b1;
                         rcvr_shiftreg[5] <= 1'b1;
                      end
                      5: begin
                         rcvr_shiftreg[5] <= 1'b1;
                         rcvr_shiftreg[6] <= 1'b1;
                      end
                      6: begin
                         rcvr_shiftreg[6] <= 1'b1;
                         rcvr_shiftreg[7] <= 1'b1;
                      end
                      7: begin
                         rcvr_shiftreg[7] <= 1'b1;
                         rcvr_shiftreg[0] <= 1'b1;
                      end
                    endcase
                 end
               endcase // case({BitRead1,BitRead2})
               OneWireIO <= WriteBit;
              end

           // WriteBit actually writes the chosen bit to the One Wire bus.
           WriteBit:
             begin
              TimeSlotCnt <= TimeSlotCnt + 1;
              case(index)
                0:
                   rcvr_shiftreg[1] <= BitWrite;
                1:
                   rcvr_shiftreg[2] <= BitWrite;
                2:
                   rcvr_shiftreg[3] <= BitWrite;
                3:
                   rcvr_shiftreg[4] <= BitWrite;
                4:
                   rcvr_shiftreg[5] <= BitWrite;
                5:
                   rcvr_shiftreg[6] <= BitWrite;
                6:
                   rcvr_shiftreg[7] <= BitWrite;
                7:
                   rcvr_shiftreg[0] <= BitWrite;
              endcase
              if(!BitWrite)
                begin
                  if(OD)
                    OneWireIO <= ODWriteZero;
                  else
                    OneWireIO <= WriteZero;
                end
              else
                begin
                  if(OD && (TimeSlotCnt == bit_ts_writeone_high_od))
                    OneWireIO <= ODWriteOne;
                  else if (!LLM && (TimeSlotCnt == bit_ts_writeone_high))  //5 7_25_01
                    OneWireIO <= WriteOne;
                  else if (LLM && (TimeSlotCnt == bit_ts_writeone_high_ll))
                    OneWireIO <= WriteOne;
                end
             end

           // WaitTS waits until the timeslot is completed, 80us. When done with
           // that timeslot, the index will be incremented.
           WaitTS:
             begin
              SET_IOSHRT <= 0;
              TimeSlotCnt <= TimeSlotCnt + 1;
              if(OD)
                begin
                  if(TimeSlotCnt == bit_ts_end_od)  //11 7_25_01
                    OneWireIO <= IndexInc;
                end
              else
                if(((TimeSlotCnt == bit_ts_end) && !LLM) || ((TimeSlotCnt==bit_ts_end_ll) && LLM))
                  OneWireIO <= IndexInc;
              if(DQ_IN)
                 LOW_DONE <= 1;
             end

           // IndexInc incs the index by 1 if normal write, by 2 if in SRA
           IndexInc:
             begin
              if(!sr_a)
                 index <= index + 1;
              else
                 begin
                    index <= index + 2;
                    First <= 1'b0;
                 end

              if(BIT_CTL || (index == 8-1 && !sr_a) || (index == 8-2 && sr_a)  )
                 begin                             // Added BIT_CTL - GAG
                    byte_done <= 1'b1;
                    OneWireIO <= UpdateBuff;
                 end
              else
                 begin
                    if((index == 7-1) && !sr_a)
                       last_rcvr_bit <= 1'b1;
                    else
                       if((index == 6-2) && sr_a)
                          last_rcvr_bit <= 1'b1;
                    OneWireIO <= DQLOW;
                    TimeSlotCnt <= 0;
                 end

                 LOW_DONE <= 0;
             end

           UpdateBuff:
             begin
                OneWireIO <= IdleS;
                if(DQ_IN && STP_SPLY)
                  LOW_DONE <= 1;
             end
         endcase
endmodule
