![]() |
|
|
|||||||
![]() |
VHDL - Can a signal be resolved as 'most recent event wins'? |
|
|
Thread Tools | Search this Thread |
|
|
#1 |
|
Hi,
This is an exercise in simplifying port maps in testbench code. I'm trying to use a record as a bus with signals going in opposite directions. Is this possible in VHDL? Something like this: type mytype is record cmd : with_the_flow type; busy : against_the_flow type; end record; The idea is to have this record be an in-signal for entity A and an out-signal for entity B. Which makes signal.busy an out signal for entity A and an in-signal for entity B. I'm fairly sure that no such thing exists in VHDL. To solve the problem, I tried to describe the record as a resolved bus. The idea is to declare the bus as inout signals for both entities and fix the multiple driver problem by resolving the individual record elements. Entities A & B know which end of the bus they represent, so only A ever drives signal.busy and only B ever drives signal.cmd. I think the problem boils down to having to resolve such that the most recent assignment wins. Typical resolution functions will look at the signal values, I would like to look at the signal attributes. Unfortunately, I don't seem to be able to get at the attributes of the component signals of the record, only the attributes of the record itself: package test is type cmd_t is (idle,read,write); type operation_t is record cmd : cmd_t; busy : boolean; end record; type op_vector is array (integer range <>) of operation_t; function op_resolve(ov : in op_vector) return operation_t; subtype op_t is op_resolve operation_t; end test; package body test is function op_resolve(ov : in op_vector) return operation_t is variable f2p_i : integer := 0; variable p2f_i : integer := 0; variable result : operation_t; begin -- Current assignment wins for i in ov'range loop -- OK if ov(i).cmd'event then -- This breaks f2p_i := i; end if; if ov(i).busy'event then p2f_i := i; end if; end loop; result.cmd := ov(f2p_i).cmd; result.busy := ov(p2f_i).busy; return result; end function op_resolve; end package body; The compiler says Model Technology ModelSim ALTERA vcom 6.1g Compiler 2006.08 Aug 12 2006 -- Loading package standard -- Compiling package test -- Compiling package body test -- Loading package test ** Error: Z:/resolving.vhd(27): Attribute "event" requires a static signal prefix. ** Error: Z:/resolving.vhd(30): Attribute "event" requires a static signal prefix. ** Error: Z:/resolving.vhd(39): VHDL Compiler exiting Is there a way to get at the record member attributes? Kind regards, Iwo Iwo Mergler |
|
|
|
|
#2 |
|
Posts: n/a
|
Iwo Mergler wrote:
> This is an exercise in simplifying port maps in > testbench code. > I'm trying to use a record as a bus with signals > going in opposite directions. Is this possible > in VHDL? This is problematic. See: http://groups.google.com/groups/sear...ucture+norberg (and many others) Consider using remote procedures as an alternative http://home.comcast.net/~mike_tresel...c_overload.vhd Good luck. -- Mike Treseler Mike Treseler |
|
|
|
#3 |
|
Posts: n/a
|
Iwo,
I do this by individually resolving the elements of the record. The easy way to do this is to assign the driving value of a port to an identity value when it is not being driven. The obvious example is to drive a 'Z' for a std_logic element of the record. For other types, you can write a resolution function by deciding that 0 makes a good identity element. The package ResolutionPkg.vhd shows two different ways to do this (I generally use resolved): http://www.synthworks.com/papers/ResolutionPkg.vhd Cheers, Jim > Hi, > > This is an exercise in simplifying port maps in > testbench code. > > I'm trying to use a record as a bus with signals > going in opposite directions. Is this possible > in VHDL? > > Something like this: > > type mytype is > record > cmd : with_the_flow type; > busy : against_the_flow type; > end record; > > The idea is to have this record be an in-signal > for entity A and an out-signal for entity B. > Which makes signal.busy an out signal for entity > A and an in-signal for entity B. > > I'm fairly sure that no such thing exists in VHDL. > > To solve the problem, I tried to describe the > record as a resolved bus. The idea is to declare the > bus as inout signals for both entities and fix the > multiple driver problem by resolving the individual > record elements. > > Entities A & B know which end of the bus they represent, > so only A ever drives signal.busy and only B ever drives > signal.cmd. > > I think the problem boils down to having to resolve such > that the most recent assignment wins. Typical resolution > functions will look at the signal values, I would like > to look at the signal attributes. > > Unfortunately, I don't seem to be able to get at the > attributes of the component signals of the record, only > the attributes of the record itself: > > package test is > type cmd_t is (idle,read,write); > type operation_t is > record > cmd : cmd_t; > busy : boolean; > end record; > type op_vector is array (integer range <>) of operation_t; > function op_resolve(ov : in op_vector) return operation_t; > subtype op_t is op_resolve operation_t; > end test; > > package body test is > function op_resolve(ov : in op_vector) return operation_t is > variable f2p_i : integer := 0; > variable p2f_i : integer := 0; > variable result : operation_t; > begin > -- Current assignment wins > for i in ov'range loop -- OK > if ov(i).cmd'event then -- This breaks > f2p_i := i; > end if; > if ov(i).busy'event then > p2f_i := i; > end if; > end loop; > result.cmd := ov(f2p_i).cmd; > result.busy := ov(p2f_i).busy; > return result; > end function op_resolve; > end package body; > > The compiler says > > Model Technology ModelSim ALTERA vcom 6.1g Compiler 2006.08 Aug 12 2006 > -- Loading package standard > -- Compiling package test > -- Compiling package body test > -- Loading package test > ** Error: Z:/resolving.vhd(27): Attribute "event" requires a static signal > prefix. > ** Error: Z:/resolving.vhd(30): Attribute "event" requires a static signal > prefix. > ** Error: Z:/resolving.vhd(39): VHDL Compiler exiting > > Is there a way to get at the record member attributes? > > Kind regards, > > Iwo > Jim Lewis |
|
|
|
#4 |
|
Posts: n/a
|
Iwo Mergler wrote:
> Hi, > > This is an exercise in simplifying port maps in > testbench code. > > I'm trying to use a record as a bus with signals > going in opposite directions. Is this possible > in VHDL? Yes, by the use of a proper resolution function and handshake mechanism this is possible. See http://groups.google.com/group/comp....5574c4e8034cd8 It shows quite some similarities with your approach. -- Paul Uiterlinden www.aimvalley.nl e-mail addres: remove the not. Paul Uiterlinden |
|
|
|
#5 |
|
Posts: n/a
|
Iwo Mergler wrote:
> Hi, > > This is an exercise in simplifying port maps in > testbench code. <snip> Mike, Jim, Paul, thank you very much for the pointers. All three responses together solve my problem. Jim's suggestion, as implemented in Paul's example shows resolution by signal value. I now know that an undriven signal assumes a default value, the leftmost element in an enumeration. This solves my problem - I can resolve the signals this way. Mike, what you describe as remote procedures is exactly what I'm trying to do. I was under the illusion that the idea was so clever that there was no need to research other people's solutions. I feel suitably chastised. This is a bus simulator for use in a testbench. It is implemented as a package with a whole bunch of bus activity procedures and an entity which is the actual bus driver. They communicate over an inout signal which is my record. The procedures contain handshake waits with the bus driver which effectively 'block' the procedure calls for the duration of the bus sequence. The resulting testbench looks roughly like this: .... use work.mypackage.all; .... architecture tb of testbench is .... component thebusexerciser is port ( -- global clk : in std_logic; reset : in std_logic; op : inout bus_op_t; -- bus interface ... ); end component; signal op : bus_op_t; .... begin master : thebusexerciser port map ( ... op => op; ... ); ... simulation : process variable data : bus_data_t; begin wait(5); -- waits 5 clock cycles after reset. bus_write(op,0x"00000000",0x"DEADBEEF"); while bus_read(op,0x"00000008") = 0x"00000000" loop null; -- polling end loop; data := bus_read(op,0x"00000004"); if data /= 0x"12345678" then scream_in_terror; end if; ... end process; etc. The idea is to use a simple sequential process to coordinate the busmaster with other parts of the testbench. Kind regards, Iwo Iwo Mergler |
|
|
|
#6 |
|
Posts: n/a
|
Iwo Mergler wrote:
> The resulting testbench looks roughly like this: > > ... > use work.mypackage.all; > ... > architecture tb of testbench is > ... > component thebusexerciser is > port ( > -- global > clk : in std_logic; > reset : in std_logic; > op : inout bus_op_t; > > -- bus interface > ... > ); > end component; > > signal op : bus_op_t; > > ... > begin > master : thebusexerciser > port map ( > ... > op => op; > ... > ); > ... > simulation : process > variable data : bus_data_t; > begin > wait(5); -- waits 5 clock cycles after reset. > bus_write(op,0x"00000000",0x"DEADBEEF"); > while bus_read(op,0x"00000008") = 0x"00000000" loop > null; -- polling > end loop; > data := bus_read(op,0x"00000004"); > if data /= 0x"12345678" then > scream_in_terror; > end if; > ... > end process; > > etc. > > The idea is to use a simple sequential process to coordinate > the busmaster with other parts of the testbench. Yup, that's the way I use it. A problem that is see with your example is in this piece: while bus_read(op,0x"00000008") = 0x"00000000" loop null; -- polling end loop; Subprogram bus_read clearly is a function and it must have a wait statement inside (or calls another procedure with a wait statement). That is a combination that is not possible in VHDL. So bus_read should be a procedure. The result value should either be returned via an out or inout mode parameter of bus_read, or it could be retrieved from signal op with a second function, like get_data. I use the latter solution, because the first solution tends to clutter the bus_read procedure with a lot of parameters. And if you want to make them optional, you end up with a whole lot of overloaded procedures. So my solution would be: bus_read(op, 0x"00000008"); poll: while get_data(op) = 0x"00000000" loop bus_read((op, 0x"00000008"); end loop poll; bus_read(op, 0x"00000004"); if get_data(op) /= 0x"12345678" then scream_in_terror; end if; The duplicated read in the poll part can be avoided with an exit statement poll: loop bus_read((op, 0x"00000008"); exit poll when get_data(op) /= 0x"00000000"; end loop poll; Or if you don't like exit statements, with an extra boolean variable: variable poll_end: boolean; ... while not poll_end loop bus_read((op, 0x"00000008"); poll_end := get_data(op) /= 0x"00000000"; end loop; Or with a loop-until construct, which VHDL unfortunately does not have... -- Paul Uiterlinden www.aimvalley.nl e-mail addres: remove the not. Paul Uiterlinden |
|
|
|
#7 |
|
Posts: n/a
|
Iwo,
> Mike, what you describe as remote procedures is exactly > what I'm trying to do. I was under the illusion that > the idea was so clever that there was no need to research > other people's solutions. I feel suitably chastised. Been teaching this in our VHDL Testbench classes since the late 90's. At that time mainly focused on std_logic. A paper on applying this technique to both subblocks and chips (and hence not writing duplicating tests at both levels) is posted here: http://www.synthworks.com/papers/ under the title: "Accelerating Verification Through Pre-Use of System-Level Testbench Components" I did not start using integer, time, and real resolution functions until last fall. Ironically Paul U had posted something about them earlier and I had missed it and instead I had to learn it in a less direct way. So me too, I wish I had been collaborating more and sooner. My current plan is to make more of our packages publicly available in some form - time permitting. Cheers, Jim Lewis SynthWorks VHDL Training Jim Lewis |
|
|
|
#8 |
|
Posts: n/a
|
Iwo Mergler wrote:
> Mike, what you describe as remote procedures is exactly > what I'm trying to do. I was under the illusion that > the idea was so clever that there was no need to research > other people's solutions. I feel suitably chastised. The idea is from Jonathan Bromley. I just coded the simplest possible example. But I'm happy that it made sense to you. > This is a bus simulator for use in a testbench. It is > implemented as a package with a whole bunch of bus > activity procedures and an entity which is the actual > bus driver. They communicate over an inout signal which > is my record. The procedures contain handshake waits with > the bus driver which effectively 'block' the procedure > calls for the duration of the bus sequence. Do your procedures use signals or process variables to retain state information? > The resulting testbench looks roughly like this: Thanks for the outline. Looks interesting. Maybe you can make us a small example when you get it all worked out. All the verification gurus like the client-server architecture arbitrating multiple processes, so it sounds like you are on a solid track. I prefer to use a single test process where the only signals are the wires to the UUT. But I'm an over-the-top procedural guy. Good luck on your project. -- Mike Treseler Mike Treseler |
|
|
|
#9 |
|
Posts: n/a
|
Paul Uiterlinden wrote:
> Iwo Mergler wrote: > >> The resulting testbench looks roughly like this: >> >> ... >> use work.mypackage.all; >> ... >> architecture tb of testbench is >> ... >> component thebusexerciser is >> port ( >> -- global >> clk : in std_logic; >> reset : in std_logic; >> op : inout bus_op_t; >> >> -- bus interface >> ... >> ); >> end component; >> >> signal op : bus_op_t; >> >> ... >> begin >> master : thebusexerciser >> port map ( >> ... >> op => op; >> ... >> ); >> ... >> simulation : process >> variable data : bus_data_t; >> begin >> wait(5); -- waits 5 clock cycles after reset. >> bus_write(op,0x"00000000",0x"DEADBEEF"); >> while bus_read(op,0x"00000008") = 0x"00000000" loop >> null; -- polling >> end loop; >> data := bus_read(op,0x"00000004"); >> if data /= 0x"12345678" then >> scream_in_terror; >> end if; >> ... >> end process; >> >> etc. >> >> The idea is to use a simple sequential process to coordinate >> the busmaster with other parts of the testbench. > > Yup, that's the way I use it. > > A problem that is see with your example is in this piece: > > while bus_read(op,0x"00000008") = 0x"00000000" loop > null; -- polling > end loop; > > Subprogram bus_read clearly is a function and it must have a wait > statement inside (or calls another procedure with a wait statement). That > is a combination that is not possible in VHDL. So bus_read should be a > procedure. > > The result value should either be returned via an out or inout mode > parameter of bus_read, or it could be retrieved from signal op with a > second function, like get_data. > > I use the latter solution, because the first solution tends to clutter the > bus_read procedure with a lot of parameters. And if you want to make them > optional, you end up with a whole lot of overloaded procedures. > > So my solution would be: > > bus_read(op, 0x"00000008"); > poll: while get_data(op) = 0x"00000000" loop > bus_read((op, 0x"00000008"); > end loop poll; > > bus_read(op, 0x"00000004"); > if get_data(op) /= 0x"12345678" then > scream_in_terror; > end if; > Thanks for solving my next problem. I added a results array to my state record and implemented your suggestion. Kind regards, Iwo Iwo Mergler |
|
|
|
#10 |
|
Posts: n/a
|
Mike Treseler wrote:
> Iwo Mergler wrote: >> This is a bus simulator for use in a testbench. It is >> implemented as a package with a whole bunch of bus >> activity procedures and an entity which is the actual >> bus driver. They communicate over an inout signal which >> is my record. The procedures contain handshake waits with >> the bus driver which effectively 'block' the procedure >> calls for the duration of the bus sequence. > > Do your procedures use signals > or process variables to retain > state information? Signals. I admit I didn't think of using process variables. Is there an advantage in doing so? Kind regards, Iwo Iwo Mergler |
|
![]() |
| Thread Tools | Search this Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| RIP HD-DVD? - HD-DVD CES Event Canceled | Air Raid | DVD Video | 0 | 01-05-2008 03:06 AM |
| Eclipse - Axis2 - Java Webservices Error | amanjsingh | Software | 1 | 10-09-2007 09:03 AM |
| SUPER BOWL GALA EVENT, tickets available | TheLeiterSideYGB | DVD Video | 1 | 01-06-2004 11:55 PM |