New FPGA convert here. I am trying to interface with a parallel ADC as part of a data acquisition project. The pins on the ADC are used for both input and output (not simultaneously). Therefore, I need to drive the pins when I want to write control data to the ADC and read data values from the ADC when it is done with conversion. What are the different ways to do that? (I have an FSM driving the write and read signals so I know they are not simultaneous.)
I am currently going with the first approach (from comments) of splitting the signals into input and output versions at the top level, but I am having no joy with it. Here is an excerpt of my code and the picture of the FPGA family's IO pin in bidirectional mode:
inout [11:0] adc_data_pin_top assign adc_data_pin_top = ~write_adc_data_n ? written_data_temp : 12'bz; assign data_from_adc = converted_datas; always @ (posedge adc_clock) begin converted_datas <= adc_data_pin_top; written_data_temp <= written_data_adc; end
My problem is that I cant read the data from the ADC. My adc_data_pin_top lines 'hold' values from the previous write cycle and spit it right back to me during my read cycle. I tried to use two tri-state buffers as shown below to make sure the write values are not 'leaking' to the input ports during a read cycle but that didnt help much. I am not sure if the tri-state buffer has to be clocked or not(i.e. if I need to use a register or just wires). Also, what exact value is a tristate signal(High Z) synthesized as in hardware? 0V? 1.4V? 2V? 3.3V? In other words, what should I expect to read when I am neither in read nor write cycle? You can see a diagram of altera's IO diagram of the pin on Page 2 of the document listed below the code:
assign adc_data_pin_top = (write_adc_data_n) ? 12'bZ : written_data_temp; assign converted_datas = (read_adc_data_n) ? 12'bZ : adc_data_pin_top;
Newbie alert! Sorry for all the triple-posting.
Edit: Chris, thanks for your help! The page won't let me comment on your comment, lol. So, I'm just going to comment here. The read and write signals are low enable and should be named that way-I'll fix that right now. Adding that inverter to the condition is probably redundant as well-read somewhere that old altera tools had a preference. I see what you are saying about the second statement--any high Z assignment infers a tristate buffer and I would have to pass that tri-state buffer(converted_datas) to my inner module which defeats the purpose of a split.
Further edits: Actually, on second thought, that is a GREAT idea! I do have push-button switches on the dev-kit that I can use to model an external switch. That way I can verify my HDL structure at least. But I cant read out my output signals unless I finally breakout that HSMC connector
Edit3: Hey Chris, finally got around to running that experiment today. I am able to drive the LED when the bidirectional bus is not in tristate. But because I cannot drive an input into the FPGA(and bidirectional pin) to simulate a one-bit ADC input, I cant verify that the bidirectional port is in tristate/read mode. Any ideas on how to get an input into an FPGA board with no GPIOs(except an HSMC connector)? Thanks!
Update: Yhello! Finally figured out a way to drive a signal into the FPGA via HSMC connector and was able to run a modified version of Chris' experiment--that was awesome! Now that I know my HDL bidirectional construct works, its one less variable to worry about. I figure the data being "spat" back to me is just the bus-hold feature of the FPGA board doing it work at high frequency to prevent metastability. That narrowed the possible issue down to control signal timing as I was not seeing data. Slackening the deadlines for the controls solved the problem. I am ecstatic to report my ADC is up and running! Thanks, Chris!