Driving bidirectional lines in Verilog
this question probably wont be explained very well and that's because I don't really understand what's happening in my design.
I need to use an I2C communication bus to talk to a camera (Terasic D5M) so I tried to write one using Verilog. I only need a master. On my logic analyzer everything looks great except I keep getting NACK signals from the camera. Initially I had no idea what was wrong so I just put开发者_运维问答 it aside.
Tonight I tried to use the Altera University IP Core which has a module for the D5M. After setting this to automatically initialize I watched what was going on on my analyzer. The trace looks the same as the output from my I2C module except this is registering an ACK by the device.
My problem is, I cannot for the life of me figure out why I'm not getting an acknowledgement. It may be that I'm not allowing the camera to pull the sda line low (scl works fine) but I cannot figure out why this would be.
Has anyone has any similar experiences or have any idea where I should go look / post / read? I would post some code but I don't know how useful it's going to be if it's not in its entirety. Sorry about being so vague but I'm really lost and don't even know what I should be asking; I guess this is a similar effect request. Thanks for any help, here's a little bit of code for the output lines from the i2c module.
`define HIGH 1'bZ
`define TRUE 1'b1
`define FALSE 1'b0
inout sda;
assign sda = (ena_sda)?sda_bit:`HIGH;
inout scl;
assign scl = (ena_scl)?pSCL:`HIGH;
pSCL is a clock that runs at the desired rate and sda_bit is the value of the sda line during operation. Here is the section that releases and waits for the ack. This is embedded in my shifting state, hence the beginning else if.
// Data shifting complete, check for ACK
// Release the SDA line and set our bit to high Z
else if(shiftComplete == `TRUE) begin
ena_sda = `FALSE;
sda_bit = `HIGH;
if(negedge_SCL) begin
ena_sda = `TRUE;
case(i2cState)
`DATA_STATE:
begin
shiftComplete = `FALSE;
nxState = `DATA_STATE;
end
`START_STATE: nxState = `REPEAT_START_STATE;
default: nxState = `STOP_STATE;
endcase
end
end /* end ACK */
I would think that releasing ena_sda would be enough to let the camera drive the module. I think I put the sda_bit = HIGH before as a test (I haven't looked at this in a month).
I would be happy to share more code or show my logic traces but I don't want to clutter this anymore. Thanks for reading.
I would separate the input and output and add to that an output enable, basically not use an inout. Does your altera device's I/O pads support being used that way? (they should) If so let the I/O pad do the inout work. Also have you defined the I/O pad as a push-pull or wired-or, or weak pull up or any of those? In some cases you may choose to have it a push-pull when output is enabled and when an input it tri-states allowing the other side to control the data line.
精彩评论