]> git.zerfleddert.de Git - raggedstone/blobdiff - ethernet/source/pci/pci_spoci_ctrl.v
add shit
[raggedstone] / ethernet / source / pci / pci_spoci_ctrl.v
diff --git a/ethernet/source/pci/pci_spoci_ctrl.v b/ethernet/source/pci/pci_spoci_ctrl.v
new file mode 100644 (file)
index 0000000..faad708
--- /dev/null
@@ -0,0 +1,919 @@
+//////////////////////////////////////////////////////////////////////
+////                                                              ////
+////  File name: pci_spoci_ctrl                                   ////
+////                                                              ////
+////  This file is part of the "PCI bridge" project               ////
+////  http://www.opencores.org/cores/pci/                         ////
+////                                                              ////
+////  Author(s):                                                  ////
+////      - Miha Dolenc (mihad@opencores.org)                     ////
+////                                                              ////
+////                                                              ////
+//////////////////////////////////////////////////////////////////////
+////                                                              ////
+//// Copyright (C) 2004 Miha Dolenc, mihad@opencores.org          ////
+////                                                              ////
+//// This source file may be used and distributed without         ////
+//// restriction provided that this copyright statement is not    ////
+//// removed from the file and that any derivative work contains  ////
+//// the original copyright notice and the associated disclaimer. ////
+////                                                              ////
+//// This source file is free; you can redistribute it            ////
+//// and/or modify it under the terms of the GNU Lesser General   ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any   ////
+//// later version.                                               ////
+////                                                              ////
+//// This source is distributed in the hope that it will be       ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
+//// PURPOSE.  See the GNU Lesser General Public License for more ////
+//// details.                                                     ////
+////                                                              ////
+//// You should have received a copy of the GNU Lesser General    ////
+//// Public License along with this source; if not, download it   ////
+//// from http://www.opencores.org/lgpl.shtml                     ////
+////                                                              ////
+//////////////////////////////////////////////////////////////////////
+//
+// CVS Revision History
+//
+// $Log: pci_spoci_ctrl.v,v $
+// Revision 1.1  2007-03-20 17:50:56  sithglan
+// add shit
+//
+// Revision 1.1  2004/01/24 11:54:18  mihad
+// Update! SPOCI Implemented!
+//
+//
+
+`include "pci_constants.v"
+
+// synopsys translate_off
+`include "timescale.v"
+// synopsys translate_on
+
+module pci_spoci_ctrl
+(
+    reset_i             ,
+    clk_i               ,
+                        
+    do_rnd_read_i       ,
+    do_seq_read_i       ,
+    do_write_i          ,
+                        
+    write_done_o        ,
+    dat_rdy_o           ,
+    no_ack_o            ,
+                        
+    adr_i               ,
+    dat_i               ,
+    dat_o               ,
+
+    pci_spoci_sda_i     ,
+    pci_spoci_sda_oe_o  ,
+    pci_spoci_scl_oe_o
+);
+
+parameter tx_rx_state_width = 9     ;
+parameter tx_rx_idle        = 'h1   ;
+parameter tx_rx_start       = 'h2   ;
+parameter tx_rx_restart     = 'h4   ;
+parameter tx_rx_send_bits   = 'h8   ;
+parameter tx_rx_rec_bits    = 'h10  ;
+parameter tx_rx_send_ack    = 'h20  ;
+parameter tx_rx_rec_ack     = 'h40  ;
+parameter tx_rx_send_nack   = 'h80  ;
+parameter tx_rx_stop        = 'h100 ;
+
+parameter rw_seq_state_width    = 5     ;
+parameter rw_seq_idle           = 'h1   ;
+parameter rw_seq_tx_ctrl        = 'h2   ;
+parameter rw_seq_tx_adr         = 'h4   ;
+parameter rw_seq_tx_byte        = 'h8   ;
+parameter rw_seq_rx_byte        = 'h10  ;
+
+`ifdef PCI33
+parameter cnt_width     = 9     ;
+parameter period_cnt    = 334   ;
+`endif
+
+`ifdef PCI66
+parameter cnt_width     = 10    ;
+parameter period_cnt    = 667   ;
+`endif
+
+input   reset_i ,
+        clk_i   ;
+
+input   do_rnd_read_i   ,
+        do_seq_read_i   ,
+        do_write_i      ;
+
+output  write_done_o    ,
+        dat_rdy_o       ,
+        no_ack_o        ;
+
+input   [10: 0] adr_i   ;
+input   [ 7: 0] dat_i   ;
+output  [ 7: 0] dat_o   ;
+
+input   pci_spoci_sda_i     ;
+
+output  pci_spoci_sda_oe_o  ,
+        pci_spoci_scl_oe_o  ;
+
+reg write_done_o    ,
+    dat_rdy_o       ,
+    no_ack_o        ;
+
+reg [ 7: 0] dat_o   ;
+
+reg pci_spoci_sda_oe_o  ,
+    pci_spoci_scl_oe_o  ;
+
+reg clk_gen_cnt_en  ;
+reg clk_gen_cnt_clr ;
+reg [cnt_width - 1:0] clk_gen_cnt   ;
+
+reg [tx_rx_state_width - 1:0] tx_rx_state       ;
+reg [tx_rx_state_width - 1:0] tx_rx_next_state  ;
+reg tx_rx_sm_idle ;
+
+reg scl_oe      ;
+reg scl_oe_en   ;
+reg sda_oe      ;
+reg sda_oe_en   ;
+
+reg sda_i_reg_en    ;
+reg sda_i_reg       ;
+
+always@(posedge clk_i or posedge reset_i)
+begin
+    if (reset_i)
+    begin
+        clk_gen_cnt <= 'h0  ;
+
+        tx_rx_state <= tx_rx_idle   ;
+
+    `ifdef ACTIVE_LOW_OE
+        pci_spoci_sda_oe_o <= 1'b1 ;
+        pci_spoci_scl_oe_o <= 1'b1 ;
+    `endif
+
+    `ifdef ACTIVE_HIGH_OE
+        pci_spoci_sda_oe_o <= 1'b0 ;
+        pci_spoci_scl_oe_o <= 1'b0 ;
+    `endif
+
+        sda_i_reg <= 1'b1 ;
+    end
+    else
+    begin
+        tx_rx_state <= tx_rx_next_state ;
+        
+        if (clk_gen_cnt_clr)
+            clk_gen_cnt <= 'h0  ;
+        else if (clk_gen_cnt_en)
+            clk_gen_cnt <= clk_gen_cnt + 1'b1 ;
+
+    
+        if (sda_oe_en)
+        begin
+        `ifdef ACTIVE_LOW_OE
+            pci_spoci_sda_oe_o <= ~sda_oe   ;
+        `endif
+
+        `ifdef ACTIVE_HIGH_OE
+            pci_spoci_sda_oe_o <= sda_oe    ;
+        `endif
+        end
+
+        if (scl_oe_en)
+        begin
+        `ifdef ACTIVE_LOW_OE
+            pci_spoci_scl_oe_o <= ~scl_oe   ;
+        `endif
+
+        `ifdef ACTIVE_HIGH_OE
+            pci_spoci_scl_oe_o <= scl_oe    ;
+        `endif
+        end
+
+        if (sda_i_reg_en)
+            sda_i_reg <= pci_spoci_sda_i ;
+    end
+end
+
+reg [ 7: 0] tx_shift_reg ;
+
+reg send_start  ;
+reg start_sent  ;
+
+reg send_bit    ;
+reg bit_sent    ;
+
+reg rec_bit     ;
+reg bit_rec     ;
+
+reg rec_ack     ;
+reg ack_rec     ;
+reg nack_rec    ;
+
+reg send_ack    ;
+reg ack_sent    ;
+reg send_nack   ;
+reg nack_sent   ;
+
+reg send_stop   ;
+reg stop_sent   ;
+
+always@
+(
+    tx_rx_state     or
+    clk_gen_cnt     or
+    send_start      or
+    send_bit        or
+    tx_shift_reg    or
+    send_stop       or
+    rec_ack         or
+    sda_i_reg       or
+    rec_bit         or
+    send_ack        or
+    send_nack
+)
+begin
+    clk_gen_cnt_clr     = 1'b0          ;
+    clk_gen_cnt_en      = 1'b0          ;
+    tx_rx_next_state    = tx_rx_state   ;
+    tx_rx_sm_idle       = 1'b0          ;
+    scl_oe              = 1'b0          ;
+    sda_oe              = 1'b0          ;
+    scl_oe_en           = 1'b0          ;
+    sda_oe_en           = 1'b0          ;
+    start_sent          = 1'b0          ;
+    bit_sent            = 1'b0          ;
+    ack_rec             = 1'b0          ;
+    nack_rec            = 1'b0          ;
+    sda_i_reg_en        = 1'b0          ;
+    stop_sent           = 1'b0          ;
+    bit_rec             = 1'b0          ;
+    ack_sent            = 1'b0          ;
+    nack_sent           = 1'b0          ;
+
+    case (tx_rx_state)
+
+    tx_rx_idle:
+    begin
+        tx_rx_sm_idle = 1'b1 ;
+
+        // from idle state, the only transition can be to the send start bit
+        if (send_start)
+        begin
+            tx_rx_next_state = tx_rx_start  ;
+            clk_gen_cnt_clr  = 1'b1         ;
+        end
+    end
+
+    tx_rx_start:
+    begin
+        clk_gen_cnt_en  = 1'b1  ;
+        sda_oe          = 1'b1  ;
+
+        // start bit is sent by transmiting 0 on the sda line
+        if (clk_gen_cnt == (period_cnt >> 1))
+        begin
+            start_sent = 1'b1 ;
+            sda_oe_en  = 1'b1 ;
+        end
+        
+        // after half clock period of driving the sda low, the only possible
+        // transition is to send state.
+        // if send bit is not active, stop the procedure - undrive sda
+        if (clk_gen_cnt == period_cnt)
+        begin
+            clk_gen_cnt_clr = 1'b1 ;
+            if (send_bit)
+            begin
+                tx_rx_next_state = tx_rx_send_bits ;
+            end
+            else
+            begin
+                sda_oe              = 1'b0          ;
+                sda_oe_en           = 1'b1          ;
+                tx_rx_next_state    = tx_rx_idle    ;
+            end
+        end
+    end
+
+    tx_rx_send_bits:
+    begin
+        clk_gen_cnt_en = 1'b1 ;
+
+        // generate high to low transition on the scl line immediately
+        if (clk_gen_cnt == 'h0)
+        begin
+            scl_oe      = 1'b1  ;
+            scl_oe_en   = 1'b1  ;
+        end
+
+        // after half of clock low time, load new value for sda oe, depending on the
+        // msb bit in the shift register
+        if (clk_gen_cnt == (period_cnt >> 2))
+        begin
+            sda_oe      = ~tx_shift_reg[7]  ;
+            sda_oe_en   = 1'b1              ;
+            bit_sent    = 1'b1              ;
+        end
+
+        // after clock low time, generate low to high transition on the scl line
+        if (clk_gen_cnt == (period_cnt >> 1))
+        begin
+            scl_oe      = 1'b0  ;
+            scl_oe_en   = 1'b1  ;
+        end
+
+        // after clock high time, check what to do next
+        if (clk_gen_cnt == (period_cnt))
+        begin
+            clk_gen_cnt_clr = 1'b1 ;
+
+            if (~send_bit)
+            begin
+                // after transmiting all the bits, the only possible transition is to the state
+                // that checks the eprom acknowledge
+                if (rec_ack)
+                    tx_rx_next_state = tx_rx_rec_ack ;
+                else
+                begin
+                    sda_oe              = 1'b0          ;
+                    sda_oe_en           = 1'b1          ;
+                    tx_rx_next_state    = tx_rx_idle    ;
+                end
+            end
+        end
+    end
+
+    tx_rx_rec_bits:
+    begin
+        clk_gen_cnt_en = 1'b1 ;
+        sda_i_reg_en   = 1'b1 ;
+
+        // generate high to low transition on the scl line immediately
+        if (clk_gen_cnt == 'h0)
+        begin
+            scl_oe      = 1'b1  ;
+            scl_oe_en   = 1'b1  ;
+        end
+
+        // after half of clock low time, disable sda driver
+        if (clk_gen_cnt == (period_cnt >> 2))
+        begin
+            sda_oe      = 1'b0  ;
+            sda_oe_en   = 1'b1  ;
+        end
+
+        // after clock low time, generate low to high transition on the scl line
+        if (clk_gen_cnt == (period_cnt >> 1))
+        begin
+            scl_oe      = 1'b0  ;
+            scl_oe_en   = 1'b1  ;
+        end
+
+        // after half of clock high time, report received bit
+        if (clk_gen_cnt == ((period_cnt >> 1) + (period_cnt >> 2)) )
+        begin
+            bit_rec = 1'b1  ;
+        end
+
+        // after clock period is finished, check the next operation
+        if (clk_gen_cnt == (period_cnt))
+        begin
+            clk_gen_cnt_clr = 1'b1 ;
+
+            if (~rec_bit)
+            begin
+                // when all bits are received, only nack or ack next states are possible
+                if (send_ack)
+                    tx_rx_next_state = tx_rx_send_ack   ;
+                else if (send_nack)
+                    tx_rx_next_state = tx_rx_send_nack  ;
+                else
+                begin
+                    tx_rx_next_state = tx_rx_idle    ;
+                end
+            end
+        end
+    end
+
+    tx_rx_send_ack:
+    begin
+        clk_gen_cnt_en  = 1'b1  ;
+
+        // generate high to low transition on the scl line
+        if (clk_gen_cnt == 'h0)
+        begin
+            scl_oe      = 1'b1  ;
+            scl_oe_en   = 1'b1  ;
+        end
+
+        // after half of clock low time, enable the sda driver
+        if (clk_gen_cnt == (period_cnt >> 2))
+        begin
+            sda_oe      = 1'b1  ;
+            sda_oe_en   = 1'b1  ;
+            ack_sent    = 1'b1  ;
+        end
+
+        // after clock low time, disable the scl driver - generate low to high transition on the scl line
+        if (clk_gen_cnt == (period_cnt >> 1))
+        begin
+            scl_oe      = 1'b0  ;
+            scl_oe_en   = 1'b1  ;
+        end
+
+        // after clock period time expires, check what to do next
+        if (clk_gen_cnt == period_cnt)
+        begin
+            clk_gen_cnt_clr = 1'b1 ;
+
+            // after the byte is acknowledged, the only possible next state is receive bits
+            // state
+            if (rec_bit)
+                tx_rx_next_state = tx_rx_rec_bits   ;
+            else
+            begin
+                // this should never happen
+                sda_oe      = 1'b0  ;
+                sda_oe_en   = 1'b1  ;
+
+                tx_rx_next_state = tx_rx_idle ;
+            end
+        end
+    end
+
+    tx_rx_rec_ack:
+    begin
+
+        clk_gen_cnt_en  = 1'b1  ;
+        sda_i_reg_en    = 1'b1  ;
+
+        // generate high to low transition on the scl line
+        if (clk_gen_cnt == 'h0)
+        begin
+            scl_oe      = 1'b1  ;
+            scl_oe_en   = 1'b1  ;
+        end
+
+        // after half of clock low time, disable the sda driver
+        if (clk_gen_cnt == (period_cnt >> 2))
+        begin
+            sda_oe      = 1'b0  ;
+            sda_oe_en   = 1'b1  ;
+        end
+
+        // after clock low time, disable the scl driver - generate low to high transition on the scl line
+        if (clk_gen_cnt == (period_cnt >> 1))
+        begin
+            scl_oe      = 1'b0  ;
+            scl_oe_en   = 1'b1  ;
+        end
+
+        // after 1/2 clock high time, report ack or nack condition, depending on the sda input state
+        if (clk_gen_cnt == ((period_cnt >> 1) + (period_cnt >> 2)) )
+        begin
+            ack_rec     = ~sda_i_reg ;
+            nack_rec    =  sda_i_reg ;
+        end
+
+        // after clock period time expires, check what to do next
+        if (clk_gen_cnt == period_cnt)
+        begin
+            clk_gen_cnt_clr = 1'b1 ;
+
+            if (send_bit)
+                tx_rx_next_state = tx_rx_send_bits  ;
+            else if (rec_bit)
+                tx_rx_next_state = tx_rx_rec_bits   ;
+            else if (send_stop)
+                tx_rx_next_state = tx_rx_stop       ;
+            else if (send_start)
+                tx_rx_next_state = tx_rx_restart    ;
+            else
+            begin
+                // this should never happen
+                tx_rx_next_state = tx_rx_idle ;
+            end
+        end
+    end
+
+    tx_rx_send_nack:
+    begin
+        clk_gen_cnt_en  = 1'b1  ;
+
+        // generate high to low transition on the scl line
+        if (clk_gen_cnt == 'h0)
+        begin
+            scl_oe      = 1'b1  ;
+            scl_oe_en   = 1'b1  ;
+        end
+
+        // after half of clock low time, disable the sda driver
+        if (clk_gen_cnt == (period_cnt >> 2))
+        begin
+            sda_oe      = 1'b0  ;
+            sda_oe_en   = 1'b1  ;
+            nack_sent   = 1'b1  ;
+        end
+
+        // after clock low time, disable the scl driver - generate low to high transition on the scl line
+        if (clk_gen_cnt == (period_cnt >> 1))
+        begin
+            scl_oe      = 1'b0  ;
+            scl_oe_en   = 1'b1  ;
+        end
+
+        // after clock period time expires, check what to do next
+        if (clk_gen_cnt == period_cnt)
+        begin
+            clk_gen_cnt_clr = 1'b1 ;
+
+            // after the no acknowledge is sent, the only possible next state is stop
+            // state
+            if (send_stop)
+                tx_rx_next_state = tx_rx_stop   ;
+            else
+            begin
+                // this should never happen
+                tx_rx_next_state = tx_rx_idle ;
+            end
+        end
+    end
+
+    tx_rx_restart:
+    begin
+        clk_gen_cnt_en = 1'b1 ;
+
+        // generate high to low transition
+        if (clk_gen_cnt == 'h0)
+        begin
+            scl_oe      = 1'b1  ;
+            scl_oe_en   = 1'b1  ;
+        end
+
+        // after half of clock low time, release sda line
+        if (clk_gen_cnt == (period_cnt >> 2))
+        begin
+            sda_oe      = 1'b0  ;
+            sda_oe_en   = 1'b1  ;
+        end
+
+        // generate low to high transition
+        if (clk_gen_cnt == (period_cnt >> 1))
+        begin
+            clk_gen_cnt_clr = 1'b1 ;
+
+            scl_oe      = 1'b0  ;
+            scl_oe_en   = 1'b1  ;
+
+            if (send_start)
+                tx_rx_next_state = tx_rx_start ;
+            else
+                tx_rx_next_state = tx_rx_idle ;
+        end
+    end
+
+    tx_rx_stop:
+    begin
+        clk_gen_cnt_en = 1'b1 ;
+
+        // generate high to low transition
+        if (clk_gen_cnt == 'h0)
+        begin
+            scl_oe      = 1'b1  ;
+            scl_oe_en   = 1'b1  ;
+        end
+
+        // after half of clock low time, drive sda line low
+        if (clk_gen_cnt == (period_cnt >> 2))
+        begin
+            sda_oe      = 1'b1  ;
+            sda_oe_en   = 1'b1  ;
+        end
+
+        // generate low to high transition
+        if (clk_gen_cnt == (period_cnt >> 1))
+        begin
+            scl_oe      = 1'b0  ;
+            scl_oe_en   = 1'b1  ;
+        end
+
+        // after full clock period, release the sda line
+        if (clk_gen_cnt == period_cnt)
+        begin
+            sda_oe      = 1'b0  ;
+            sda_oe_en   = 1'b1  ;
+            stop_sent   = 1'b1  ;
+
+            tx_rx_next_state = tx_rx_idle ;
+        end
+    end
+
+    endcase
+end
+
+reg [rw_seq_state_width - 1:0]  rw_seq_state    ;
+
+reg doing_read      , 
+    doing_write     , 
+    doing_seq_read  ,
+    adr_set         ;
+
+reg [ 3: 0] bits_transfered ;
+
+always@(posedge clk_i or posedge reset_i)
+begin
+    if (reset_i)
+    begin
+        rw_seq_state    <= rw_seq_idle  ;
+        adr_set         <= 1'b0         ;
+        doing_read      <= 1'b0         ;
+        doing_write     <= 1'b0         ;
+        doing_seq_read  <= 1'b0         ;
+        dat_o           <= 'h0          ;
+        tx_shift_reg    <= 'h0          ;
+        send_start      <= 'h0          ;
+        send_stop       <= 'h0          ;
+        send_bit        <= 'h0          ;
+        send_nack       <= 'h0          ;
+        rec_ack         <= 'h0          ;
+        no_ack_o        <= 'h0          ;
+        bits_transfered <= 'h0          ;
+        write_done_o    <= 'h0          ;
+        dat_rdy_o       <= 'h0          ;
+        send_ack        <= 'h0          ;
+        rec_bit         <= 'h0          ;
+    end
+    else
+    begin
+
+        case (rw_seq_state)
+            
+        rw_seq_idle:
+        begin
+            tx_shift_reg <= {4'b1010, adr_i[10: 8], 1'b0} ;
+            adr_set      <= 1'b0                          ;
+
+            if ( tx_rx_sm_idle & ~(doing_write | doing_read | doing_seq_read) )
+            begin
+                if (do_write_i | do_rnd_read_i | do_seq_read_i)
+                begin
+                    rw_seq_state <= rw_seq_tx_ctrl  ;
+                    send_start   <= 1'b1            ;
+                end
+
+                if (do_write_i)
+                    doing_write     <= 1'b1 ;
+                else if (do_rnd_read_i)
+                    doing_read      <= 1'b1 ;
+                else if (do_seq_read_i)
+                    doing_seq_read  <= 1'b1 ;
+            end
+            else
+            begin
+                doing_write     <= 1'b0 ;
+                doing_read      <= 1'b0 ;
+                doing_seq_read  <= 1'b0 ;
+            end
+        end
+    
+        rw_seq_tx_ctrl:
+        begin
+            if (send_start)
+            begin
+                bits_transfered <= 'h0 ;
+
+                if (start_sent)
+                begin
+                    send_start <= 1'b0 ;
+                    send_bit   <= 1'b1 ;
+                end
+            end
+            else if (send_bit)
+            begin
+                if (bit_sent)
+                begin
+                    bits_transfered <= bits_transfered + 1'b1 ;
+                    tx_shift_reg <= {tx_shift_reg[6:0], tx_shift_reg[0]} ;
+                end
+
+                if (bits_transfered == 'h8)
+                begin
+                    send_bit <= 1'b0 ;
+                    rec_ack  <= 1'b1 ;
+                end
+            end
+            else if (rec_ack)
+            begin
+                bits_transfered <= 'h0 ;
+
+                if (ack_rec | nack_rec)
+                    rec_ack <= 1'b0 ;
+
+                if (ack_rec)
+                begin
+                    if (doing_write | ~adr_set)
+                    begin
+                        rw_seq_state    <= rw_seq_tx_adr    ;
+                        tx_shift_reg    <= adr_i[ 7: 0]     ;
+                        send_bit        <= 1'b1             ;
+                    end
+                    else
+                    begin
+                        rw_seq_state    <= rw_seq_rx_byte   ;
+                        rec_bit         <= 1'b1             ;
+                    end
+                end
+                else if (nack_rec)
+                begin
+                    no_ack_o    <= 1'b1 ;
+                    send_stop   <= 1'b1 ;
+                end
+            end
+            else if (send_stop)
+            begin
+                no_ack_o <= 1'b0 ;
+
+                if (stop_sent)
+                begin
+                    send_stop       <= 1'b0         ;
+                    rw_seq_state    <= rw_seq_idle  ;
+                end
+            end
+        end
+    
+        rw_seq_tx_adr:
+        begin
+            if (send_bit)
+            begin
+                if (bit_sent)
+                begin
+                    bits_transfered <= bits_transfered + 1'b1 ;
+                    tx_shift_reg <= {tx_shift_reg[6:0], tx_shift_reg[0]} ;
+                end
+
+                if (bits_transfered == 'h8)
+                begin
+                    send_bit <= 1'b0 ;
+                    rec_ack  <= 1'b1 ;
+                end
+            end
+            else if (rec_ack)
+            begin
+                bits_transfered <= 'h0 ;
+
+                if (ack_rec | nack_rec)
+                    rec_ack <= 1'b0 ;
+
+                if (ack_rec)
+                begin
+
+                    adr_set <= 1'b1 ;
+
+                    if (doing_write)
+                    begin
+                        send_bit        <= 1'b1             ;
+                        rw_seq_state    <= rw_seq_tx_byte   ;
+                        tx_shift_reg    <= dat_i            ;
+                    end
+                    else if (doing_read | doing_seq_read)
+                    begin
+                        send_start      <= 1'b1             ;
+                        rw_seq_state    <= rw_seq_tx_ctrl   ;
+                        tx_shift_reg    <= 8'b10100001      ;
+                    end
+                end
+                else if (nack_rec)
+                begin
+                    no_ack_o    <= 1'b1 ;
+                    send_stop   <= 1'b1 ;
+                end
+            end
+            else if (send_stop)
+            begin
+                no_ack_o    <= 1'b0 ;
+
+                if (stop_sent)
+                begin
+                    send_stop       <= 1'b0         ;
+                    rw_seq_state    <= rw_seq_idle  ;
+                end
+            end
+        end
+    
+        rw_seq_tx_byte:
+        begin
+            if (send_bit)
+            begin
+                if (bit_sent)
+                begin
+                    bits_transfered <= bits_transfered + 1'b1 ;
+                    tx_shift_reg <= {tx_shift_reg[6:0], tx_shift_reg[0]} ;
+                end
+
+                if (bits_transfered == 'h8)
+                begin
+                    send_bit <= 1'b0 ;
+                    rec_ack  <= 1'b1 ;
+                end
+            end
+            else if (rec_ack)
+            begin
+                bits_transfered <= 'h0 ;
+
+                if (ack_rec | nack_rec)
+                begin
+                    rec_ack   <= 1'b0   ;
+                    send_stop <= 1'b1   ;
+                end
+
+                if (nack_rec)
+                    no_ack_o <= 1'b1 ;
+
+                if (ack_rec)
+                    write_done_o <= 1'b1 ;
+            end
+            else if (send_stop)
+            begin
+                no_ack_o        <= 1'b0 ;
+                write_done_o    <= 1'b0 ;
+
+                if (stop_sent)
+                begin
+                    send_stop       <= 1'b0         ;
+                    rw_seq_state    <= rw_seq_idle  ;
+                end
+            end
+        end
+    
+        rw_seq_rx_byte:
+        begin
+            if (rec_bit)
+            begin
+                if (bit_rec)
+                begin
+                    bits_transfered <= bits_transfered + 1'b1   ;
+                    dat_o           <= {dat_o[6:0], sda_i_reg}  ;
+                end
+
+                if (bits_transfered == 'h8)
+                begin
+                    rec_bit   <= 1'b0 ;
+                    dat_rdy_o <= 1'b1 ;
+                    if (doing_read)
+                        send_nack <= 1'b1 ;
+                    else
+                        send_ack  <= 1'b1 ;
+                end
+            end
+            else if (send_nack)
+            begin
+                dat_rdy_o       <= 1'b0 ;
+                bits_transfered <= 'h0  ;
+
+                if (nack_sent)
+                begin
+                    send_stop <= 1'b1 ;
+                    send_nack <= 1'b0 ;
+                end
+            end
+            else if (send_ack)
+            begin
+                dat_rdy_o       <= 1'b0 ;
+                bits_transfered <= 'h0  ;
+
+                if (~do_seq_read_i)
+                begin
+                    send_ack    <= 1'b0 ;
+                    send_nack   <= 1'b1 ;
+                end
+                else if (ack_sent)
+                begin
+                    send_ack <= 1'b0 ;
+                    rec_bit  <= 1'b1 ;
+                end
+            end
+            else if (send_stop)
+            begin
+                if (stop_sent)  
+                begin
+                    send_stop       <= 1'b0         ;
+                    rw_seq_state    <= rw_seq_idle  ;
+                end
+            end
+        end
+        endcase
+    end
+end
+
+endmodule // pci_spoci_ctrl
\ No newline at end of file
Impressum, Datenschutz