0
\$\begingroup\$

I have a Spartan 3-E board.I was using the inbuilt Xilinx SRL 16 (16 bit concatenated shift registers) for I2C communication.I verified successful implementation by displaying the number of "Acks" received on LEDs i.e (I had an internal counter which would increment if SDA was pulled low during the 9th clock cycle).My problem starts when instead of using the Xilinx SRL primitive, I built my custom 8bit Left Shift Register.I had to do this because the system has to be kept idle for some time and only a few specific registers need to be programmed so I can't rely on the auto increment feature.Any way, I haven't been able to verify I2C comm. as before, despite keeping all other aspects the same and ensuring absolutely zero difference between simulation patterns of the earlier successful design and this new one. I am sharing my code and would be extremely grateful to anyone who could have a look.

 STARTING CONDTION : I am using PULLups on both SCL and SDA. ------------------8-bit SRL----------------

module CustomSRL(
    input [7 : 0] Value,
    input LE,
    input CE,
    input clk_i2c,
    output Q
);
reg [7 : 0] SRL_8;
always @ (posedge clk_i2c)
begin
    if(CE) begin
    if(LE) SRL_8 <= Value;
    else   SRL_8 <= {SRL_8[6 : 0],1'b0};
          end   
end
    assign Q = SRL_8[7];
endmodule

UPDATE :

I was just experimenting and realized that when I replace my custom Shift Register (provided above) with the SRL16 E primitive, the design works.This is very surprising.I tried to make small changes to the logic by using a simple register with a Load Enable and a multiplexer to single out the bits.However, that doesn't work either.

Why is it that the SRL16E primitive design works but not the others? I have provided code for my shift register (serial in,serial out, parallel synchronous load) module above.The simulation results are the same for all three designs.

Can anyone offer an explanation for this apparently bizarre behavior? Sending Values to 8 bit Shift Register :

always @ (*)
begin
    case (Byte_Counter) 
    0 : LUT <= 8'h56;                                   //Device Addres  
    1 : LUT <= i2c_address;                         //Register Address
    2 : LUT <= i2c_val;                             //Data
    5 : LUT <= 8'h7E;                                   //STOP & START
    default : LUT <= 8'hFF;
    endcase
end

    always @ (*)
begin
    case (Reg_Counter)
    1 :begin i2c_address <= 8'h00; i2c_val <= 8'h02;    end           
    2 :begin i2c_address <= 8'h03; i2c_val <= 8'h00;   end   
    3 :begin i2c_address <= 8'h05; i2c_val <= 8'h09;   end   
    4 :begin i2c_address <= 8'h07; i2c_val <= 8'h07;   end
    5 :begin i2c_address <= 8'h09; i2c_val <= 8'h00;    end
    default : begin i2c_address <=8'h00; i2c_val <= 8'h00;   end
    endcase
end

Variable LUT is loaded into the 8 bit Shift Register on the 9th(when SDA=high impedance) clock cycle.

One thing that I'd like to add is that I tried to register the outputs of the multiplexers before packing it off to the 8-bit SRL by :

always @ (posedge clk_i2c) temp <= LUT;

However, that hasn't worked either, but I do get one interesting warning :

INFO:Xst:2260 - The FF/Latch <i2c_ADV7171/temp_6> in Unit <Verilog> is equivalent to the following FF/Latch : <i2c_ADV7171/temp_4>

As far as I can tell, this shouldn't happen because temp[6] and temp[4] aren't throughout equal.

\$\endgroup\$
  • \$\begingroup\$ The picture added is of the STARTING CONDITION. I am using PULL UPS on both SCL and SDA. \$\endgroup\$ – Ahmed Ali Abbasi Mar 5 '17 at 15:51
  • \$\begingroup\$ In the picture I think that I see SDA falling just before SCL turns low. The SDA must be valid as long as SCL is high. The SDA is allowed to change at the same moment the SCL turns low for I2C, but not for the SMBus. For the SMBus the SDA may only change after the SCL has turned low (that is safer). \$\endgroup\$ – Jot Mar 6 '17 at 23:15
  • \$\begingroup\$ I have reconfirmed that the SDA line goes low before SDA for I2C communication.Plus, this exact waveform works when I use a Xilinx SRL16E primitive, instead of using the SRL I've coded above. Other then that, I 've also tried to use a simple 16 bit register and mux out the outputs, one by one, which hasn't worked either.Could you take a look at the SRL module in the code above? It simulates perfectly but doesn't work. \$\endgroup\$ – Ahmed Ali Abbasi Mar 7 '17 at 6:09
0
\$\begingroup\$

The problem was with the hold time.Since the SDA line changed exactly on the falling edge of SCL, There was a hold time violation.I added a flip flop to produce a delay of around 600ns and the design works. I have read that such a constraint matters with certain Analog Devices components.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.