VHDL: Tri-State Buffer Control - Page 1
Forum section: electronics / general

author: tec5c
author_rank: Frequent Contributor
timestamp: September 27, 2015, 09:31:00 am
content: Hi all,I'm using an INOUT port and am wanting to define it as either an input or an output for a specific function, i.e., writing to a RAM block.I have read certain things about controlling the port by using something like the following:data <= data_out when (........) else (others => "ZZZZ");If in the above, data is defined as an INOUT port do you have to declare the data_out as an output port or will it be recognised that you're wanting to set the INOUT port as an output for whatever is contained inside the parentheses?I guess I was a little premature in making this thread as I could have easily attempted to do what I was asking about and see if it threw an ".... is not declared" error at me. Which I have just done, and sure enough it gives said error.I guess now I just need to figure out how to implement the output port into my program.

author: tec5c
author_rank: Frequent Contributor
timestamp: September 27, 2015, 11:26:49 am
content: I have tried two things in order to get this to work.Firstly, I tried doing away with the INOUT data bus and having them as separate IN and OUT ports, which didn't work. I'm not sure if there needs to be a MUX involved when doing this method?Secondly, I tried the approach of declaring an OUTPUT signal which essentially gave the same results as the above method, which I guess makes sense?The problem that I'm having with just using an INOUT data bus is that when I try to store the accumulator value, it results in an unknown logic value, i.e., '0X10' when it should be '0110'. Not quite sure how to tackle this problem (quite new to VHDL).Any thoughts? I can provide code and/or testbench waveform diagrams if necessary.

author: dmills
author_rank: Super Contributor
timestamp: September 27, 2015, 05:40:48 pm
content: Tristate in FPGAs only really makes sense for physical IO pin drivers, and depending on the FPGA in question either setting the signal to the pin driver to "Z" or using a specific library block with a separate tristate control line can be the way to do this.Nothing internal to the FPGA core really supports tristate, that is a physical pin thing.Internally, FPGA memory blocks generally have separate input and output signals.The best piece of advice I ever received for beginning FPGA work is 'Start by drawing the circuit diagram, then translate that to the HDL'.Regards, Dan.

author: hamster_nz
author_rank: Super Contributor
timestamp: September 27, 2015, 08:34:25 pm
content: TL;DR - don't use tristate logic. use a separate data_in and data_out bus. If that doesn't work it is your logic at fault.I've never seen an FPGA with tristate logic within the fabric. On the edge of the FPGA a tristate driver is implemented using an I/O buffer that looks like this:The tools map an "inout" port to 'I', 'O' and 'T' inputs. If anybody asked me, I strongly recommend you never pass an INOUT signal outside of the top-level of a design, but quickly convert it into data_in, data_out, tristate signals. This stops a logic error deep in your design locking a bus that may run across the entire design - which is a real pain to debug. Another trap for young players is that the 'T' signal can be relatively slow to take effect, and can be a problem for high speed designs like SDRAM interfaces.However... if you really have to use any tristate logic within the internals of your FPGA project the tools attempt to map it to a common bus with a single driver, and logic structure that selects who is driving that bus at any time - maybe something like:Code:bus <= (driver1_data and driver1_enable) or (driver2_data and driver2_enable) or (driver3_data and driver3_enable) or ....Unlike actual tristate drivers this is not a very efficient structure and doesn't scale very well as you end up with high fan-out nets running all over the FPGA.But it does tell you something that may be of value - each module that connects to the bus must have a clearly identifiable "output_enable" signal for each module that drives the bus, and for the design to work properly you must ensure that only one output_enable for a bus can be asserted at any time.So if you are connecting a memory to a CPU you need something like this:Code:with output_enable select data <= "ZZZZ" when '0', mem(addr) when others;...and output_enable should only be asserted only during read cycles, (during which time the CPU's own output_enable has to be turned off).If you have multiple components drive the same bus at the same time, nothing really bad will happen (no flames or smoke), but the value on the logical bus will be some mashup of the requested values - and this is why you are getting the 'X's during simulation - it is where the data bus is getting driven with a "1" by one device and a "0" by another.

author: tec5c
author_rank: Frequent Contributor
timestamp: September 28, 2015, 04:26:48 am
content: Thanks for the replies.Hamster, what you said makes sense.I did try the dual data bus (separate in and out ports) though it still did not work, so I'm starting to think that perhaps there's errors somewhere else in my program?I think the next thing I'll try will be to implement the output enable signal, though I'm not entirely sure I know how to do this... still learning!