I'm getting an empty netlist after running the synthesis on the I2C Slave. The inputs (
RESET) and the
SDA line are defined in the top module, and also the behavioural simulation is running properly. Is the reason because of deletion of a source file? If so, how can I check if it has been deleted? Or is it because it's doing some sort of optimization? I'm attaching the codes so it can be checked by others and it can help me figure out that if there is a problem with my vivado itself.
`timescale 1ns / 1ps module I2C_SLAVE #(parameter SLAVE_ADDR = 7'b1101010) // Slave Address for this module is 0x6A ( input Reset_L, // (WIRE) Active Low Reset to clear the data within slave and reset the registers input SCL, // (WIRE) Serial Clock inout SDA // (WIRE) Serial Data ); // STATES OF STATE MACHINE BETWEEN START AND STOP CONDITION localparam ADDRESS = 3'b000; // Address from the master is read and checked with slave address localparam ADDR_ACKN = 3'b001; // Acknowledgement from slave to master is sent from if address matches localparam RECEIVE = 3'b010; // If Address last bit is 0 then data is received from master to slave (WRITE OPERATION) localparam RX_ACKN = 3'b011; // Sends an Acknowledgement to master after the data is received localparam TRANSMIT = 3'b100; // If Address last bit is 1 then data is transmitted from slave to master (READ OPERATION) localparam TX_ACKN = 3'b101; // Waits for Acknowledgement from master after the data is transmitted localparam HOLD = 3'b110; // It is the rest state which implies slave is not active // STATE MACHINE VARIABLE reg [2:0] state_machine; // REGISTERS FOR INTERNAL OPERATIONS reg busy = 1'b0; // Used to activate and deactivate FSM (SLAVE) reg [7:0] address; // Used to hold the input serial data reg [2:0] bit_index; // Used in accessing each bit of address and data register reg [7:0] slave_data; // Data held by the slave // CONTROL REGISTERS TO ACTIVATE OUTPUT FUNCTION OF SDA reg SDA_EN; // Controls when the SDA should act as output reg SDA_OUT; // Holds the serial data to be transmitted from slave // SDA INPUT AND OUTPUT TRANSITION assign SDA = (SDA_EN) ? SDA_OUT : 1'bz; // [SDA_EN == 1] => O/P pin and [SDA_EN == 0] => I/P pin // START CONDITION always @(negedge SDA) // If SDA goes low when SCL is high then start condition occurs begin if (SCL == 1) // If busy is already high then repeated start condition occurs begin address <= 8'b0; // Address reg is reset to store the new address transmitted from master bit_index <= 3'b111; // Bit Index reg is preset as the first data transmitted will be MSB state_machine <= ADDRESS; // SM variable is set to first state where address is obtained if (busy == 0) busy <= 1'b1; // Busy reg is made high indicating the slave FSM is active end end // STOP CONDITION always @(posedge SDA) // If SDA goes high when SCL is high then stop condition occurs begin if ((busy == 1) && (SCL == 1)) busy <= 1'b0; // Busy reg is made low indicating the slave FSM is inactive end // FSM FOR OPERATIONS always @(posedge SCL) // SDA will be checked during SCL high condition begin if (~Reset_L) // Clears the data held by slave begin SDA_EN <= 1'b0; SDA_OUT <= 1'b0; slave_data <= 8'b0; end if (busy == 1) begin case(state_machine) ADDRESS: begin if (bit_index > 0) begin address[bit_index] <= SDA; bit_index <= bit_index - 1; // Bit index reg is decremented until last bit is received end else state_machine <= ADDR_ACKN; end ADDR_ACKN: begin if (address[7:1] == SLAVE_ADDR) // Compares the address transmitted by master with the slave's address begin // If address matched, based on operation to be performed the FSM moves to next state bit_index <= 3'b111; // Presets the bit index reg if(address == 0) // If Address Bit == 0 then slave becomes data receiver state_machine <= RECEIVE; // WRITE OPERATION else // If Address Bit == 1 then slave becomes data transmitter state_machine <= TRANSMIT; // READ OPERATION end else state_machine <= HOLD; // If address does not match slave moves to HOLD state end RECEIVE: begin slave_data[bit_index] <= SDA; // Serial data is written into to the slave data buffer reg if (bit_index == 0) state_machine <= RX_ACKN; // FSM moves to acknowledgement state where slave sends to master else bit_index <= bit_index - 1; // Bit index reg is decremented until last bit is received end RX_ACKN: begin bit_index <= 3'b111; // Presets the bit index reg state_machine <= ADDRESS; // FSM moves to ADDRESS state after sending an acknowledgement so that master can perform operations on other slave if interested end TRANSMIT: begin if (bit_index == 0) state_machine <= TX_ACKN; // FSM moves to acknowledgement state where the master sends to slave else bit_index <= bit_index - 1; // Bit index reg is decremented until last bit is received end TX_ACKN: begin if (SDA == 0) // After getting acknowledgement from master the FSM moves to ADDRESS state begin bit_index <= 3'b111; // Presets the bit index reg state_machine <= ADDRESS; // Master can perform operations on other slaves or stop end else // If acknowledgement is not received from the master then slave enters HOLD state state_machine <= HOLD; end default: // The default state will be HOLD state where the slave will not respond or interact with the master state_machine <= HOLD; endcase end end // ACKNOWLEDGEMENT AND DATA IS TRANSMITTED BY ENABLING SDA AS OUTPUT PIN always @(negedge SCL) // Change in SDA needs to take place only during SCL low condition begin case(state_machine) ADDR_ACKN: begin // SDA will become output pin as slave needs to send acknowledgement to master SDA_EN <= 1'b1; SDA_OUT <= 1'b0; end RX_ACKN: // Write Acknowledgement begin // SDA will become output pin as slave needs to send acknowledgement to master SDA_EN <= 1'b1; SDA_OUT <= 1'b0; end TRANSMIT: // Read Acknowledgement begin // SDA will become output pin as data held by slave needs to be trasmitted to master SDA_EN <= 1'b1; SDA_OUT <= slave_data[bit_index]; // Data is fed serially to SDA output pin end default: SDA_EN <= 1'b0; // By default SDA will be kept as input pin unless SDA should act as output pin endcase end endmodule
`timescale 1ns / 1ps // TIME PERIOD OF SCL = 4 microseconds // TIME PERIOD OF FPGA CLOCK = 10 nanoseconds module I2C_SLAVE_TB(); reg clock, reset_l, reset_l_generator; wire o_scl_gen, SCL; wire SDA; reg sda_tb, sda_drive, scl_en, scl_tb; SCL_GENERATOR scl_generator_inst(clock, reset_l_generator, o_scl_gen); I2C_SLAVE i2c_slave_inst(reset_l, SCL, SDA); assign SCL = (scl_en) ? scl_tb : o_scl_gen; assign SDA = (sda_drive) ? 1'bz : sda_tb; pullup(SDA); initial begin reset_l = 1'b0; reset_l_generator = 1'b0; scl_en =1'b1; scl_tb = 1'b1; clock = 1'b0; forever #5 clock = ~clock; end initial begin sda_drive = 1'b0; sda_tb = 1; #2000 sda_tb = 1'b0; end initial begin #1000 reset_l_generator = 1'b1; #2500 reset_l = 1'b1; scl_en = 1'b0; #2500 sda_tb = 1'b1; #3995 sda_tb = 1'b1; #3995 sda_tb = 1'b0; #3995 sda_tb = 1'b1; #3995 sda_tb = 1'b0; #3995 sda_tb = 1'b1; #3995 sda_tb = 1'b0; // bit represents read write bit (write = 0, read = 1) #3995 sda_drive = 1'b1; // TESTING RECEIVE(WRITE) OPERATION OF SLAVE: #3995 sda_drive = 1'b0; #3995 sda_tb = 1'b1; #3995 sda_tb = 1'b0; #3995 sda_tb = 1'b0; #3995 sda_tb = 1'b1; #3995 sda_tb = 1'b0; #3995 sda_tb = 1'b1; #3995 sda_tb = 1'b1; #3995 sda_tb = 1'b0; sda_drive = 1'b1; #5000 scl_en = 1'b1; // making the SCL line high till next operation is performed on it. scl_tb = 1'b1; end endmodule
`timescale 1ns / 1ps // Parameters: I2C SCL clock frequency for Magnetometer is within range 100 - 400 kHz // Considering SCL of 250 kHz and FPGA Master Clock of 100 Mhz // 1 SCL Clock Cycle = 400 Master Clock Cycles module SCL_GENERATOR #(parameter MASTER_CLKS = 200) ( input wire Clock, // FPGA Main Clock is given as input for Clock generator input wire Reset_L, // Active low Reset used in initializing the Clock generator output reg SCL_Clk // Used as Serial Clock input in I2C protocol communication ); reg [$clog2(MASTER_CLKS)-1:0] Clk_Count; // Used to Count the number of clock pulses from Main Clock always @(posedge Clock) begin if (~Reset_L) // Useful in reseting the count register and initializing the SCL value as 0 begin SCL_Clk <= 1'b0; Clk_Count <= 8'b0; end else begin if (Clk_Count < MASTER_CLKS - 1) // Counts 400 Main Clock pulses Clk_Count <= Clk_Count + 1; else begin // Complements the SCL_Clock to create pulse train every 400th Clock Pulse SCL_Clk <= ~SCL_Clk; // Useful in maintaining the 250 kHZ SCL Frequency Clk_Count <= 0; end end end endmodule