DrTrigon

How to connect Wishbone Registers to pins defined as INOUT (BiDirectional)

Recommended Posts

To whom it may concern

 

As mentioned in Map Errors due to IOB / BUFGMUX clock component not placed at an optimal site pair more precise in post #9, I am working to Make a Wishbone Library based on a symbol created before.

 

Here I have the issue that I need to connect the "Wishbone_to_Registers_x10" to my symbol which has a data bus (8 bit) of pins defined as INOUT (BiDirectional), how to do that?

 

I could think of a solution by using a bus multiplexer (switching 8 bit in parallel at the same time), which I couldn't find - actually not even single bit. Another idea was to do it in ZPUino software by switching Wishbone output registers to high impedance, but could not find any info about that. The hints I found so far were; change the source - what I don't want to do at this stage - this is kind of similar to what is done for the I2C implementations as explained in I2C on the Papilio One Zpuino Core - but I did not understand them or better how to use them for a 8 bit bus on the Papilio Duo. So ... any explanation or hint how to solve this issue is very welcome at this stage. ;)

 

Thanks a lot for your time and greetings

Share this post


Link to post
Share on other sites

Ok, the quick and easy answer is avoid using Bidirectional pins in the beginning. :) It is much, much simpler if you define a pin as an input or an output at design time. Bidirectional pins should not be the default when you are connecting to the outside world, only use them if you have no other option, otherwise stick with input or output only. If you absolutely need to use bidirectional pins in order to change a pin from input to output at runtime then you are going to need to provide an Output Enable (OE) pin (or register) to control whether the pin is an input or an output since it can only be one or the other at any given time. The GPIO pins are a good example of how this is done using a register to control the OE (look at the pinout symbol on the right side of a ZPUino circuit). There is also examples in the Language Templates of Xilinx ISE and there should be an IOBUF or some such symbol that allows you to do it schematically.

 

I don't have Xilinx ISE installed on the computer I'm on right now so can't make a better example but this might be enough hints to get you on the right track. If not I can make a tutorial next week for this - it's a good topic to cover.

 

Jack.

Share this post


Link to post
Share on other sites

Hello Jack!

 

Ok, the quick and easy answer is avoid using Bidirectional pins in the beginning. :)

 

I have to stick to a given 3rd-party code and don't want to change it right now.

 

It is much, much simpler if you define a pin as an input or an output at design time. Bidirectional pins should not be the default when you are connecting to the outside world, only use them if you have no other option, otherwise stick with input or output only. If you absolutely need to use bidirectional pins in order to change a pin from input to output at runtime then you are going to need to provide an Output Enable (OE) pin (or register) to control whether the pin is an input or an output since it can only be one or the other at any given time.

 

You are perfectly right. Sorry I should have mentioned initially that the symbol has read (RD) and write (WR) pins to select the data flow direction.

 

The GPIO pins are a good example of how this is done using a register to control the OE (look at the pinout symbol on the right side of a ZPUino circuit). There is also examples in the Language Templates of Xilinx ISE and there should be an IOBUF or some such symbol that allows you to do it schematically.

 

I don't have Xilinx ISE installed on the computer I'm on right now so can't make a better example but this might be enough hints to get you on the right track. If not I can make a tutorial next week for this - it's a good topic to cover.

 

I looked for BUFs but couldn't find any suitable ones. Now you are mentioning IOBUF and that was exactly what I was looking for! ;) Thanks a lot! I'm away for experimenting now - will report back the results later...

 

Goodbye and thanks for all the fish!

 

ps.: The tutorial would be great anyway, just to see how you would do it - but for the moment I think I am fine.

Share this post


Link to post
Share on other sites

[...] will report back the results later...

 

Now few minutes later I played around and learned a lot again; how to create Iterated Instances (array of instances on buses) for buffers like IOBUF, learned about the fact that dedicated buffers for in- and output exists (IBUF and OBUF), how to use BUF to separate/combine nets of different names, learned again some important lessions about how to use ISE, how to edit the symbol, etc. ... - a lot nice new stuff...! Was cool - thanks!

 

So but when trying to synthesize the full blow example including ZPUino and correct/good CLK signal source etc. I ran into this:

 

ERROR:Xst:528 - Multi-source in Unit <Papilio_DUO_LX9> on signal <XLXI_48/XLXI_2/DIN<7>>; this signal is connected to multiple drivers.

Drivers are:

   Output port IOBUF:IO of instance <XLXI_48/XLXI_3_7>

   Output signal of BUFT instance <XLXI_48/XLXI_2/xone_wire_io/DATA<7>_DOUT<7>>

 

...this basically tells me what I intentionally did; I connected the INOUT port of my library (XLXI_2) to th IO port of an IOBUF (XLXI_3). What am I doing wrong? What am I missing?

 

Greetings

Share this post


Link to post
Share on other sites

Now few minutes later I played around and learned a lot again; how to create Iterated Instances (array of instances on buses) for buffers like IOBUF, learned about the fact that dedicated buffers for in- and output exists (IBUF and OBUF), how to use BUF to separate/combine nets of different names, learned again some important lessions about how to use ISE, how to edit the symbol, etc. ... - a lot nice new stuff...! Was cool - thanks!

So but when trying to synthesize the full blow example including ZPUino and correct/good CLK signal source etc. I ran into this:

ERROR:Xst:528 - Multi-source in Unit on signal >; this signal is connected to multiple drivers.

Drivers are:

Output port IOBUF:IO of instance

Output signal of BUFT instance _DOUT<7>>

...this basically tells me what I intentionally did; I connected the INOUT port of my library (XLXI_2) to th IO port of an IOBUF (XLXI_3). What am I doing wrong? What am I missing?

Greetings

Sounds like you have two outputs connected... Can you take a screenshot?

Share this post


Link to post
Share on other sites

Sounds like you have two outputs connected... Can you take a screenshot?

 

Sure I connected 2 BiDirectional ports together, see marked part in the attached screenshot. The datasheet of the DS1WM Synthesizable 1-Wire Bus Master (IP core) is freely available, if needed.

 

I'm not sure but I think I am allowed to reproduce the code (at least in parts) here as well, since the Acceptance letter states:

 

The software source code DS1WM does not require a license and may be freely copied, modified or distributed without restriction. No act or omission by Maxim Integrated shall be deemed to constitute a representation or warranty by Maxim Integrated as to the functionality or utility of DS1WM.

 

...as English is not my native language I might be fooled but I think it should be safe, right?

post-39148-0-51416800-1449402207_thumb.p

Share this post


Link to post
Share on other sites

Oh, this is something different then what I thought your problem was. :)

 

That IOBUF is not going to work because it is intended to be used with an external bidirectional pin. You cannot use High-Z states internally, only external pins have that capability so something like the IOBUF will not work on an internal bus. You can verify this by right clicking on IOBUF and selecting Symbol/Symbol Info. This will open a datasheet for the symbol and you will see it is intended for an external pin.

 

The big problem here is that ds1wm code that you have found is meant to be used at a top level, most HDL designers will not use a shared read and write bus internally in a design. It doesn't really cost anything to have separate read and write buses inside an FPGA and it greatly reduces the complexity because then you don't have to use read or write enable pins and worry about when you can read and write etc. It makes sense to use that when you are going to be connecting the read/write bus to physical pins because in that case you have a limited amount of IO pins and it is beneficial to share them for your data bus.

 

So long story short, this is not something that I've run into very often and don't really know the solution off the top of my head... I think that it might just be a matter of figuring out the right way to connect the data(7:0) bus to the register9_in and register9_out buses. I would have to experiment with different ways of doing this to see what works...

 

Let me think about this some more.

 

Jack.

Share this post


Link to post
Share on other sites

Hello Jack

 

That IOBUF is not going to work because it is intended to be used with an external bidirectional pin. You cannot use High-Z states internally, only external pins have that capability so something like the IOBUF will not work on an internal bus. You can verify this by right clicking on IOBUF and selecting Symbol/Symbol Info. This will open a datasheet for the symbol and you will see it is intended for an external pin.

 

Yes, I somehow got suspicious about using bidirectional pins internally - and yes I learned it now "the hard way" and will never forget this again. As a friend of mine formulated it very nicely: "'Bidirectional' is a quick way to get a headache." ;))) He told me even when using on external pins there are restrictions. So lets rip the thing apart. (May be I should not write that I actually had a look a the datasheet of IOBUF, but I missed this part...)

 

The big problem here is that ds1wm code that you have found is meant to be used at a top level, most HDL designers will not use a shared read and write bus internally in a design. It doesn't really cost anything to have separate read and write buses inside an FPGA and it greatly reduces the complexity because then you don't have to use read or write enable pins and worry about when you can read and write etc. It makes sense to use that when you are going to be connecting the read/write bus to physical pins because in that case you have a limited amount of IO pins and it is beneficial to share them for your data bus.

 

When thinking about it - using bidirectional internally must lead to shorting the chip as some point by accident. Thus I am actually quite happy that the software does refuse to generate such bitstreams. ;)

So my chip has 2 bidirectional pins - 1 is needed as the 1-wire bus is bidirectional, that's ok since it goes to an external pin. I had a look at the VHDL source and think its fairly straight forward to rip the bidirectional into 2 parts and separate in from out. I did it already.

 

The issue I have is; I actually don't know how to re-generate the symbol from the changed code? Somehow I should be able to update the symbol or generate it newly, right? Can you lead me through?

 

So long story short, this is not something that I've run into very often and don't really know the solution off the top of my head... I think that it might just be a matter of figuring out the right way to connect the data(7:0) bus to the register9_in and register9_out buses. I would have to experiment with different ways of doing this to see what works...

 

As long as there are no protection resistors available to insert on the schematic level, I think I am fine with changing the code now.

 

Do you have the source code for ds1wm?

 

Sure. Why?

 

Thanks a lot and greetings

Share this post


Link to post
Share on other sites

So the best thing to do to recreate the symbol is to right click on it and edit the symbol and change the bus names manually. Or edit the .sym file, it is just an xml file. Or delete the .sym file and then regenerate it with the changed buses.

 

The reason I asked if you had source code was to see if you could separate out the buses. That is probably the best solution here.

 

The other course of action I was going to suggest is to make a new symbol and use VHDL to define some code that will us an if statement to turn the bidirectional data bus into a read and write bus. It should work to define an IO bus, an out bus, an in bus, and a OE control line. Then use a VHDL if statement to connect either the input or output bus to the data bus depending on the OE control line. Connect the OE control line to the read line in your symbol...

 

Anyway, you are on the right path it seems.

 

Jack.

Share this post


Link to post
Share on other sites

So the best thing to do to recreate the symbol is to right click on it and edit the symbol and change the bus names manually. Or edit the .sym file, it is just an xml file. Or delete the .sym file and then regenerate it with the changed buses.

 

I was struggling quite a bit ... In my library folder are 2 projects; the ds1wm library and the wishbone variant. Basically I tried to change the .vhd file and regenerate the symbol of the first one which consists of 6 .vhd files. I was not able to do it since no matter what I tried, from removing 1 file to removing all in various ways - either ISE was not able to generate the new symbol or freezed.

I was never able to get to the view shown here having the new .vhd file separate, respective not in the Edit_Your_Chip_Design category and thus could not properly (re)generate the symbol. The 'Code to the VHDL File', 'Turn the VHDL File into A Schematic Symbol' and 'Edit Design' parts turned out to be quite critical in the end.

 

The only thing that helped in the end was compressing everything within the library folder into a archive and then delete it and start from an empty library folder. By doing so it worked and I was able to change my code as:

 

[...]

ENTITY ds1wm IS

   PORT (

      ADDRESS                 : IN std_logic_vector(2 DOWNTO 0);   

      ADS_bar                 : IN std_logic;   

      CLK                     : IN std_logic;

      EN_bar                  : IN std_logic;

      MR                      : IN std_logic;   

      RD_bar                  : IN std_logic;   

      WR_bar                  : IN std_logic;   

      INTR                    : OUT std_logic;   

      STPZ                    : OUT std_logic;  

--      DATA                    : INOUT std_logic_vector(7 DOWNTO 0);   

      DIN                     : IN std_logic_vector(7 downto 0);

      DOUT                    : OUT std_logic_vector(7 downto 0);

      DDIR                    : OUT std_logic;

      DQ                      : INOUT std_logic);

END ENTITY ds1wm;

[...]

--  signal DDIR                : std_logic;

--  signal DOUT                : std_logic_vector(7 downto 0);

  signal DQ_CONTROL          : std_logic;

--  signal DIN                 : std_logic_vector(7 downto 0);

[...]

  xone_wire_io : one_wire_io

    PORT MAP (

      CLK         => CLK,

--      DDIR        => DDIR,

      DDIR        => '0',

--      DOUT        => DOUT,

      DOUT        => "00000000",

      DQ_CONTROL  => DQ_CONTROL,

      MR          => MR,

--      DIN         => DIN,

      DQ_IN       => DQ_IN,

--      DATA        => DATA,

      DQ          => DQ

      );

[...]

 

So basically one_wire_io acts as an IOBUF that makes DATA from DIN, DOUT and DDIR. I disconnected this part of one_wire_io and feed the signals to pins instead.

 

The reason I asked if you had source code was to see if you could separate out the buses. That is probably the best solution here.

 

Yesss... I mean this is what I wanted to avoid in the first place... so I ended up doing it. ;) BUT thanks to you I learned a lot on this journey.

 

The other course of action I was going to suggest is to make a new symbol and use VHDL to define some code that will us an if statement to turn the bidirectional data bus into a read and write bus. It should work to define an IO bus, an out bus, an in bus, and a OE control line. Then use a VHDL if statement to connect either the input or output bus to the data bus depending on the OE control line. Connect the OE control line to the read line in your symbol...

 

I do not really get this one... this code containing the if statement would be the same as an IOBUF as I tried to use it, right? Since bidirectional lines are not supported internally what I understand is that all codes always use DIN and DOUT internally and create the bidirectional only before connecting to a pin as a very last step, like the code I use does:

 

    DATA <= DOUT when DDIR='1' else "ZZZZZZZZ";

    DIN <= DATA;

 

So finally I was able to synthesize today and now step 3 doing the ZPUino code will follow!

 

Thanks a lot for all support! Greetings and all the best!

ds1wm_owmaster_Wishbone.pdf

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now