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.
------------------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.