Altera_Forum
Honored Contributor
14 years agoLack of capability with Qsys conduits
Hello all,
My apologies in advance, but this is a long-winded one... my inner monologue seems to be broken today. :D I have a bit of an outstanding issue with what, to me anyways, seems like a gaping hole in the the capabilities offered by Qsys (and, prior to that, SoPC Builder). To illustrate it, I'll provide the specifics of the use case I'm presently being affected on. I have a design which is producing a number of different packet streams, bound for transmission over a 1G Ethernet interface. The MAC and the arbitration stage are custom-designed - this is *not* using the ATSE, nor can it. So the suggestion "you should just use the ATSE" is a non-starter. The arbiter provides N "client" interfaces, and uses a couple of handshaking signals in addition to the data. Each client asserts a "valid" signal when it has a packet to send, along with the first byte of the packet header. This amounts to an arbitration request. When the client has been selected by the Tx arbiter, it then asserts an "advance" signal to the client for a few cycles - this instructs the client to feed the next few bytes into the arbiter's pipeline while it is enforcing the IFG and beginning to produce the packet's preamble and SFD sequence. At exactly the right moment in the sequence, another signal "ack" is pulsed for one clock, which directs the client to proceed with the remainder of the packet all the way to its end. The client lowers its "valid" signal to end the packet. All of these signals are also qualified by a "clockenable" signal, allowing the interface to throttle the data rate for 100M links as well as 1G. My first thought was to implement the Qsys component wrapper by adapting the interface described above to an Avalon-ST link. However, it pretty quickly became apparent that this wasn't really a good fit. First, an Avalon-ST sink has only one signal to send back to the source, "ready" - I would somehow need to multiplex the "advance", "ack", and even "clockenable" into this one signal. There's no clean way to do that - I'm not saying it's impossible, but it would be ugly and probably necessitate changes to the existing core logic being wrapped for Avalon, which is not really acceptable anyways since it is already running in a lot of designs on different targets. Second, the "valid" signal in Avalon-ST can't be used as an arbitration request signal; per the Avalon-ST spec, data symbols are always transferred on every cycle in which valid is asserted, it's merely up to the Source to deassert valid within the appropriate ready latency. I could, of course abuse the spec and just do whatever I want with the signals, but... well, I'll get to that. So instead I opted to use the free-form "conduit" interface type. This worked fine for my initial design which had only one packet source and consequently no arbitration stage. Then I added it in along with another packet source, and trouble ensued. As I added a Qsys wrapper to the arbiter, I created several conduit interfaces, giving them names like "client_tx_0", "client_tx_1", etc. Since the signals down in the HDL module also require unique names, they similarly received names like "Client_Tx_Data_0", "Client_Tx_Valid_0", etc. But when I tried to bolt this up to my transmitting clients, everything compiled but.. nothing worked! After a little investigation, I found that the conduits weren't actually connecting anything together. In hindsight, I should have realized they wouldn't - the conduit interface has no real "roles" for its signals, they all are just uniformly given the psuedo-role of "export". The only scheme used to make the logical connections between the two ends of a connection made in Qsys is by an *exact name match*. This just plain old does not scale; clearly, I can't design my FIFO-based Avalon-MM Ethernet peripheral for the NIOS2 to have the signal names "Client_Tx_Valid_3", "Client_Tx_Ack_3", etc. with the intent that it will *only* ever be used in a design where it is bolted up to the fourth interface of our Tx arbiter block! In fact, I might have two NIOS2's, each with one of these peripherals, and both sharing the same Ethernet port through an arbiter - how would that work? As a result, I have to resort to a very, very silly workaround - I export these interfaces from the Qsys design, and then hand-wire things in my top-level HDL. Very ugly, as there is no way to visualize these connections in the Qsys GUI (in fact, they just look "unconnected" since they're exported). Really, the simple solution for Altera to implement would be to allow the use of free-form signal roles within conduit interfaces. Instead of: add_interface client_0_tx conduit end add_interface_port client_0_tx Client_Tx_Enable_0 export Output 1 add_interface_port client_0_tx Client_Tx_Lock_0 export Input 1 add_interface_port client_0_tx Client_Tx_Data_0 export Input MAC_PORT_WIDTH add_interface_port client_0_tx Client_Tx_Valid_0 export Input MAC_PORT_WIDTH/8 ... what I would *really* like to be able to do is this: add_interface client_0_tx conduit end add_interface_port client_0_tx Client_Tx_Enable_0 enable Output 1 add_interface_port client_0_tx Client_Tx_Lock_0 lock Input 1 add_interface_port client_0_tx Client_Tx_Data_0 data Input MAC_PORT_WIDTH add_interface_port client_0_tx Client_Tx_Valid_0 valid Input MAC_PORT_WIDTH/8 ... What the latter implies is the ability to assign roles to each of the signals, using whatever words I want. When Qsys generation occurs, all it needs to do is look for the matching role to connect the signals up. If a signal's role is "export", it can instead do the legacy behavior, which is to look for an exact name match. To keep things clean, Qsys could perform a DRC on each of your interfaces to make sure you're either using the "new" semantics, i.e. ascribing a unique role to each of your signals, or calling them *all* "export". Mixing user-defined roles as well as export *could* be figured out, but it would be sort of sloppy IMHO. I would think this should be pretty easy to implement; without it, there's no good solution. Probably the biggest bit of evidence in my mind that this is, as I've so carelessly characterized it, a "gaping hole" is the fact that some of Altera's own IP blocks with similar requirements solve the issue by sort of abusing the Avalon-ST interface standard. Take the altera_vectored_interrupt_controller for example. It supports up to 32 IRQ inputs, each of which can come from different modules within the system. Clearly, they can't expect these other modules to name their IRQ lines something like "vic_irq_5", using precognition to decide which input to the VIC someone is going to use (or, for that matter, the fact that they even intend to use the VIC!) So they make each interrupt client interface an Avalon-ST interface. But... it only uses two signal roles, valid and data. The valid signal is, actually, the IRQ pulse, and the data signal concatenates an ID and a configuration vector. Does it work? Yes, of course - but is it really being used as a streaming data source? No, not at all. What would actually be an even better solution to the general problem would be to allow free-form declaration of different interface types. These could even fundamentally behave exactly the same as conduit interfaces do, with the extension of signal roles as I described earlier. What if the Altera vectored interrupt controller had multiple interfaces of type "vectored_irq", and had the roles "irq", "id", and "config"? Wouldn't that be a much more literate way to do this, and much more illuminating to whomever looks at a design in the Qsys GUI than to see a bunch of Avalon-ST connections? And to the point of difficulty in implementation - again - this hardly needs to behave much differently than the generation / elaboration of conduits today. Just my three cents. ;)