data/full_repos/permissive/190755935/src/comms/rtl/i2c_master_core.v
1: b'%Error: data/full_repos/permissive/190755935/src/comms/rtl/i2c_master_core.v:69: Cannot find include file: ../../pipe/rtl/pipe_defs.v\n`include "../../pipe/rtl/pipe_defs.v" \n         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/190755935/src/comms/rtl,data/full_repos/permissive/190755935/../../pipe/rtl/pipe_defs.v\n             data/full_repos/permissive/190755935/src/comms/rtl,data/full_repos/permissive/190755935/../../pipe/rtl/pipe_defs.v.v\n             data/full_repos/permissive/190755935/src/comms/rtl,data/full_repos/permissive/190755935/../../pipe/rtl/pipe_defs.v.sv\n             ../../pipe/rtl/pipe_defs.v\n             ../../pipe/rtl/pipe_defs.v.v\n             ../../pipe/rtl/pipe_defs.v.sv\n             obj_dir/../../pipe/rtl/pipe_defs.v\n             obj_dir/../../pipe/rtl/pipe_defs.v.v\n             obj_dir/../../pipe/rtl/pipe_defs.v.sv\n%Error: data/full_repos/permissive/190755935/src/comms/rtl/i2c_master_core.v:72: Define or directive not defined: \'`PS_d8\'\n        parameter PipeSpec = `PS_d8,\n                             ^~~~~~\n%Error: data/full_repos/permissive/190755935/src/comms/rtl/i2c_master_core.v:72: syntax error, unexpected \',\', expecting TYPE-IDENTIFIER\n        parameter PipeSpec = `PS_d8,\n                                   ^\n%Error: data/full_repos/permissive/190755935/src/comms/rtl/i2c_master_core.v:74: syntax error, unexpected \')\', expecting \';\'\n    ) (\n    ^\n%Error: data/full_repos/permissive/190755935/src/comms/rtl/i2c_master_core.v:78: Define or directive not defined: \'`P_Data_w\'\n        input [`P_Data_w(PipeSpec)-1:0]  slave_address,     \n               ^~~~~~~~~\n%Error: data/full_repos/permissive/190755935/src/comms/rtl/i2c_master_core.v:79: Define or directive not defined: \'`P_Data_w\'\n        input [`P_Data_w(PipeSpec):0]    read_count,        \n               ^~~~~~~~~\n%Error: data/full_repos/permissive/190755935/src/comms/rtl/i2c_master_core.v:89: Define or directive not defined: \'`P_Data_w\'\n        output [`P_Data_w(PipeSpec)-1:0] write_count,       \n                ^~~~~~~~~\n%Error: data/full_repos/permissive/190755935/src/comms/rtl/i2c_master_core.v:91: Define or directive not defined: \'`P_w\'\n        inout [`P_w(PipeSpec)-1:0]       pipe_in,\n               ^~~~\n%Error: data/full_repos/permissive/190755935/src/comms/rtl/i2c_master_core.v:92: Define or directive not defined: \'`P_w\'\n        inout [`P_w(PipeSpec)-1:0]       pipe_out,\n               ^~~~\n%Error: data/full_repos/permissive/190755935/src/comms/rtl/i2c_master_core.v:95: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n        input                            scl_in,\n        ^~~~~\n%Error: data/full_repos/permissive/190755935/src/comms/rtl/i2c_master_core.v:97: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n        input                            sda_in,\n        ^~~~~\n%Error: data/full_repos/permissive/190755935/src/comms/rtl/i2c_master_core.v:115: Define or directive not defined: \'`P_Data_w\'\n    localparam DataWidth = `P_Data_w( PipeSpec );\n                           ^~~~~~~~~\n%Error: data/full_repos/permissive/190755935/src/comms/rtl/i2c_master_core.v:141: syntax error, unexpected IDENTIFIER\n    p_unpack_start_stop  #( .PipeSpec( PipeSpec ) ) p_up_ss( .pipe(pipe_in), .start( in_start), .stop( in_stop) );\n    ^~~~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/190755935/src/comms/rtl/i2c_master_core.v:151: syntax error, unexpected IDENTIFIER\n    p_pack_ssdvrp #( .PipeSpec( PipeSpec ) ) out_pack( .start(out_start), .stop(out_stop), .data(out_data), .valid(out_valid), .ready(out_ready), .pipe(pipe_out) );\n    ^~~~~~~~~~~~~\n%Error: data/full_repos/permissive/190755935/src/comms/rtl/i2c_master_core.v:160: syntax error, unexpected always\n    always @(posedge clock) begin\n    ^~~~~~\n%Error: data/full_repos/permissive/190755935/src/comms/rtl/i2c_master_core.v:202: syntax error, unexpected assign\n    assign in_ready = ( i2cm_state == I2CM_ADDRESS ) ||\n    ^~~~~~\n%Error: data/full_repos/permissive/190755935/src/comms/rtl/i2c_master_core.v:233: syntax error, unexpected always\n    always @(posedge clock) begin\n    ^~~~~~\n%Error: data/full_repos/permissive/190755935/src/comms/rtl/i2c_master_core.v:745: syntax error, unexpected always\n    always @( posedge clock ) begin\n    ^~~~~~\n%Error: Exiting due to 18 error(s)\n'
module i2c_master_core #(
        parameter PipeSpec = `PS_d8,
        parameter ClockCount = 200
    ) (
        input clock,
        input reset,

        input [`P_Data_w(PipeSpec)-1:0]  slave_address,
        input [`P_Data_w(PipeSpec):0]    read_count,
        input [2:0]                      operation,
        input                            send_address,
        input                            send_operation,
        input                            send_write_count,

        input                            start_operation,

        output                           complete,
        output                           error,
        output [`P_Data_w(PipeSpec)-1:0] write_count,

        inout [`P_w(PipeSpec)-1:0]       pipe_in,
        inout [`P_w(PipeSpec)-1:0]       pipe_out,

        output reg [0:0]                 scl_out,
        input                            scl_in,
        output reg [0:0]                 sda_out,
        input                            sda_in,

        output [7:0] debug
    );




    localparam OperationWrite     =  0;
    localparam OperationRead      =  1;
    localparam OperationWriteRead =  2;
    localparam OperationInPipe    = -1;

    localparam ClockCountWidth = $clog2( ClockCount + 1 ) + 1;

    reg [ClockCountWidth:0] clock_counter;
    wire clock_counter_expired = clock_counter[ ClockCountWidth ];

    localparam DataWidth = `P_Data_w( PipeSpec );
    localparam AddressWidth = DataWidth - 1;

    localparam BitCounterWidth = $clog2( DataWidth + 1 ) + 1;
    reg [BitCounterWidth-1:0] bit_counter;
    wire bit_counter_expired = bit_counter[ BitCounterWidth -1 ];


    wire slave_address_in_pipe = slave_address[ AddressWidth ];


    wire operation_in_pipe = operation[ 2 ];


    wire read_count_in_pipe = read_count[ DataWidth ];





    wire                 in_start;
    wire                 in_stop;
    wire [DataWidth-1:0] in_data;
    wire                 in_valid;
    wire in_ready;

    p_unpack_start_stop  #( .PipeSpec( PipeSpec ) ) p_up_ss( .pipe(pipe_in), .start( in_start), .stop( in_stop) );
    p_unpack_data        #( .PipeSpec( PipeSpec ) )  p_up_d( .pipe(pipe_in), .data( in_data) );
    p_unpack_valid_ready #( .PipeSpec( PipeSpec ) ) p_up_vr( .pipe(pipe_in), .valid( in_valid), .ready( in_ready) );

    wire                 out_start;
    wire                 out_stop;
    wire [DataWidth-1:0] out_data;
    wire                 out_valid;
    wire                 out_ready;

    p_pack_ssdvrp #( .PipeSpec( PipeSpec ) ) out_pack( .start(out_start), .stop(out_stop), .data(out_data), .valid(out_valid), .ready(out_ready), .pipe(pipe_out) );





    reg scl_in_1;
    reg sda_in_1;

    always @(posedge clock) begin

        scl_in_1 <= scl_in;
        sda_in_1 <= sda_in;

    end

    reg [DataWidth-1:0] transfer_word;



    localparam I2CM_IDLE =            0,
               I2CM_ADDRESS =         1,
               I2CM_OPERATION =       2,
               I2CM_COUNT =           3,
               I2CM_START_TRIGGER =   4,
               I2CM_START =           5,
               I2CM_BITS =            6,
               I2CM_CLOCK_UP =        7,
               I2CM_CLOCK_DOWN =      8,
               I2CM_ACK_BIT =         9,
               I2CM_ACK_CLOCK_UP =   10,
               I2CM_ACK_CLOCK_DOWN = 11,
               I2CM_NEXT =           12,
               I2CM_REPORT_A =       13,
               I2CM_REPORT_B =       14,
               I2CM_DRAIN =          15,
               I2CM_ENDING1 =        16,
               I2CM_ENDING2 =        17,
               I2CM_STOP =           18;

    reg [4:0] i2cm_state;

    localparam I2CM_FUNCTION_IDLE = 0,
               I2CM_FUNCTION_ADDRESS = 1,
               I2CM_FUNCTION_COUNT = 2,
               I2CM_FUNCTION_READING = 3,
               I2CM_FUNCTION_WRITING = 4;

    reg [2:0] i2cm_function;


    assign in_ready = ( i2cm_state == I2CM_ADDRESS ) ||
                      ( i2cm_state == I2CM_OPERATION ) ||
                      ( i2cm_state == I2CM_COUNT ) ||
                      ( ( i2cm_state == I2CM_NEXT ) && !in_start ) ||
                      ( i2cm_state == I2CM_DRAIN );

    reg i2cm_ack;
    reg i2cm_start_required;
    reg i2cm_stop;

    reg [DataWidth-1:0] i2cm_address;

    reg [DataWidth-1:0] i2cm_word_counter;
    reg [DataWidth-1:0] i2cm_read_count;

    reg [DataWidth-1:0] i2cm_write_count;

    reg                 i2cm_complete;
    reg                 i2cm_error;

    reg                 i2cm_out_start;
    reg                 i2cm_out_stop;
    reg [DataWidth-1:0] i2cm_out_data;
    reg                 i2cm_out_valid;
    wire                i2cm_out_ready;

    reg                 i2cm_read;


    wire out_be_ready;

    always @(posedge clock) begin
        if ( reset ) begin
            clock_counter <= 0;
            scl_out <= 1;
            sda_out <= 1;
            i2cm_ack <= 0;
            i2cm_start_required <= 0;
            i2cm_stop <= 0;
            i2cm_state <= I2CM_IDLE;
            i2cm_function <= I2CM_FUNCTION_IDLE;
            i2cm_out_start <= 0;
            i2cm_out_stop <= 0;
            i2cm_out_data <= 0;
            i2cm_out_valid <= 0;
            i2cm_word_counter <= 0;
            i2cm_read_count <= 0;
            i2cm_read <= 0;
            i2cm_write_count <= 0;
            i2cm_complete <= 0;
            i2cm_error <= 0;
        end else begin
            case ( i2cm_state )
                I2CM_IDLE: begin
                        if ( ( in_valid && in_start ) || start_operation ) begin
                            i2cm_complete <= 0;
                            i2cm_error <= 0;
                            clock_counter <= ( ClockCount >> 2 ) - 'H2;
                            i2cm_start_required <= 1;
                            i2cm_function <= I2CM_FUNCTION_ADDRESS;
                            if ( slave_address_in_pipe ) begin

                                i2cm_state <= I2CM_ADDRESS;
                            end else begin
                                i2cm_address <= slave_address[ DataWidth-2:0];
                                if ( operation_in_pipe ) begin

                                    i2cm_state <= I2CM_OPERATION;
                                end else begin



                                    if ( operation == OperationRead ) begin

                                        transfer_word <= { slave_address[ DataWidth-2:0 ], 1'H1 };

                                        i2cm_read <= 1;
                                        if ( read_count_in_pipe ) begin
                                            i2cm_state <= I2CM_COUNT;
                                        end else begin
                                            sda_out <= 0;
                                            i2cm_read_count <= read_count;
                                            i2cm_state <= I2CM_START;
                                            i2cm_stop <= 1;
                                        end
                                    end else begin



                                        transfer_word <= { slave_address[ DataWidth-2:0 ], 1'H0 };
                                        i2cm_state <= I2CM_START;
                                        i2cm_read <= 0;

                                        sda_out <= 0;
                                    end
                                end
                            end
                        end
                    end
                I2CM_ADDRESS: begin
                        if ( in_valid && ( in_start == i2cm_start_required ) ) begin

                            if ( operation_in_pipe ) begin

                                i2cm_address <= in_data[ DataWidth-1:1];
                                i2cm_read <= in_data[ 0 ];
                                transfer_word <= in_data;
                            end else begin

                                i2cm_address <= in_data[ DataWidth-2:0];
                                transfer_word <= { in_data[ DataWidth-2:0 ], (operation == OperationRead) };
                                i2cm_read <= (operation == OperationRead);
                            end


                            sda_out <= 0;
                            i2cm_ack <= 0;

                            i2cm_start_required <= 0;


                            if ( ( (operation_in_pipe) && in_data[ 0 ] ) || ( operation == OperationRead ) ) begin

                                if ( read_count_in_pipe ) begin
                                    i2cm_state <= I2CM_COUNT;
                                end else begin
                                    i2cm_read_count <= read_count;
                                    i2cm_state <= I2CM_START;
                                    i2cm_stop <= 1;
                                end
                            end else begin

                                i2cm_stop <= in_stop;
                                i2cm_state <= I2CM_START;
                            end
                        end
                    end
                I2CM_OPERATION: begin
                        if ( in_valid && ( in_start == i2cm_start_required ) ) begin
                            i2cm_read <= in_data[ 0 ];

                            sda_out <= 0;
                            i2cm_ack <= 0;
                            transfer_word <= { i2cm_address[ DataWidth-2:0 ], in_data[ 0 ] };

                            i2cm_start_required <= 0;


                            if ( in_data[ 0 ] ) begin
                                if ( read_count_in_pipe ) begin
                                    i2cm_state <= I2CM_COUNT;
                                end else begin
                                    i2cm_read_count <= read_count;
                                    i2cm_state <= I2CM_START;
                                    i2cm_stop <= 1;
                                end
                            end else begin

                                i2cm_stop <= in_stop;
                                i2cm_state <= I2CM_START;
                            end
                        end
                    end
                I2CM_COUNT: begin
                        if ( in_valid && ( in_start == i2cm_start_required ) ) begin

                            sda_out <= 0;
                            i2cm_read_count <= in_data;
                            i2cm_state <= I2CM_START;
                            i2cm_stop <= 1;
                        end
                    end

                I2CM_START_TRIGGER: begin
                        if ( start_operation )
                            i2cm_state <= I2CM_START;
                    end
                I2CM_START: begin

                        if ( clock_counter_expired ) begin
                            if ( ~i2cm_read )
                                i2cm_write_count <= 0;

                            scl_out <= 0;
                            i2cm_state <= I2CM_BITS;
                            bit_counter <= DataWidth - 2;
                            clock_counter <= ( ClockCount >> 2 ) - 'H2;
                        end else begin
                            clock_counter <= clock_counter - (clock_counter_expired ? 0 : 1 );
                        end
                    end
                I2CM_BITS: begin

                        if ( i2cm_out_valid ) begin
                            i2cm_out_start <= 0;
                            i2cm_out_stop <= 0;
                            i2cm_out_data <= 0;
                            i2cm_out_valid <= 0;
                        end

                        if ( clock_counter_expired ) begin



                            if ( i2cm_function != I2CM_FUNCTION_READING ) begin
                                sda_out <= transfer_word[ DataWidth -1 ];
                                transfer_word <= { transfer_word, 1'H0 };
                            end else begin
                                sda_out <= 1;
                            end
                            i2cm_state <= I2CM_CLOCK_UP;
                            clock_counter <= ( ClockCount >> 2 ) - 'H2;
                        end else begin
                            clock_counter <= clock_counter - (clock_counter_expired ? 0 : 1 );
                        end
                    end
                I2CM_CLOCK_UP: begin

                        if ( clock_counter_expired ) begin

                            scl_out <= 1;

                            if ( scl_in_1 == 1 ) begin

                                if ( i2cm_function == I2CM_FUNCTION_READING ) begin

                                    transfer_word <= { transfer_word[ DataWidth-2:0], sda_in_1 };
                                end

                                clock_counter <= ( ClockCount >> 1 ) - 'H3;
                                i2cm_state <= I2CM_CLOCK_DOWN;
                            end
                        end else begin
                            clock_counter <= clock_counter - (clock_counter_expired ? 0 : 1 );
                        end
                    end
                I2CM_CLOCK_DOWN: begin

                        if ( clock_counter_expired ) begin
                            clock_counter <= ( ClockCount >> 2 ) - 'H2;
                            scl_out <= 0;
                            if ( bit_counter_expired ) begin
                                i2cm_state <= I2CM_ACK_BIT;
                            end else begin
                                i2cm_state <= I2CM_BITS;
                                bit_counter <= bit_counter - 1;
                            end
                        end else begin
                            clock_counter <= clock_counter - (clock_counter_expired ? 0 : 1 );
                        end
                    end
                I2CM_ACK_BIT: begin


                        if ( clock_counter_expired ) begin
                            clock_counter <= ( ClockCount >> 2 ) - 'H2;
                            if ( i2cm_function != I2CM_FUNCTION_READING ) begin
                                    sda_out <= 1;
                            end else begin

                                if ( i2cm_word_counter == ( i2cm_read_count - 1'H1 ) )
                                    sda_out <= 1;
                                else
                                    sda_out <= 0;
                            end
                            i2cm_state <= I2CM_ACK_CLOCK_UP;
                        end else begin
                            clock_counter <= clock_counter - (clock_counter_expired ? 0 : 1 );
                        end
                    end
                I2CM_ACK_CLOCK_UP: begin


                        if ( clock_counter_expired ) begin
                            clock_counter <= ( ClockCount >> 2 ) - 'H2;

                            scl_out <= 1;

                            if ( scl_in_1 == 1 ) begin

                                if ( i2cm_function != I2CM_FUNCTION_READING ) begin

                                    i2cm_ack <= ~sda_in_1;
                                end else begin


                                end



                                clock_counter <= ( ClockCount >> 1 ) - 'H3;
                                i2cm_state <= I2CM_ACK_CLOCK_DOWN;
                            end
                        end else begin
                            clock_counter <= clock_counter - (clock_counter_expired ? 0 : 1 );
                        end
                    end
                I2CM_ACK_CLOCK_DOWN: begin

                        if ( clock_counter_expired ) begin

                            case ( i2cm_function )
                                I2CM_FUNCTION_ADDRESS: begin

                                        scl_out <= 0;

                                        i2cm_word_counter <= 0;
                                        clock_counter <= ( ClockCount >> 2 ) - 'H2;
                                        bit_counter <= DataWidth - 2;
                                        if ( i2cm_ack ) begin

                                            if ( i2cm_read ) begin
                                                if ( out_be_ready ) begin

                                                    if ( send_address || send_operation ) begin
                                                        i2cm_out_start <= 1;
                                                        i2cm_out_stop <= 0;
                                                        if ( send_address && send_operation )
                                                            i2cm_out_data <= { i2cm_address, 1'H1 };
                                                        else begin
                                                            if ( send_address )
                                                                i2cm_out_data <= { 1'H0, i2cm_address };
                                                            else
                                                                i2cm_out_data <= 1'H1;
                                                        end
                                                        i2cm_out_valid <= 1;
                                                    end
                                                    i2cm_state <= I2CM_BITS;

                                                    i2cm_function <= ( i2cm_read ) ? I2CM_FUNCTION_READING : I2CM_FUNCTION_WRITING;
                                                end
                                            end else begin

                                                i2cm_function <= ( i2cm_read ) ? I2CM_FUNCTION_READING : I2CM_FUNCTION_WRITING;
                                                i2cm_state <= I2CM_NEXT;
                                            end
                                        end else begin


                                            i2cm_function <= ( i2cm_read ) ? I2CM_FUNCTION_READING : I2CM_FUNCTION_WRITING;
                                            i2cm_error <= 1;
                                            if ( i2cm_stop ) begin

                                                i2cm_state <= I2CM_REPORT_A;
                                            end else begin

                                                i2cm_state <= I2CM_DRAIN;
                                            end
                                        end
                                    end
                                I2CM_FUNCTION_READING: begin

                                        scl_out <= 0;

                                        if ( out_be_ready ) begin
                                            i2cm_out_start <= ( i2cm_word_counter == 0 ) && ~send_address && ~send_operation;
                                            i2cm_out_data <= transfer_word;
                                            i2cm_out_valid <= 1;
                                            i2cm_word_counter <= i2cm_word_counter + 1'H1;
                                            if ( i2cm_word_counter == ( i2cm_read_count - 1'H1 ) ) begin
                                                i2cm_out_stop <= 1;
                                                i2cm_complete <= 1;
                                                i2cm_state <= I2CM_ENDING1;
                                            end else begin
                                                i2cm_out_stop <= 0;
                                                transfer_word <= 0;
                                                i2cm_state <= I2CM_BITS;
                                            end
                                            clock_counter <= ( ClockCount >> 2 ) - 'H2;
                                            bit_counter <= DataWidth - 2;

                                        end



                                    end
                                I2CM_FUNCTION_WRITING: begin
                                        bit_counter <= DataWidth - 2;
                                        clock_counter <= ( ClockCount >> 2 ) - 'H2;
                                        scl_out <= 0;
                                        if ( i2cm_ack )
                                            i2cm_word_counter <= i2cm_word_counter + 1;
                                        else
                                            i2cm_error <= 1;

                                        if ( i2cm_stop ) begin

                                            i2cm_state <= I2CM_REPORT_A;
                                            i2cm_complete <= 1;
                                        end else begin
                                            if ( ~i2cm_ack ) begin
                                                i2cm_error <= 1;
                                                i2cm_state <= I2CM_DRAIN;
                                            end else begin
                                                i2cm_state <= I2CM_NEXT;
                                            end
                                        end
                                    end
                            endcase
                        end else begin
                            clock_counter <= clock_counter - (clock_counter_expired ? 0 : 1 );
                        end
                    end
                I2CM_NEXT: begin



                        if ( in_valid ) begin
                            if ( in_start ) begin




                                i2cm_state <= I2CM_REPORT_A;
                                clock_counter <= ( ClockCount >> 2 ) - 'H3;
                            end else begin
                                scl_out <= 0;
                                transfer_word <= in_data;
                                i2cm_stop <= in_stop;
                                i2cm_state <= I2CM_BITS;
                                clock_counter <= ( ClockCount >> 2 ) - 'H3;
                            end
                        end
                    end
                I2CM_REPORT_A: begin

                        i2cm_write_count <= i2cm_word_counter;
                        if ( out_be_ready ) begin

                            if ( send_address ) begin
                                if ( send_operation ) begin
                                    i2cm_out_data <= { i2cm_address, i2cm_read  };
                                end else begin
                                    i2cm_out_data <= { 1'H0, i2cm_address };
                                end
                                i2cm_out_start <= 1;
                                i2cm_out_valid <= 1;
                            end else begin
                                if ( send_operation ) begin
                                    i2cm_out_start <= 1;
                                    i2cm_out_data <= i2cm_read;
                                    i2cm_out_valid <= 1;
                                end
                            end

                            i2cm_out_stop = ( i2cm_read && i2cm_error ) || ( ~i2cm_read && ~send_write_count );
                            if ( i2cm_function == I2CM_FUNCTION_READING ) begin

                                i2cm_state <= I2CM_ENDING1;
                            end else begin

                                i2cm_state <= I2CM_REPORT_B;
                            end
                        end
                    end
                I2CM_REPORT_B: begin

                        if ( i2cm_out_valid ) begin
                            i2cm_out_start <= 0;
                            i2cm_out_stop <= 0;
                            i2cm_out_data <= 0;
                            i2cm_out_valid <= 0;
                        end else begin
                            if ( !send_write_count ) begin
                                i2cm_state <= I2CM_ENDING1;
                            end else begin
                                if ( out_be_ready ) begin
                                    i2cm_out_start <= ( ~send_address && ~send_operation );
                                    i2cm_out_data <= i2cm_word_counter;
                                    i2cm_out_valid <= 1;
                                    i2cm_out_stop <= 1;
                                    i2cm_state <= I2CM_ENDING1;
                                end
                            end
                        end
                    end
                I2CM_DRAIN: begin

                        if ( ~in_valid || ( in_valid && in_stop ) || i2cm_stop ) begin
                            i2cm_state <= I2CM_REPORT_A;
                        end
                    end
                I2CM_ENDING1: begin
                        i2cm_function <= I2CM_FUNCTION_IDLE;
                        if ( i2cm_out_valid ) begin
                            i2cm_out_start <= 0;
                            i2cm_out_stop <= 0;
                            i2cm_out_data <= 0;
                            i2cm_out_valid <= 0;
                        end

                        if ( clock_counter_expired ) begin
                            if ( ( in_valid && in_start ) )
                                sda_out <= 1;
                            else
                                sda_out <= 0;
                            i2cm_state <= I2CM_ENDING2;
                            clock_counter <= ( ClockCount >> 2 ) - 'H2;
                        end else begin
                            clock_counter <= clock_counter - (clock_counter_expired ? 0 : 1 );
                        end
                    end
                I2CM_ENDING2: begin

                        if ( clock_counter_expired ) begin
                            scl_out <= 1;
                            if ( scl_in_1 ) begin
                                i2cm_state <= I2CM_STOP;
                                clock_counter <= ( ClockCount >> 2 ) - 'H2;
                            end
                        end else begin
                            clock_counter <= clock_counter - (clock_counter_expired ? 0 : 1 );
                        end
                    end
                I2CM_STOP: begin
                        if ( clock_counter_expired ) begin
                            sda_out <= 1;
                            i2cm_state <= I2CM_IDLE;
                        end else begin
                            clock_counter <= clock_counter - (clock_counter_expired ? 0 : 1 );
                        end
                    end
                default: begin
                        i2cm_state <= I2CM_IDLE;
                    end

            endcase



        end
    end

    localparam I2CM_BE_IDLE = 0,
               I2CM_BE_BUSY = 1;

    reg i2cm_be_state;

    reg                 i2cm_out_start_store;
    reg                 i2cm_out_stop_store;
    reg [DataWidth-1:0] i2cm_out_data_store;
    reg                 i2cm_out_valid_store;

    always @( posedge clock ) begin
        if ( reset ) begin
            i2cm_be_state <= I2CM_BE_IDLE;
            i2cm_out_start_store <= 0;
            i2cm_out_stop_store <= 0;
            i2cm_out_data_store <= 0;
            i2cm_out_valid_store <= 0;
        end else begin
            case ( i2cm_be_state )
                I2CM_BE_IDLE: begin
                        if ( i2cm_out_valid ) begin
                            i2cm_out_start_store <= i2cm_out_start;
                            i2cm_out_stop_store <= i2cm_out_stop;
                            i2cm_out_data_store <= i2cm_out_data;
                            i2cm_out_valid_store <= 1;
                            i2cm_be_state <= I2CM_BE_BUSY;
                        end
                    end
                I2CM_BE_BUSY: begin
                        if ( out_ready ) begin
                            i2cm_out_start_store <= 0;
                            i2cm_out_stop_store <= 0;
                            i2cm_out_data_store <= 0;
                            i2cm_out_valid_store <= 0;
                            i2cm_be_state <= I2CM_BE_IDLE;
                        end
                    end
            endcase
        end
    end

    assign out_start = i2cm_out_start_store;
    assign out_stop = i2cm_out_stop_store;
    assign out_data = i2cm_out_data_store;
    assign out_valid = i2cm_out_valid_store;

    assign out_be_ready = ( i2cm_be_state == I2CM_BE_IDLE );

    assign write_count = i2cm_write_count;
    assign complete = i2cm_complete;
    assign error = i2cm_error;

    assign debug[3:0] = i2cm_state;

endmodule
module i2c_master_core #(
        parameter PipeSpec = `PS_d8,
        parameter ClockCount = 200
    ) (
        input clock,
        input reset,

        input [`P_Data_w(PipeSpec)-1:0]  slave_address,
        input [`P_Data_w(PipeSpec):0]    read_count,
        input [2:0]                      operation,
        input                            send_address,
        input                            send_operation,
        input                            send_write_count,

        input                            start_operation,

        output                           complete,
        output                           error,
        output [`P_Data_w(PipeSpec)-1:0] write_count,

        inout [`P_w(PipeSpec)-1:0]       pipe_in,
        inout [`P_w(PipeSpec)-1:0]       pipe_out,

        output reg [0:0]                 scl_out,
        input                            scl_in,
        output reg [0:0]                 sda_out,
        input                            sda_in,

        output [7:0] debug
    );





    localparam OperationWrite     =  0;
    localparam OperationRead      =  1;
    localparam OperationWriteRead =  2;
    localparam OperationInPipe    = -1;

    localparam ClockCountWidth = $clog2( ClockCount + 1 ) + 1;

    reg [ClockCountWidth:0] clock_counter;
    wire clock_counter_expired = clock_counter[ ClockCountWidth ];

    localparam DataWidth = `P_Data_w( PipeSpec );
    localparam AddressWidth = DataWidth - 1;

    localparam BitCounterWidth = $clog2( DataWidth + 1 ) + 1;
    reg [BitCounterWidth-1:0] bit_counter;
    wire bit_counter_expired = bit_counter[ BitCounterWidth -1 ];


    wire slave_address_in_pipe = slave_address[ AddressWidth ];


    wire operation_in_pipe = operation[ 2 ];


    wire read_count_in_pipe = read_count[ DataWidth ];





    wire                 in_start;
    wire                 in_stop;
    wire [DataWidth-1:0] in_data;
    wire                 in_valid;
    wire in_ready;

    p_unpack_start_stop  #( .PipeSpec( PipeSpec ) ) p_up_ss( .pipe(pipe_in), .start( in_start), .stop( in_stop) );
    p_unpack_data        #( .PipeSpec( PipeSpec ) )  p_up_d( .pipe(pipe_in), .data( in_data) );
    p_unpack_valid_ready #( .PipeSpec( PipeSpec ) ) p_up_vr( .pipe(pipe_in), .valid( in_valid), .ready( in_ready) );

    wire                 out_start;
    wire                 out_stop;
    wire [DataWidth-1:0] out_data;
    wire                 out_valid;
    wire                 out_ready;

    p_pack_ssdvrp #( .PipeSpec( PipeSpec ) ) out_pack( .start(out_start), .stop(out_stop), .data(out_data), .valid(out_valid), .ready(out_ready), .pipe(pipe_out) );





    reg scl_in_1;
    reg sda_in_1;

    always @(posedge clock) begin

        scl_in_1 <= scl_in;
        sda_in_1 <= sda_in;

    end

    reg [DataWidth-1:0] transfer_word;



    localparam I2CM_IDLE =            0,
               I2CM_ADDRESS =         1,
               I2CM_OPERATION =       2,
               I2CM_COUNT =           3,
               I2CM_START_TRIGGER =   4,
               I2CM_START =           5,
               I2CM_BITS =            6,
               I2CM_CLOCK_UP =        7,
               I2CM_CLOCK_DOWN =      8,
               I2CM_ACK_BIT =         9,
               I2CM_ACK_CLOCK_UP =   10,
               I2CM_ACK_CLOCK_DOWN = 11,
               I2CM_NEXT =           12,
               I2CM_REPORT_A =       13,
               I2CM_REPORT_B =       14,
               I2CM_DRAIN =          15,
               I2CM_ENDING1 =        16,
               I2CM_ENDING2 =        17,
               I2CM_STOP =           18;

    reg [4:0] i2cm_state;

    localparam I2CM_FUNCTION_IDLE = 0,
               I2CM_FUNCTION_ADDRESS = 1,
               I2CM_FUNCTION_COUNT = 2,
               I2CM_FUNCTION_READING = 3,
               I2CM_FUNCTION_WRITING = 4;

    reg [2:0] i2cm_function;


    assign in_ready = ( i2cm_state == I2CM_ADDRESS ) ||
                      ( i2cm_state == I2CM_OPERATION ) ||
                      ( i2cm_state == I2CM_COUNT ) ||
                      ( ( i2cm_state == I2CM_NEXT ) && !in_start ) ||
                      ( i2cm_state == I2CM_DRAIN );

    reg i2cm_ack;
    reg i2cm_start_required;
    reg i2cm_stop;

    reg [DataWidth-1:0] i2cm_address;

    reg [DataWidth-1:0] i2cm_word_counter;
    reg [DataWidth-1:0] i2cm_read_count;

    reg [DataWidth-1:0] i2cm_write_count;

    reg                 i2cm_complete;
    reg                 i2cm_error;

    reg                 i2cm_out_start;
    reg                 i2cm_out_stop;
    reg [DataWidth-1:0] i2cm_out_data;
    reg                 i2cm_out_valid;
    wire                i2cm_out_ready;

    reg                 i2cm_read;


    wire out_be_ready;

    always @(posedge clock) begin
        if ( reset ) begin
            clock_counter <= 0;
            scl_out <= 1;
            sda_out <= 1;
            i2cm_ack <= 0;
            i2cm_start_required <= 0;
            i2cm_stop <= 0;
            i2cm_state <= I2CM_IDLE;
            i2cm_function <= I2CM_FUNCTION_IDLE;
            i2cm_out_start <= 0;
            i2cm_out_stop <= 0;
            i2cm_out_data <= 0;
            i2cm_out_valid <= 0;
            i2cm_word_counter <= 0;
            i2cm_read_count <= 0;
            i2cm_read <= 0;
            i2cm_write_count <= 0;
            i2cm_complete <= 0;
            i2cm_error <= 0;
        end else begin
            case ( i2cm_state )
                I2CM_IDLE: begin
                        if ( ( in_valid && in_start ) || start_operation ) begin
                            i2cm_complete <= 0;
                            i2cm_error <= 0;
                            clock_counter <= ( ClockCount >> 2 ) - 'H2;
                            i2cm_start_required <= 1;
                            i2cm_function <= I2CM_FUNCTION_ADDRESS;
                            if ( slave_address_in_pipe ) begin

                                i2cm_state <= I2CM_ADDRESS;
                            end else begin
                                i2cm_address <= slave_address[ DataWidth-2:0];
                                if ( operation_in_pipe ) begin

                                    i2cm_state <= I2CM_OPERATION;
                                end else begin



                                    if ( operation == OperationRead ) begin

                                        transfer_word <= { slave_address[ DataWidth-2:0 ], 1'H1 };

                                        i2cm_read <= 1;
                                        if ( read_count_in_pipe ) begin
                                            i2cm_state <= I2CM_COUNT;
                                        end else begin
                                            sda_out <= 0;
                                            i2cm_read_count <= read_count;
                                            i2cm_state <= I2CM_START;
                                            i2cm_stop <= 1;
                                        end
                                    end else begin



                                        transfer_word <= { slave_address[ DataWidth-2:0 ], 1'H0 };
                                        i2cm_state <= I2CM_START;
                                        i2cm_read <= 0;

                                        sda_out <= 0;
                                    end
                                end
                            end
                        end
                    end
                I2CM_ADDRESS: begin
                        if ( in_valid && ( in_start == i2cm_start_required ) ) begin

                            if ( operation_in_pipe ) begin

                                i2cm_address <= in_data[ DataWidth-1:1];
                                i2cm_read <= in_data[ 0 ];
                                transfer_word <= in_data;
                            end else begin

                                i2cm_address <= in_data[ DataWidth-2:0];
                                transfer_word <= { in_data[ DataWidth-2:0 ], (operation == OperationRead) };
                                i2cm_read <= (operation == OperationRead);
                            end


                            sda_out <= 0;
                            i2cm_ack <= 0;

                            i2cm_start_required <= 0;


                            if ( ( (operation_in_pipe) && in_data[ 0 ] ) || ( operation == OperationRead ) ) begin

                                if ( read_count_in_pipe ) begin
                                    i2cm_state <= I2CM_COUNT;
                                end else begin
                                    i2cm_read_count <= read_count;
                                    i2cm_state <= I2CM_START;
                                    i2cm_stop <= 1;
                                end
                            end else begin

                                i2cm_stop <= in_stop;
                                i2cm_state <= I2CM_START;
                            end
                        end
                    end
                I2CM_OPERATION: begin
                        if ( in_valid && ( in_start == i2cm_start_required ) ) begin
                            i2cm_read <= in_data[ 0 ];

                            sda_out <= 0;
                            i2cm_ack <= 0;
                            transfer_word <= { i2cm_address[ DataWidth-2:0 ], in_data[ 0 ] };

                            i2cm_start_required <= 0;


                            if ( in_data[ 0 ] ) begin
                                if ( read_count_in_pipe ) begin
                                    i2cm_state <= I2CM_COUNT;
                                end else begin
                                    i2cm_read_count <= read_count;
                                    i2cm_state <= I2CM_START;
                                    i2cm_stop <= 1;
                                end
                            end else begin

                                i2cm_stop <= in_stop;
                                i2cm_state <= I2CM_START;
                            end
                        end
                    end
                I2CM_COUNT: begin
                        if ( in_valid && ( in_start == i2cm_start_required ) ) begin

                            sda_out <= 0;
                            i2cm_read_count <= in_data;
                            i2cm_state <= I2CM_START;
                            i2cm_stop <= 1;
                        end
                    end

                I2CM_START_TRIGGER: begin
                        if ( start_operation )
                            i2cm_state <= I2CM_START;
                    end
                I2CM_START: begin

                        if ( clock_counter_expired ) begin
                            if ( ~i2cm_read )
                                i2cm_write_count <= 0;

                            scl_out <= 0;
                            i2cm_state <= I2CM_BITS;
                            bit_counter <= DataWidth - 2;
                            clock_counter <= ( ClockCount >> 2 ) - 'H2;
                        end else begin
                            clock_counter <= clock_counter - (clock_counter_expired ? 0 : 1 );
                        end
                    end
                I2CM_BITS: begin

                        if ( i2cm_out_valid ) begin
                            i2cm_out_start <= 0;
                            i2cm_out_stop <= 0;
                            i2cm_out_data <= 0;
                            i2cm_out_valid <= 0;
                        end

                        if ( clock_counter_expired ) begin



                            if ( i2cm_function != I2CM_FUNCTION_READING ) begin
                                sda_out <= transfer_word[ DataWidth -1 ];
                                transfer_word <= { transfer_word, 1'H0 };
                            end else begin
                                sda_out <= 1;
                            end
                            i2cm_state <= I2CM_CLOCK_UP;
                            clock_counter <= ( ClockCount >> 2 ) - 'H2;
                        end else begin
                            clock_counter <= clock_counter - (clock_counter_expired ? 0 : 1 );
                        end
                    end
                I2CM_CLOCK_UP: begin

                        if ( clock_counter_expired ) begin

                            scl_out <= 1;

                            if ( scl_in_1 == 1 ) begin

                                if ( i2cm_function == I2CM_FUNCTION_READING ) begin

                                    transfer_word <= { transfer_word[ DataWidth-2:0], sda_in_1 };
                                end

                                clock_counter <= ( ClockCount >> 1 ) - 'H3;
                                i2cm_state <= I2CM_CLOCK_DOWN;
                            end
                        end else begin
                            clock_counter <= clock_counter - (clock_counter_expired ? 0 : 1 );
                        end
                    end
                I2CM_CLOCK_DOWN: begin

                        if ( clock_counter_expired ) begin
                            clock_counter <= ( ClockCount >> 2 ) - 'H2;
                            scl_out <= 0;
                            if ( bit_counter_expired ) begin
                                i2cm_state <= I2CM_ACK_BIT;
                            end else begin
                                i2cm_state <= I2CM_BITS;
                                bit_counter <= bit_counter - 1;
                            end
                        end else begin
                            clock_counter <= clock_counter - (clock_counter_expired ? 0 : 1 );
                        end
                    end
                I2CM_ACK_BIT: begin


                        if ( clock_counter_expired ) begin
                            clock_counter <= ( ClockCount >> 2 ) - 'H2;
                            if ( i2cm_function != I2CM_FUNCTION_READING ) begin
                                    sda_out <= 1;
                            end else begin

                                if ( i2cm_word_counter == ( i2cm_read_count - 1'H1 ) )
                                    sda_out <= 1;
                                else
                                    sda_out <= 0;
                            end
                            i2cm_state <= I2CM_ACK_CLOCK_UP;
                        end else begin
                            clock_counter <= clock_counter - (clock_counter_expired ? 0 : 1 );
                        end
                    end
                I2CM_ACK_CLOCK_UP: begin


                        if ( clock_counter_expired ) begin
                            clock_counter <= ( ClockCount >> 2 ) - 'H2;

                            scl_out <= 1;

                            if ( scl_in_1 == 1 ) begin

                                if ( i2cm_function != I2CM_FUNCTION_READING ) begin

                                    i2cm_ack <= ~sda_in_1;
                                end else begin


                                end



                                clock_counter <= ( ClockCount >> 1 ) - 'H3;
                                i2cm_state <= I2CM_ACK_CLOCK_DOWN;
                            end
                        end else begin
                            clock_counter <= clock_counter - (clock_counter_expired ? 0 : 1 );
                        end
                    end
                I2CM_ACK_CLOCK_DOWN: begin

                        if ( clock_counter_expired ) begin

                            case ( i2cm_function )
                                I2CM_FUNCTION_ADDRESS: begin

                                        scl_out <= 0;

                                        i2cm_word_counter <= 0;
                                        clock_counter <= ( ClockCount >> 2 ) - 'H2;
                                        bit_counter <= DataWidth - 2;
                                        if ( i2cm_ack ) begin

                                            if ( i2cm_read ) begin
                                                if ( out_be_ready ) begin

                                                    if ( send_address || send_operation ) begin
                                                        i2cm_out_start <= 1;
                                                        i2cm_out_stop <= 0;
                                                        if ( send_address && send_operation )
                                                            i2cm_out_data <= { i2cm_address, 1'H1 };
                                                        else begin
                                                            if ( send_address )
                                                                i2cm_out_data <= { 1'H0, i2cm_address };
                                                            else
                                                                i2cm_out_data <= 1'H1;
                                                        end
                                                        i2cm_out_valid <= 1;
                                                    end
                                                    i2cm_state <= I2CM_BITS;

                                                    i2cm_function <= ( i2cm_read ) ? I2CM_FUNCTION_READING : I2CM_FUNCTION_WRITING;
                                                end
                                            end else begin

                                                i2cm_function <= ( i2cm_read ) ? I2CM_FUNCTION_READING : I2CM_FUNCTION_WRITING;
                                                i2cm_state <= I2CM_NEXT;
                                            end
                                        end else begin


                                            i2cm_function <= ( i2cm_read ) ? I2CM_FUNCTION_READING : I2CM_FUNCTION_WRITING;
                                            i2cm_error <= 1;
                                            if ( i2cm_stop ) begin

                                                i2cm_state <= I2CM_REPORT_A;
                                            end else begin

                                                i2cm_state <= I2CM_DRAIN;
                                            end
                                        end
                                    end
                                I2CM_FUNCTION_READING: begin

                                        scl_out <= 0;

                                        if ( out_be_ready ) begin
                                            i2cm_out_start <= ( i2cm_word_counter == 0 ) && ~send_address && ~send_operation;
                                            i2cm_out_data <= transfer_word;
                                            i2cm_out_valid <= 1;
                                            i2cm_word_counter <= i2cm_word_counter + 1'H1;
                                            if ( i2cm_word_counter == ( i2cm_read_count - 1'H1 ) ) begin
                                                i2cm_out_stop <= 1;
                                                i2cm_complete <= 1;
                                                i2cm_state <= I2CM_ENDING1;
                                            end else begin
                                                i2cm_out_stop <= 0;
                                                transfer_word <= 0;
                                                i2cm_state <= I2CM_BITS;
                                            end
                                            clock_counter <= ( ClockCount >> 2 ) - 'H2;
                                            bit_counter <= DataWidth - 2;

                                        end



                                    end
                                I2CM_FUNCTION_WRITING: begin
                                        bit_counter <= DataWidth - 2;
                                        clock_counter <= ( ClockCount >> 2 ) - 'H2;
                                        scl_out <= 0;
                                        if ( i2cm_ack )
                                            i2cm_word_counter <= i2cm_word_counter + 1;
                                        else
                                            i2cm_error <= 1;

                                        if ( i2cm_stop ) begin

                                            i2cm_state <= I2CM_REPORT_A;
                                            i2cm_complete <= 1;
                                        end else begin
                                            if ( ~i2cm_ack ) begin
                                                i2cm_error <= 1;
                                                i2cm_state <= I2CM_DRAIN;
                                            end else begin
                                                i2cm_state <= I2CM_NEXT;
                                            end
                                        end
                                    end
                            endcase
                        end else begin
                            clock_counter <= clock_counter - (clock_counter_expired ? 0 : 1 );
                        end
                    end
                I2CM_NEXT: begin



                        if ( in_valid ) begin
                            if ( in_start ) begin




                                i2cm_state <= I2CM_REPORT_A;
                                clock_counter <= ( ClockCount >> 2 ) - 'H3;
                            end else begin
                                scl_out <= 0;
                                transfer_word <= in_data;
                                i2cm_stop <= in_stop;
                                i2cm_state <= I2CM_BITS;
                                clock_counter <= ( ClockCount >> 2 ) - 'H3;
                            end
                        end
                    end
                I2CM_REPORT_A: begin

                        i2cm_write_count <= i2cm_word_counter;
                        if ( out_be_ready ) begin

                            if ( send_address ) begin
                                if ( send_operation ) begin
                                    i2cm_out_data <= { i2cm_address, i2cm_read  };
                                end else begin
                                    i2cm_out_data <= { 1'H0, i2cm_address };
                                end
                                i2cm_out_start <= 1;
                                i2cm_out_valid <= 1;
                            end else begin
                                if ( send_operation ) begin
                                    i2cm_out_start <= 1;
                                    i2cm_out_data <= i2cm_read;
                                    i2cm_out_valid <= 1;
                                end
                            end

                            i2cm_out_stop = ( i2cm_read && i2cm_error ) || ( ~i2cm_read && ~send_write_count );
                            if ( i2cm_function == I2CM_FUNCTION_READING ) begin

                                i2cm_state <= I2CM_ENDING1;
                            end else begin

                                i2cm_state <= I2CM_REPORT_B;
                            end
                        end
                    end
                I2CM_REPORT_B: begin

                        if ( i2cm_out_valid ) begin
                            i2cm_out_start <= 0;
                            i2cm_out_stop <= 0;
                            i2cm_out_data <= 0;
                            i2cm_out_valid <= 0;
                        end else begin
                            if ( !send_write_count ) begin
                                i2cm_state <= I2CM_ENDING1;
                            end else begin
                                if ( out_be_ready ) begin
                                    i2cm_out_start <= ( ~send_address && ~send_operation );
                                    i2cm_out_data <= i2cm_word_counter;
                                    i2cm_out_valid <= 1;
                                    i2cm_out_stop <= 1;
                                    i2cm_state <= I2CM_ENDING1;
                                end
                            end
                        end
                    end
                I2CM_DRAIN: begin

                        if ( ~in_valid || ( in_valid && in_stop ) || i2cm_stop ) begin
                            i2cm_state <= I2CM_REPORT_A;
                        end
                    end
                I2CM_ENDING1: begin
                        i2cm_function <= I2CM_FUNCTION_IDLE;
                        if ( i2cm_out_valid ) begin
                            i2cm_out_start <= 0;
                            i2cm_out_stop <= 0;
                            i2cm_out_data <= 0;
                            i2cm_out_valid <= 0;
                        end

                        if ( clock_counter_expired ) begin
                            if ( ( in_valid && in_start ) )
                                sda_out <= 1;
                            else
                                sda_out <= 0;
                            i2cm_state <= I2CM_ENDING2;
                            clock_counter <= ( ClockCount >> 2 ) - 'H2;
                        end else begin
                            clock_counter <= clock_counter - (clock_counter_expired ? 0 : 1 );
                        end
                    end
                I2CM_ENDING2: begin

                        if ( clock_counter_expired ) begin
                            scl_out <= 1;
                            if ( scl_in_1 ) begin
                                i2cm_state <= I2CM_STOP;
                                clock_counter <= ( ClockCount >> 2 ) - 'H2;
                            end
                        end else begin
                            clock_counter <= clock_counter - (clock_counter_expired ? 0 : 1 );
                        end
                    end
                I2CM_STOP: begin
                        if ( clock_counter_expired ) begin
                            sda_out <= 1;
                            i2cm_state <= I2CM_IDLE;
                        end else begin
                            clock_counter <= clock_counter - (clock_counter_expired ? 0 : 1 );
                        end
                    end
                default: begin
                        i2cm_state <= I2CM_IDLE;
                    end

            endcase



        end
    end

    localparam I2CM_BE_IDLE = 0,
               I2CM_BE_BUSY = 1;

    reg i2cm_be_state;

    reg                 i2cm_out_start_store;
    reg                 i2cm_out_stop_store;
    reg [DataWidth-1:0] i2cm_out_data_store;
    reg                 i2cm_out_valid_store;

    always @( posedge clock ) begin
        if ( reset ) begin
            i2cm_be_state <= I2CM_BE_IDLE;
            i2cm_out_start_store <= 0;
            i2cm_out_stop_store <= 0;
            i2cm_out_data_store <= 0;
            i2cm_out_valid_store <= 0;
        end else begin
            case ( i2cm_be_state )
                I2CM_BE_IDLE: begin
                        if ( i2cm_out_valid ) begin
                            i2cm_out_start_store <= i2cm_out_start;
                            i2cm_out_stop_store <= i2cm_out_stop;
                            i2cm_out_data_store <= i2cm_out_data;
                            i2cm_out_valid_store <= 1;
                            i2cm_be_state <= I2CM_BE_BUSY;
                        end
                    end
                I2CM_BE_BUSY: begin
                        if ( out_ready ) begin
                            i2cm_out_start_store <= 0;
                            i2cm_out_stop_store <= 0;
                            i2cm_out_data_store <= 0;
                            i2cm_out_valid_store <= 0;
                            i2cm_be_state <= I2CM_BE_IDLE;
                        end
                    end
            endcase
        end
    end

    assign out_start = i2cm_out_start_store;
    assign out_stop = i2cm_out_stop_store;
    assign out_data = i2cm_out_data_store;
    assign out_valid = i2cm_out_valid_store;

    assign out_be_ready = ( i2cm_be_state == I2CM_BE_IDLE );

    assign write_count = i2cm_write_count;
    assign complete = i2cm_complete;
    assign error = i2cm_error;

    assign debug[3:0] = i2cm_state;

endmodule