sensor_i2c_prot.v 20.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
/*!
 * <b>Module:</b>sensor_i2c_prot
 * @file sensor_i2c_prot.v
 * @date 2015-10-05  
 * @author Andrey Filippov     
 *
 * @brief Generate i2c R/W sequence from a 32-bit word and LUT
 *
 * @copyright Copyright (c) 2015 Elphel, Inc .
 *
 * <b>License:</b>
12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * sensor_i2c_prot.v is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 *  sensor_i2c_prot.v 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/> .
25 26 27 28 29 30
 *
 * Additional permission under GNU GPL version 3 section 7:
 * If you modify this Program, or any covered work, by linking or combining it
 * with independent modules provided by the FPGA vendor only (this permission
 * does not extend to any 3-rd party modules, "soft cores" or macros) under
 * different license terms solely for the purpose of generating binary "bitstream"
31
 * files and/or simulating the code, the copyright holders of this Program give
32 33
 * you the right to distribute the covered work without those independent modules
 * as long as the source code for them is available from the FPGA vendor free of
Andrey Filippov's avatar
Andrey Filippov committed
34
 * charge, and there is no dependence on any encrypted modules for simulating of
35 36 37
 * the combined code. This permission applies to you if the distributed code
 * contains all the components and scripts required to completely simulate it
 * with at least one of the Free Software programs.
38
 */
39 40
`timescale 1ns/1ps

41 42 43 44 45 46 47 48 49 50 51 52 53 54
module  sensor_i2c_prot#(
    parameter SENSI2C_TBL_RAH =          0, // high byte of the register address 
    parameter SENSI2C_TBL_RAH_BITS =     8,
    parameter SENSI2C_TBL_RNWREG =       8, // read register (when 0 - write register
    parameter SENSI2C_TBL_SA =           9, // Slave address in write mode
    parameter SENSI2C_TBL_SA_BITS =      7,
    parameter SENSI2C_TBL_NBWR =        16, // number of bytes to write (1..10)
    parameter SENSI2C_TBL_NBWR_BITS =    4,
    parameter SENSI2C_TBL_NBRD =        16, // number of bytes to read (1 - 8) "0" means "8"
    parameter SENSI2C_TBL_NBRD_BITS =    3,
    parameter SENSI2C_TBL_NABRD =       19, // number of address bytes for read (0 - 1 byte, 1 - 2 bytes)
    parameter SENSI2C_TBL_DLY =         20, // bit delay (number of mclk periods in 1/4 of SCL period)
    parameter SENSI2C_TBL_DLY_BITS=      8
)(
Andrey Filippov's avatar
Andrey Filippov committed
55 56 57 58
    input            mrst,         // @ posedge mclk
    input            mclk,         // global clock
    input            i2c_rst,
    input            i2c_start,
Andrey Filippov's avatar
Andrey Filippov committed
59 60
    input            active_sda,     // global config bit: active pull SDA
    input            early_release_0,// global config bit: release SDA immediately after end of SCL if next bit is 1 (for ACKN). Data hold time by slow 0->1 
61
    // setup LUT to translate address page into SA, actual address MSB and number of bytes to write (second word bypasses translation)
Andrey Filippov's avatar
Andrey Filippov committed
62
    input            tand,         // table address/not data
Andrey Filippov's avatar
Andrey Filippov committed
63
    input     [27:0] td,           // table address/data in            
Andrey Filippov's avatar
Andrey Filippov committed
64 65
    input            twe,          // table write enable
    input            sda_in,       // data from sda pad
Andrey Filippov's avatar
Andrey Filippov committed
66 67 68 69 70
    output           sda,
    output           sda_en,
    output           scl,
    output reg       i2c_run,      // released as soon as the last command (usually STOP) gets to the i2c start/stop/shift module
    output reg       i2c_busy,     // released when !i2c_run and all i2c activity is over 
Andrey Filippov's avatar
Andrey Filippov committed
71
    output reg [1:0] seq_mem_ra, // number of byte to read from the sequencer memory
72
    output    [ 1:0] seq_mem_re, // [0] - re, [1] - regen to the sequencer memory
Andrey Filippov's avatar
Andrey Filippov committed
73 74 75
    input     [ 7:0] seq_rd,     // data from the sequencer memory 
    output    [ 7:0] rdata,
    output           rvalid
76
);
Andrey Filippov's avatar
Andrey Filippov committed
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
/*
    Sequencer provides 4 bytes per command, read one byte at a time as seq_rd[7:0] with byte address provided by seq_mem_ra[1:0],
    seq_mem_re[0] external memory re, seq_mem_re[1] - regen
    MSB (byte 3) is used as index in the table that provides for register writes (tdout[8] == 0):
        high byte of the register address (if used) - tdout[7:0]
        slave address - tdout[15:9],
        number of bytes to send after SA - tdout[19:16] (includes both adderss and data bytes, aligned to the MSB)
        bit delay - tdout[27:20] (periods of mclk for 1/4 of the SCL period), should be >2(?)
        
        if number of bytes to send (including address) >4, there will be no stop and the next command will bypass MSB decoding through table
        and be sent out as data bytes (MSB first, aligned to the LSB (byte[0]), so if only one byte is to be sent bytes[3:1] will be skipped.
   In read mode (tdout[8] == 1) it is possible to use 1 or 2 byte register address and read 1..8 bytes
        bit delay - tdout[27:20] (same as for register writes - see above)
        Slave address in the read mode is provided as byte[2], register adderss in bytes[1:0] (byte[1] is skipped for 1-byte addresses)
        Number of data bytes to read is provided as tdout[18:16], with 0 meaning 8 bytes
        Nuber of register address bytes is defined by tdout[19]: 0 - one byte, 1 - 2 bytes address
   "active_sda" (configuration bit enables active pull-up on SDA line by the master for faster communication, it is active during second
        half of the SCL=0 for the data bits and also for the first interval of the RESTART sequence and for the last of the STOP one.
   "early_release_0" - when sending data bit "0" over the SDA line, release SDA=0 immediately after SCL: 1->0 if the next bit to send is "1".
        This is OK as the SDA 0->1 transition will be slower than SCL 1->0 (only pulled up by a resistor), so there will be positive hold time
        on SDA line. This is done so for communications with 10359 (or similar) board where FPGA can also actively drive SDA line for faster
        communication.
   Active driving of the SDA line increases only master send communication, so ACKN may be missed, but it is not used in this implementation.
   Reading registers is less used operation than write and can use slower communication spped (provided through the table)      
*/
102 103
    reg    [ 7:0] twa;
    wire   [31:0] tdout;
Andrey Filippov's avatar
Andrey Filippov committed
104 105 106
    reg    [ 7:0] reg_ah;   // MSB of the register address (instead of the byte 2)
    reg    [ 7:0] slave_a_rah;    // 8-bit slave address , used instead of the byte 3, later replaced with reg_ah
    reg    [ 3:0] num_bytes_send; // number of bytes to send (if more than 4 will skip stop and continue with next data
Andrey Filippov's avatar
Andrey Filippov committed
107 108 109
    reg    [ 7:0] i2c_dly;      // bit duration-1 (>=2?), 1 unit - 4 mclk periods
    
    
110
    reg    [ 3:0] bytes_left_send; // Number of bytes left in register write sequence (not counting sa?)
Andrey Filippov's avatar
Andrey Filippov committed
111 112 113
    reg    [ 6:0] run_reg_wr;      // run register write [6] - start, [5] - send sa, [4] - send high byte (from table),..[0] - send stop 
    reg    [ 4:0] run_extra_wr;    // continue register write (if more than sa + 4bytes) [4] - byte 3, .. [1]- byte0,  [0] - stop
    reg    [ 7:0] run_reg_rd; // [7] - start, [6] SA (byte 3), [5] (optional) - RA_msb, [4] - RA_lsb, [3] - restart, [2] - SA, [1] - read bytes, [0] - stop
Andrey Filippov's avatar
Andrey Filippov committed
114 115 116
    reg           run_extra_wr_d;  // any of run_extra_wr bits, delayed by 1
    reg           run_any_d;       // any of command states, delayed by 1
    reg    [1:0]  pre_cmd;         // from i2c_start until run_any_d will be active
117
    reg           first_mem_re;
Andrey Filippov's avatar
Andrey Filippov committed
118 119
//    reg           i2c_done;
//    wire          i2c_next_byte;
120
    reg    [ 2:0] mem_re;
Andrey Filippov's avatar
Andrey Filippov committed
121
    reg           mem_valid;
122
    reg    [ 2:0] table_re;
123
    
Andrey Filippov's avatar
Andrey Filippov committed
124 125 126
//    reg           read_mem_msb;
//    wire          decode_reg_rd = &seq_rd[7:4];
//    wire          start_wr_seq_w = !run_extra_wr_d && !decode_reg_rd && read_mem_msb;
127 128
    wire          start_wr_seq_w = table_re[2] && !tdout[SENSI2C_TBL_RNWREG];
    wire          start_rd_seq_w = table_re[2] &&  tdout[SENSI2C_TBL_RNWREG];
Andrey Filippov's avatar
Andrey Filippov committed
129
    wire          start_extra_seq_w = i2c_start && (bytes_left_send !=0);
130
    
131 132 133
 //   wire          snd_start_w = run_reg_wr[6] || 1'b0; // add start & restart of read
 //   wire          snd_stop_w =  run_reg_wr[0] || 1'b0; // add stop of read
 //   wire          snd9_w     =  (|run_reg_wr[5:1]) || 1'b0; // add for read and extra write;
Andrey Filippov's avatar
Andrey Filippov committed
134 135 136 137 138 139 140 141 142 143

    reg           snd_start;
    reg           snd_stop;
    reg           snd9;
    // the following signals are mutually exclusive, can be encoded to 2 bits. Invaluid during next_cmd_d
    reg           send_seq_data; // including first SA for read
    reg           send_rd_sa;    // from the table
    reg           send_sa_rah;   // send slave address/ high address from the table
    reg           send_rd;       // send 1fe/1ff to read data
    reg     [6:0] rd_sa;         // 7-bit slave address for reading
Andrey Filippov's avatar
Andrey Filippov committed
144
    wire    [1:0] sel_sr_in = {  // select source for the shift register
Andrey Filippov's avatar
Andrey Filippov committed
145 146
                  send_sa_rah | send_rd,
                  send_rd_sa | send_rd};
Andrey Filippov's avatar
Andrey Filippov committed
147 148 149
    reg     [8:0] sr_in;         // input data for the shift register
    wire          bus_busy;      // i2c bus is active
    wire          bus_open;      // i2c bus is "open" (START-ed but not STOP-ed) - between multi-byte write if it spans >1 32-bit comands
Andrey Filippov's avatar
Andrey Filippov committed
150 151 152 153 154 155 156 157

    wire          i2c_rdy;
    reg           next_cmd; // i2c command (start/stop/data) accepted, proceed to the next stage
    reg           next_cmd_d; // next cycle after next_cmd (first at new state)
    wire          pre_next_cmd = (snd_start || snd_stop || snd9) && i2c_rdy;
    reg           next_byte_wr;
    
    reg           read_address_bytes; // 0 - single-byte register adderss, 1 - two-byte register address
158
    reg    [ 2:0] read_data_bytes;    // 1..8 bytes to read from the i2c slave (0 is 8!)
Andrey Filippov's avatar
Andrey Filippov committed
159 160 161
    
    reg    [ 1:0] initial_address; // initial data byte to read: usually 3  but for extra write may be different
    wire   [ 3:0] initial_address_w =  bytes_left_send - 1; // if bytes left to send == 0 - will be 3                      
Andrey Filippov's avatar
Andrey Filippov committed
162 163
    wire          unused;            // unused ackn signal SuppressThisWarning VEditor
    
164
    wire          pre_table_re = !run_extra_wr_d && first_mem_re && mem_re[1];
Andrey Filippov's avatar
Andrey Filippov committed
165
    reg           rnw;  // last command was read (not write) - do not increment bytes_left_send
Andrey Filippov's avatar
Andrey Filippov committed
166
    
167
//    wire          dout_stb; // rvalid
Andrey Filippov's avatar
Andrey Filippov committed
168
      
169
    assign seq_mem_re = mem_re[1:0];
170
//    assign rvalid = dout_stb && run_reg_rd[1];
171
    always @ (posedge mclk) begin
Andrey Filippov's avatar
Andrey Filippov committed
172 173
        if (mrst || i2c_rst || start_wr_seq_w) rnw <= 0;
        else if (start_rd_seq_w)               rnw <= 1;
Andrey Filippov's avatar
Andrey Filippov committed
174 175
        run_extra_wr_d <= |run_extra_wr;
        
Andrey Filippov's avatar
Andrey Filippov committed
176 177
        run_any_d <= (|run_reg_wr) || (|run_extra_wr) || (|run_reg_rd);
        
178 179 180 181
        if (mrst || i2c_rst)  first_mem_re <= 0;
        else if (i2c_start)   first_mem_re <= 1;
        else if (mem_re[2])   first_mem_re <= 0;
        
Andrey Filippov's avatar
Andrey Filippov committed
182 183 184
        if (mrst || i2c_rst) pre_cmd <= 0;
        else if (i2c_start)  pre_cmd <= 1;
        else if (run_any_d)  pre_cmd <= 0;
185

Andrey Filippov's avatar
Andrey Filippov committed
186 187 188 189 190 191 192
        if (mrst || i2c_rst) i2c_run <= 0;
        else                 i2c_run <=  i2c_start || pre_cmd || run_any_d;

        if (mrst || i2c_rst) i2c_busy <= 0;
        else                 i2c_busy <= i2c_start || pre_cmd || run_any_d || bus_busy || bus_open;
        
        
193
        table_re <= {table_re[1:0], pre_table_re}; // start_wr_seq_w};
Andrey Filippov's avatar
Andrey Filippov committed
194 195
        
        if (table_re[2]) begin
196 197 198
            reg_ah <=         tdout[SENSI2C_TBL_RAH +: SENSI2C_TBL_RAH_BITS]; //[ 7:0];   // MSB of the register address (instead of the byte 2)
            num_bytes_send <= tdout[SENSI2C_TBL_NBWR +: SENSI2C_TBL_NBWR_BITS] ; // [19:16]; // number of bytes to send (if more than 4 will skip stop and continue with next data
            i2c_dly <=        tdout[SENSI2C_TBL_DLY +: SENSI2C_TBL_DLY_BITS]; //[27:20];
Andrey Filippov's avatar
Andrey Filippov committed
199
        end
200 201
        if      (table_re[2])               slave_a_rah <= {tdout[SENSI2C_TBL_SA +: SENSI2C_TBL_SA_BITS], 1'b0}; // {tdout[15:9], 1'b0};
        else if (next_cmd && run_reg_wr[5]) slave_a_rah <= reg_ah; // will copy even if not used
Andrey Filippov's avatar
Andrey Filippov committed
202
 //    wire          pre_next_cmd = (snd_start || snd_stop || snd9) && i2c_rdy;
Andrey Filippov's avatar
Andrey Filippov committed
203 204 205
        next_cmd <= pre_next_cmd;
        
        next_cmd_d <= next_cmd;
206
        
Andrey Filippov's avatar
Andrey Filippov committed
207
        next_byte_wr <= snd9 && i2c_rdy && !run_reg_wr[5] && !rnw; // (|run_reg_rd); // same time as next_cmd, no pulse when sending SA during write
208

209 210 211
//        snd_start <= snd_start_w; // add & i2c_ready? Not really needed as any i2c stage will be busy for long enough
//        snd_stop <=  snd_stop_w;
//        snd9 <=      snd9_w;
Andrey Filippov's avatar
Andrey Filippov committed
212 213
        
        if     (mrst || i2c_rst) bytes_left_send <= 0;
214
        else if (start_wr_seq_w) bytes_left_send <= tdout[SENSI2C_TBL_NBWR +: SENSI2C_TBL_NBWR_BITS]; // num_bytes_send;
Andrey Filippov's avatar
Andrey Filippov committed
215 216 217
        else if (next_byte_wr)   bytes_left_send <= bytes_left_send - 1;

        // calculate stages for each type of commands
218
        // start and write sa and some bytes, stop if number of bytes <= 4 at the end        
Andrey Filippov's avatar
Andrey Filippov committed
219 220 221 222 223 224 225 226 227 228 229
        if      (mrst || i2c_rst) run_reg_wr <= 0;
        else if (start_wr_seq_w)  run_reg_wr <= 7'h40;
        else if (next_cmd)        run_reg_wr <= {1'b0,         // first "start"
                                                run_reg_wr[6], // slave_addr - always after start
                                                run_reg_wr[5] & (|num_bytes_send[3:2]), // MSB (from the table)
                                                run_reg_wr[4] | (run_reg_wr[5] & (num_bytes_send == 4'h3)), // byte 2 (from input)
                                                run_reg_wr[3] | (run_reg_wr[5] & (num_bytes_send == 4'h2)), // byte 1 (from input)
                                                run_reg_wr[2] | (run_reg_wr[5] & (num_bytes_send == 4'h1)), // byte 0 (from input)
                                                run_reg_wr[1] & (bytes_left_send == 4'h1)
                                                };
        // send just bytes (up to 4), stop if nothing left 
Andrey Filippov's avatar
Andrey Filippov committed
230 231
        if      (mrst || i2c_rst)               run_extra_wr <= 0;
        else if (start_extra_seq_w)             run_extra_wr <= {
Andrey Filippov's avatar
Andrey Filippov committed
232 233 234 235 236 237
                                                        |bytes_left_send[3:2], // >= 4 bytes left
                                                        (bytes_left_send == 3), // exactly 3 bytes left
                                                        (bytes_left_send == 2), // exactly 2 bytes left
                                                        (bytes_left_send == 1), // exactly 1 bytes left (zero should never be left)
                                                        1'b0
                                                     };
Andrey Filippov's avatar
Andrey Filippov committed
238
        else if (next_cmd)                      run_extra_wr <= {
Andrey Filippov's avatar
Andrey Filippov committed
239 240 241 242 243
                                                        1'b0,
                                                        run_extra_wr[4],
                                                        run_extra_wr[3],
                                                        run_extra_wr[2],
                                                        run_extra_wr[1] & (bytes_left_send == 4'h1)
Andrey Filippov's avatar
Andrey Filippov committed
244
                                                };
Andrey Filippov's avatar
Andrey Filippov committed
245 246

//     reg    [ 7:0] run_reg_rd; // [7] - start, [6] SA (byte 3), [5] (optional) - RA_msb, [4] - RA_lsb, [3] - restart, [2] - SA, [1] - read bytes, [0] - stop
247

248 249 250 251 252
//        if      (table_re[2] &&  tdout[8])  read_address_bytes <= tdout[19];
        if      (table_re[2] &&  tdout[SENSI2C_TBL_RNWREG])  read_address_bytes <= tdout[SENSI2C_TBL_NABRD]; // [19];
        
//        if      (table_re[2] &&  tdout[8])  read_data_bytes <= tdout[18:16];
        if      (table_re[2] &&  tdout[SENSI2C_TBL_RNWREG])  read_data_bytes <= tdout[SENSI2C_TBL_NBRD +: SENSI2C_TBL_NBRD_BITS];
Andrey Filippov's avatar
Andrey Filippov committed
253
        else if (run_reg_rd[1] && next_cmd) read_data_bytes <= read_data_bytes - 1;
Andrey Filippov's avatar
Andrey Filippov committed
254 255
        
        // read i2c data
Andrey Filippov's avatar
Andrey Filippov committed
256 257 258
        if      (mrst || i2c_rst) run_reg_rd <= 0;
//        else if (!run_extra_wr_d &&  decode_reg_rd && read_mem_msb)  run_reg_rd <= 8'h80;
        else if (start_rd_seq_w)  run_reg_rd <= 8'h80;
Andrey Filippov's avatar
Andrey Filippov committed
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
        else if (next_cmd)        run_reg_rd <= {1'b0,         // first "start"
                                                run_reg_rd[7], // slave_addr - always after start (bit0 = 0)
                                                run_reg_rd[6] & read_address_bytes, // optional MSB of the register address
                                                run_reg_rd[5] | (run_reg_rd[6] & ~read_address_bytes), // LSB of the register address
                                                run_reg_rd[4], // restart
                                                run_reg_rd[3], // send slave address with 1 in bit[0]
                                                run_reg_rd[2] | (run_reg_rd[1] & (read_data_bytes != 3'h1)), // repeat reading bytes
                                                run_reg_rd[1] & (read_data_bytes == 3'h1)
                                                };
        // read sequencer memory byte (for the current word)
        mem_re <= {mem_re[1:0], i2c_start | next_cmd_d & (
                               (|run_reg_wr[3:1]) |
                               (|run_extra_wr[4:1]) |
                               (|run_reg_rd[6:4]))};
        initial_address <=  initial_address_w[1:0]; // if bytes left to send is 0 mod 4 - will be 3 (read MSB)
        seq_mem_ra <= i2c_start ? initial_address : { // run_extra_wr[4] is not needed - it will be read by i2c_start
                                                       run_reg_wr[3] | run_extra_wr[3] | run_reg_rd[6],
                                                       run_reg_wr[2] | run_extra_wr[2] | run_reg_rd[5]
                                                    };
        if (mrst || i2c_rst || i2c_start || next_cmd ) mem_valid <= 0;
        else if (mem_re[2])                            mem_valid <= 1;
        
        // calculate snd9 and delay it if waiting for memory using mem_valid, set din[8:0] 
        if (run_reg_rd[6] && mem_re[2]) rd_sa <= seq_rd[7:1]; // store sa to use with read
        
        send_seq_data <= !next_cmd && mem_valid && ((|run_reg_wr[3:1]) || (|run_extra_wr[4:1]) || (|run_reg_rd[6:4])); 
        send_rd_sa <=    !next_cmd && run_reg_rd[2];
286
        send_sa_rah <=   !next_cmd && (|run_reg_wr[5:4]);
Andrey Filippov's avatar
Andrey Filippov committed
287 288
        send_rd <=       !next_cmd && run_reg_rd[1];
        
289 290 291 292 293 294 295 296 297
        if (mrst || i2c_rst || next_cmd) snd9 <= 0;
        else                             snd9 <= snd9 ? (!i2c_rdy) : ((send_seq_data || send_rd_sa || send_sa_rah || send_rd) && !next_cmd);

        if (mrst || i2c_rst || next_cmd) snd_start <= 0;
        else                             snd_start <= snd_start? (!i2c_rdy) : (run_reg_wr[6] || run_reg_rd[7] || run_reg_rd[3]);

        if (mrst || i2c_rst || next_cmd) snd_stop <= 0;
        else                             snd_stop <= snd_stop? (!i2c_rdy) : (run_reg_wr[0] || run_extra_wr[0] || run_reg_rd[0]);
        
Andrey Filippov's avatar
Andrey Filippov committed
298 299 300 301 302 303
        case (sel_sr_in)
            2'h0: sr_in <= {seq_rd, 1'b1};
            2'h1: sr_in <= {rd_sa, 2'b11};
            2'h2: sr_in <= {slave_a_rah, 1'b1};
            2'h3: sr_in <= {8'hff,(read_data_bytes == 3'h1)}; 
        endcase
304 305
        
    end    
Andrey Filippov's avatar
Andrey Filippov committed
306 307

    sensor_i2c_scl_sda sensor_i2c_scl_sda_i (
Andrey Filippov's avatar
Andrey Filippov committed
308 309 310 311 312 313 314 315 316
        .mrst            (mrst),          // input
        .mclk            (mclk),          // input
        .i2c_rst         (i2c_rst),       // input
        .i2c_dly         (i2c_dly),       // input[7:0] 
        .active_sda      (active_sda), // input
        .early_release_0 (early_release_0), // input
        .snd_start       (snd_start),     // input
        .snd_stop        (snd_stop),      // input
        .snd9            (snd9),          // input
317
        .rcv             (run_reg_rd[1]), // input       
Andrey Filippov's avatar
Andrey Filippov committed
318 319 320 321 322 323 324 325 326 327
        .din             (sr_in),         // input[8:0] 
        .dout            ({rdata,unused}),// output[8:0] 
        .dout_stb        (rvalid),        // output reg 
        .scl             (scl),           // output reg 
        .sda_in          (sda_in),        // input
        .sda             (sda),           // output reg 
        .sda_en          (sda_en),        // output reg 
        .ready           (i2c_rdy),       // output register
        .bus_busy        (bus_busy),      // output reg 
        .is_open         (bus_open)       // output
Andrey Filippov's avatar
Andrey Filippov committed
328
    );
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
     
    // table write  
    always @ (posedge mclk) begin
        if      (mrst) twa <= 0;
        else if (twe)  twa <= tand ? td[7:0] : (twa + 1);  
    end
    
    ram18_var_w_var_r #(
        .REGISTERS    (1),
        .LOG2WIDTH_WR (5),
        .LOG2WIDTH_RD (5),
        .DUMMY        (0)
    ) ram18_var_w_var_r_i (
        .rclk        (mclk), // input
        .raddr       ({1'b0, seq_rd}), // input[8:0] 
        .ren         (table_re[0]), // input
        .regen       (table_re[1]), // input
        .data_out    (tdout), // output[31:0] 
        .wclk        (mclk), // input
        .waddr       ({1'b0, twa}), // input[8:0] 
        .we          (twe && !tand), // input
        .web         (4'hf), // input[3:0] 
Andrey Filippov's avatar
Andrey Filippov committed
351
        .data_in     ({4'b0, td}) // input[31:0] 
352 353 354 355 356
    );


endmodule