Commit 730d8ca4 authored by Andrey Filippov's avatar Andrey Filippov
Browse files

started modification of the i2c sequencer to support SMIA registers (2 bytes...

started modification of the i2c sequencer to support SMIA registers (2 bytes address, >=2 bytes of data) and register read
parent 49a3f9e2
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
    parameter FPGA_VERSION =          32'h03930039;
 No newline at end of file
    parameter FPGA_VERSION =          32'h0393003a;
 No newline at end of file
+7 −34
Original line number Diff line number Diff line
@@ -424,33 +424,6 @@ module sensor_i2c#(
        .web(8'hff), // input[7:0] 
        .data_in(di_r) // input[31:0] 
    );
/*
   RAMB16_S9_S18 i_fifo (
                          .DOA(i2c_data[7:0]),     // Port A 8-bit Data Output
                          .DOPA(),                 // Port A 1-bit Parity Output
                          .ADDRA({page_r[2:0],
                                          rpointer[5:0],
                                             byte_number[1:0]}),       // Port A 11-bit Address Input
                          .CLKA(mclk),            // Port A Clock
                          .DIA(8'h0),              // Port A 8-bit Data Input
                          .DIPA(1'b0),             // Port A 1-bit parity Input
                          .ENA(i2c_byte_start[0]), // Port A RAM Enable Input
                          .SSRA(1'b0),             // Port A Synchronous Set/Reset Input
                          .WEA(1'b0),              // Port A Write Enable Input

                          .DOB(),                  // Port B 16-bit Data Output
                          .DOPB(),                 // Port B 2-bit Parity Output
                          .ADDRB(i2c_cmd_wa[9:0]), // Port B 10-bit Address Input
                          .CLKB(mclk),            // Port B Clock
                          .DIB(di_3[15:0]),        // Port B 16-bit Data Input
                          .DIPB(2'b0),             // Port-B 2-bit parity Input
                          .ENB(i2c_cmd_we),        // PortB RAM Enable Input
                          .SSRB(1'b0),             // Port B Synchronous Set/Reset Input
                          .WEB(1'b1)               // Port B Write Enable Input
                          );
     
*/


endmodule
+111 −0
Original line number Diff line number Diff line
/*******************************************************************************
 * Module: sensor_i2c_prot
 * Date:2015-10-05  
 * Author: andrey     
 * Description: Generate i2c R/W sequence from a 32-bit word and LUT
 *
 * Copyright (c) 2015 Elphel, Inc .
 * 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/> .
 *******************************************************************************/
`timescale 1ns/1ps

module  sensor_i2c_prot(
    input         mrst,         // @ posedge mclk
    input         mclk,         // global clock
    input         i2c_rst,
    input         i2c_start,
    input  [ 7:0] i2c_dly,      // bit duration-1 (>=2?), 1 unit - 4 mclk periods
    // setup LUT to translate address page into SA, actual address MSB and number of bytes to write (second word bypasses translation)
    input         tand,         // table address/not data
    input  [19:0] td,           // table address/data in            
    input         twe,          // table write enable
    output reg    sda,
    output reg    sda_en,
    output reg    scl,
    output        i2c_run,
    output [ 1:0] seq_mem_ra, // number of byte to read from the sequencer memory
    output [ 1:0] seq_mem_re, // [0] - re, [1] - regen to teh sequencer memory
    input  [ 7:0] seq_rd,     // data from the sequencer memory 
    output [ 7:0] rdata,
    output        rvalid
);
    reg    [ 7:0] twa;
    wire   [31:0] tdout;
    wire   [ 7:0] reg_ah =         tdout[7:0];   // MSB of the register address (instead of the byte 2)
    wire   [ 6:0] slave_a =        tdout[14:8];  // 7-bit slave address (lsb == 1), used instead of the byte 3
    wire   [ 3:0] num_bytes_send = tdout[19:16]; // number of bytes to send (if more than 4 will skip stop and continue with next data
    reg    [ 3:0] bytes_left_send; // Number of bytes left in register write sequence (not counting sa?)
    reg           run_reg_wr;       // run register write
    reg           run_extra_wr;    // continue register write (if more than sa + 4bytes)
    reg           run_reg_rd;
    reg           i2c_done;
    wire          i2c_next_byte;
    reg    [ 2:0] mem_re;
    reg    [ 2:0] table_re;
    
    
    wire          decode_reg_rd = &seq_rd[7:5];
    wire          start_wr_seq = !run_extra_wr && !decode_reg_rd && read_mem_msb;
    reg           read_mem_msb;   
    assign seq_mem_re = mem_re[1:0];
    
    always @ (posedge mclk) begin
        read_mem_msb <= mem_re[1] && (seq_mem_ra == 3); // reading sequencer data MSB
        mem_re <= {mem_re[1:0], i2c_start | i2c_next_byte}; 
        table_re <= {table_re[1:0], start_wr_seq};
        
        if      (mrst || i2c_rst)                                 run_extra_wr <= 0;
        else if (i2c_start && (bytes_left_send !=0))              run_extra_wr <= 1;
        else if (i2c_done)                                        run_extra_wr <= 0;

        if      (mrst || i2c_rst)                                 run_reg_wr <= 0;
        else if (start_wr_seq)                                    run_reg_wr <= 1;
        else if (i2c_done)                                        run_reg_wr <= 0;

        if      (mrst || i2c_rst)                                 run_reg_rd <= 0;
        else if (!run_extra_wr &&  decode_reg_rd && read_mem_msb) run_reg_rd <= 1;
        else if (i2c_done)                                        run_reg_rd <= 0;
        
        // table_re[2] - valid table data (slave_a, reg_ah, reg_ah
    
    end    
     
     
    // 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] 
        .data_in     ({12'b0, td}) // input[31:0] 
    );


endmodule
+246 −13

File changed.

Preview size limit exceeded, changes collapsed.

+4 −4
Original line number Diff line number Diff line
@@ -951,7 +951,7 @@ assign #10 gpio_pins[9] = gpio_pins[8];
            1'b1,   // input                                   set_bytes;  // [11] if 1, use bytes (below), 0 - nop
            2'h3,   // input  [SENSI2C_CMD_BYTES_PBITS -1 : 0] bytes;      // [10:9] set command bytes to send after slave address (0..3)
            1'b1,   // input                                   set_dly;    // [8] if 1, use dly (0 - ignore)
            8'h0a,  // input   [SENSI2C_CMD_DLY_PBITS - 1 : 0] dly;        // [7:0]  - duration of quarter i2c cycle (if 0, [3:0] control SCL+SDA)
            8'h02, //a,  // input   [SENSI2C_CMD_DLY_PBITS - 1 : 0] dly;        // [7:0]  - duration of quarter i2c cycle (if 0, [3:0] control SCL+SDA)
            2'b0,   // input    [SENSI2C_CMD_SCL_WIDTH -1 : 0] scl_ctl;    // [1:0] : 0: NOP, 1: 1'b0->SCL, 2: 1'b1->SCL, 3: 1'bz -> SCL 
            2'b0);  // input    [SENSI2C_CMD_SDA_WIDTH -1 : 0] sda_ctl;    // [3:2] : 0: NOP, 1: 1'b0->SDA, 2: 1'b1->SDA, 3: 1'bz -> SDA  
    TEST_TITLE = "RESEST_I2C_SEQUENCER1";
@@ -963,7 +963,7 @@ assign #10 gpio_pins[9] = gpio_pins[8];
            1'b1,   // input                                   set_bytes;  // [11] if 1, use bytes (below), 0 - nop
            2'h3,   // input  [SENSI2C_CMD_BYTES_PBITS -1 : 0] bytes;      // [10:9] set command bytes to send after slave address (0..3)
            1'b1,   // input                                   set_dly;    // [8] if 1, use dly (0 - ignore)
            8'h0a,  // input   [SENSI2C_CMD_DLY_PBITS - 1 : 0] dly;        // [7:0]  - duration of quarter i2c cycle (if 0, [3:0] control SCL+SDA)
            8'h02, //a,  // input   [SENSI2C_CMD_DLY_PBITS - 1 : 0] dly;        // [7:0]  - duration of quarter i2c cycle (if 0, [3:0] control SCL+SDA)
            2'b0,   // input    [SENSI2C_CMD_SCL_WIDTH -1 : 0] scl_ctl;    // [1:0] : 0: NOP, 1: 1'b0->SCL, 2: 1'b1->SCL, 3: 1'bz -> SCL 
            2'b0);  // input    [SENSI2C_CMD_SDA_WIDTH -1 : 0] sda_ctl;    // [3:2] : 0: NOP, 1: 1'b0->SDA, 2: 1'b1->SDA, 3: 1'bz -> SDA  
    TEST_TITLE = "RESEST_I2C_SEQUENCER2";
@@ -975,7 +975,7 @@ assign #10 gpio_pins[9] = gpio_pins[8];
            1'b1,   // input                                   set_bytes;  // [11] if 1, use bytes (below), 0 - nop
            2'h3,   // input  [SENSI2C_CMD_BYTES_PBITS -1 : 0] bytes;      // [10:9] set command bytes to send after slave address (0..3)
            1'b1,   // input                                   set_dly;    // [8] if 1, use dly (0 - ignore)
            8'h0a,  // input   [SENSI2C_CMD_DLY_PBITS - 1 : 0] dly;        // [7:0]  - duration of quarter i2c cycle (if 0, [3:0] control SCL+SDA)
            8'h02, //a,  // input   [SENSI2C_CMD_DLY_PBITS - 1 : 0] dly;        // [7:0]  - duration of quarter i2c cycle (if 0, [3:0] control SCL+SDA)
            2'b0,   // input    [SENSI2C_CMD_SCL_WIDTH -1 : 0] scl_ctl;    // [1:0] : 0: NOP, 1: 1'b0->SCL, 2: 1'b1->SCL, 3: 1'bz -> SCL 
            2'b0);  // input    [SENSI2C_CMD_SDA_WIDTH -1 : 0] sda_ctl;    // [3:2] : 0: NOP, 1: 1'b0->SDA, 2: 1'b1->SDA, 3: 1'bz -> SDA  
    TEST_TITLE = "RESEST_I2C_SEQUENCER3";
@@ -987,7 +987,7 @@ assign #10 gpio_pins[9] = gpio_pins[8];
            1'b1,   // input                                   set_bytes;  // [11] if 1, use bytes (below), 0 - nop
            2'h3,   // input  [SENSI2C_CMD_BYTES_PBITS -1 : 0] bytes;      // [10:9] set command bytes to send after slave address (0..3)
            1'b1,   // input                                   set_dly;    // [8] if 1, use dly (0 - ignore)
            8'h0a,  // input   [SENSI2C_CMD_DLY_PBITS - 1 : 0] dly;        // [7:0]  - duration of quarter i2c cycle (if 0, [3:0] control SCL+SDA)
            8'h02, //a,  // input   [SENSI2C_CMD_DLY_PBITS - 1 : 0] dly;        // [7:0]  - duration of quarter i2c cycle (if 0, [3:0] control SCL+SDA)
            2'b0,   // input    [SENSI2C_CMD_SCL_WIDTH -1 : 0] scl_ctl;    // [1:0] : 0: NOP, 1: 1'b0->SCL, 2: 1'b1->SCL, 3: 1'bz -> SCL 
            2'b0);  // input    [SENSI2C_CMD_SDA_WIDTH -1 : 0] sda_ctl;    // [3:2] : 0: NOP, 1: 1'b0->SDA, 2: 1'b1->SDA, 3: 1'bz -> SDA