Wow! No TestbenchWow!

Started by rickman January 27, 2011
This is the first project I've done in Verilog in many years.  With a
long history in VHDL I have a new perspective and am seeing Verilog in
a different way.  I am finding some of the differences to be pretty
interesting actually.

I've already commented on the lack of the wildcard sensitivity only to
find that VHDL has recently added this.  Now I am learning how Verilog
allows hierarchical path references to signals for test benches.  This
is awesome!!!  I would love to have had this in Verilog.  It is such a
PITA to have to bring every generic or debug signal to the top of a
design just to support a test bench.

... or did I miss something again?

Rick
rickman wrote:
> This is the first project I've done in Verilog in many years. With a > long history in VHDL I have a new perspective and am seeing Verilog in > a different way. I am finding some of the differences to be pretty > interesting actually. > > I've already commented on the lack of the wildcard sensitivity only to > find that VHDL has recently added this. Now I am learning how Verilog > allows hierarchical path references to signals for test benches. This > is awesome!!! I would love to have had this in Verilog. It is such a > PITA to have to bring every generic or debug signal to the top of a > design just to support a test bench. > > ... or did I miss something again?
Yep; VHDL 2008 added External Names (P1076-2008, section 8.7), which I believe are the moral equivalent of Verilog hierarchical references. Google's first hit on them: http://www.doulos.com/knowhow/vhdl_designers_guide/vhdl_2008/vhdl_200x_ease/#hierarchicalnames -- Tim McBrayer MathWorks
"rickman"  wrote in message 
news:f8d79600-a7d4-4c5b-b5d3-655122ad1124@k14g2000pre.googlegroups.com...
..
I've already commented on the lack of the wildcard sensitivity only to
find that VHDL has recently added this.  Now I am learning how Verilog
allows hierarchical path references to signals for test benches.  This
is awesome!!!  I would love to have had this in Verilog.  It is such a
PITA to have to bring every generic or debug signal to the top of a
design just to support a test bench.

... or did I miss something again?

Yes, VHDL2008 supports hierarchical references (works fine in Modelsim 
10.0), before that you had SignalSpy and many other custom solutions to this 
issue.

<<signal .test2008_tb.u1.muxout : std_logic_vector(2 downto 0) >>  <= force 
"011";   -- inject error

Hans.
www.ht-lab.com

rickman wrote:

> This is the first project I've done in Verilog in many years. With a > long history in VHDL I have a new perspective and am seeing Verilog in > a different way. I am finding some of the differences to be pretty > interesting actually. > > I've already commented on the lack of the wildcard sensitivity only to > find that VHDL has recently added this. Now I am learning how Verilog > allows hierarchical path references to signals for test benches. This > is awesome!!! I would love to have had this in Verilog. It is such a > PITA to have to bring every generic or debug signal to the top of a > design just to support a test bench. > > ... or did I miss something again?
Yes! ;-) Well, maybe.... For bringing up debug signals to the testbench you can use "global" signals declared in a package. It is not synthesizable (but for debug signals that would not be a problem). Also, the assignment to the global signal has to take place at the location were the object to be observed is visible. Example: PACKAGE pkg IS SIGNAL spy: std_logic_vector(7 DOWNTO 0); END PACKAGE pkg; In the architecture where you want to observe a signal: USE work.pkg.ALL; ARCHITECTURE arch OF design_block IS BEGIN ... spy <= observed_signal; ... END ARCHITECTURE arch; In your testbench: USE work.pkg.ALL; ARCHITECTURE arch OF tb IS BEGIN ... -- spy is visible here, due to the USE statement IF spy = ... -- whatever ... END ARCHITECTURE arch; Another way to do all this is using the new VHDL-2008 feature called "external names". Then you can peek into the DUV every which way you want, without the need of changing DUV code. Example (from the Ashenden/Lewis book: VHDL-2008 just the new stuff): ASSERT <<SIGNAL .tb.duv.controller.state: std_logic_vector(0 TO 4)>> /= "00000" REPORT "Illegal controller state"; VHDL-2008 also includes FORCE and RELEASE assignments. This means that you don't need simulator dependant commands anymore for forcing signals in the DUT. I have no idea if there already is a simulator that supports these constructs. -- Paul Uiterlinden www.aimvalley.nl e-mail addres: remove the not.
On Jan 27, 2:22=A0pm, rickman <gnu...@gmail.com> wrote:
> This is the first project I've done in Verilog in many years. =A0With a > long history in VHDL I have a new perspective and am seeing Verilog in > a different way. =A0I am finding some of the differences to be pretty > interesting actually. > > I've already commented on the lack of the wildcard sensitivity only to > find that VHDL has recently added this. =A0Now I am learning how Verilog > allows hierarchical path references to signals for test benches. =A0This > is awesome!!! =A0I would love to have had this in Verilog. =A0It is such =
a
> PITA to have to bring every generic or debug signal to the top of a > design just to support a test bench. > > ... or did I miss something again? > > Rick
I've always thought that it would be nice if FPGA synthesis tools supported the hierarchical path names too. i.e. if you wanted to debug a core with chipscope, you could do assign trig0[0] =3D my_core.some_internal_block.troublesome_node;
rickman wrote:
> This is the first project I've done in Verilog in many years. With a > long history in VHDL I have a new perspective and am seeing Verilog in > a different way. I am finding some of the differences to be pretty > interesting actually. > > I've already commented on the lack of the wildcard sensitivity only to > find that VHDL has recently added this. Now I am learning how Verilog > allows hierarchical path references to signals for test benches. This > is awesome!!! I would love to have had this in Verilog. It is such a > PITA to have to bring every generic or debug signal to the top of a > design just to support a test bench.
If you're using ModelSim, there's a library "modelsim_lib" that has a function called "SignalSpy". With that you can access any signal in your design from a test bench. Use it like this: library modelsim_lib; use modelsim_lib.util.all; -- entity, architecture, signal declarations skipped ----------------------------------------------------------------------------- -- spy process ----------------------------------------------------------------------------- sig_spy : process is begin init_signal_spy("/DUT/submodule1/submodule2/interesting_signal", "tb_sig", 1); wait; end process sig_spy; This connects "interesting_signal" to your test bench signal "tb_sig". This is not synthesizable and you have to consider ModelSim's built in optimization, which might optimize away the signal you want to look at during elaboration, but it's a start and works with older VHDL releases. Doesn't work for GENERICs, though... HTH, Sean
> I've always thought that it would be nice if FPGA synthesis tools > supported the hierarchical path names too. > i.e. if you wanted to debug a core with chipscope, you could do > > assign trig0[0] = my_core.some_internal_block.troublesome_node;
VHDL: I've successfully used signals in packages (global signals) in synthesis (synplify). Declare a signal in a package (I used std_ulogic to try to catch multiple drivers at compile time, but the error(s) came at elaboration...). So at the top entity you "use debug_pkg" and get access to the debug_signal. Just drive it to your output, i.e. debug_pin <= debug_signal; In the lower level entity, also "use debug_pkg" and send your troublesome_node to the debug_signal: debug_signal <= troublesome_node; HTH -- Pont
On Thu, 27 Jan 2011 06:22:19 -0800 (PST), rickman wrote:

> Now I am learning how Verilog >allows hierarchical path references to signals for test benches. This >is awesome!!!
Not as awesome as the ability to call tasks (procedures) in a module, from another module. That's just the neatest thing ever, for stimulus generation. This little example should give you a flavour of what you can do: `timescale 1ns/1ns module simulatedUartTransmitter(output reg TxD); time bitTime; // task setBitTime(input time newBitTime); bitTime = newBitTime; endtask task sendChar(input [7:0] char); begin // send start bit TxD = 0; // send eight data bits, LSB first repeat (8) begin #(bitTime) TxD = char[0]; char = char >> 1; end // send stop bit #(bitTime) TxD = 1; #(bitTime); end endtask // initial TxD = 1; // line idles in "Mark" state // endmodule module justTryThisOne; // connections wire serial_TxD; // stimulus generator instance simulatedUartTransmitter txGenerator(.TxD(serial_TxD)); // // There's no DUT in this example, but you can still // see the signal generator at work. // // code to generate some stimulus initial begin txGenerator.setBitTime(104000); // 9600Bd, roughly #1_000_000; // idle awhile before starting txGenerator.sendChar("h"); // ask the sig-gen... txGenerator.sendChar("i"); // ...to send some data txGenerator.sendChar("!"); // ...at our request #1_000_000; // idle awhile at the end end endmodule Utterly fantastic when you want to do stuff like mimicking the behaviour of a CPU in your testbench. Just write a module that can generate read or write cycles on a bus, then connect an instance of it to your DUT and get it to do accesses in the same way you'd expect your CPU to behave. Apologies if this is stuff you've seen already. It's so useful that I couldn't resist sharing the example (again). -- Jonathan Bromley
Jonathan Bromley wrote:

> On Thu, 27 Jan 2011 06:22:19 -0800 (PST), rickman wrote: > >> Now I am learning how Verilog >>allows hierarchical path references to signals for test benches. This >>is awesome!!! > > Not as awesome as the ability to call tasks > (procedures) in a module, from another module. > That's just the neatest thing ever, for > stimulus generation. This little example > should give you a flavour of what you can do: > > `timescale 1ns/1ns > > module simulatedUartTransmitter(output reg TxD); > time bitTime; > // > task setBitTime(input time newBitTime); > bitTime = newBitTime; > endtask > > task sendChar(input [7:0] char); > begin > // send start bit > TxD = 0; > // send eight data bits, LSB first > repeat (8) begin > #(bitTime) TxD = char[0]; > char = char >> 1; > end > // send stop bit > #(bitTime) TxD = 1; > #(bitTime); > end > endtask > // > initial TxD = 1; // line idles in "Mark" state > // > endmodule > > module justTryThisOne; > // connections > wire serial_TxD; > // stimulus generator instance > simulatedUartTransmitter txGenerator(.TxD(serial_TxD)); > // > // There's no DUT in this example, but you can still > // see the signal generator at work. > // > // code to generate some stimulus > initial begin > txGenerator.setBitTime(104000); // 9600Bd, roughly > #1_000_000; // idle awhile before starting > txGenerator.sendChar("h"); // ask the sig-gen... > txGenerator.sendChar("i"); // ...to send some data > txGenerator.sendChar("!"); // ...at our request > #1_000_000; // idle awhile at the end > end > endmodule > > Utterly fantastic when you want to do stuff like > mimicking the behaviour of a CPU in your testbench. > Just write a module that can generate read or write > cycles on a bus, then connect an instance of it to > your DUT and get it to do accesses in the same way > you'd expect your CPU to behave. > > Apologies if this is stuff you've seen already. > It's so useful that I couldn't resist sharing > the example (again).
Thanks for sharing. I've kept this for reference, as I don't use Verilog normally but want to keep up to date as much as possible. It is fantastically more simple than the hoops and loops you must go through when implementing this in VHDL. Been there, done that (or rather: doing that). And I am saying this as a VHDL aficionado. One question though: if the task sendChar is called concurrently from different procedural blocks in a way that the calls are overlapping, I think the result would be a great mess (I am saying this as a not so great lover of how Verilog works). Is there a simple way to deal with collisions like that? Or will the simplicity be lost then for the most part? -- Paul Uiterlinden www.aimvalley.nl e-mail addres: remove the not.
Sorry I came in late for this one.

>`timescale 1ns/1ns > >module simulatedUartTransmitter(output reg TxD); > time bitTime; > // > task setBitTime(input time newBitTime); > bitTime = newBitTime; > endtask > > task sendChar(input [7:0] char); > begin > // send start bit > TxD = 0; > // send eight data bits, LSB first > repeat (8) begin > #(bitTime) TxD = char[0]; > char = char >> 1; > end > // send stop bit > #(bitTime) TxD = 1; > #(bitTime); > end > endtask > // > initial TxD = 1; // line idles in "Mark" state > // >endmodule > >module justTryThisOne; > // connections > wire serial_TxD; > // stimulus generator instance > simulatedUartTransmitter txGenerator(.TxD(serial_TxD)); > // > // There's no DUT in this example, but you can still > // see the signal generator at work. > // > // code to generate some stimulus > initial begin > txGenerator.setBitTime(104000); // 9600Bd, roughly > #1_000_000; // idle awhile before starting > txGenerator.sendChar("h"); // ask the sig-gen... > txGenerator.sendChar("i"); // ...to send some data > txGenerator.sendChar("!"); // ...at our request > #1_000_000; // idle awhile at the end > end >endmodule
I'm still quite new to VHDL external names. But I thought this is already possible with VHDL-2008? The simulatedUartTransmitter just looks like a package to me, with a few procedures: library ieee; use ieee.std_logic_1164.all; package uartPkg is type simulatedUartTransmitter is protected procedure setBitTime(newBitTime:in time); procedure sendChar(char:in character); end protected simulatedUartTransmitter; signal TxD:std_ulogic; shared variable uartTx: simulatedUartTransmitter; end package uartPkg; package body uartPkg is type simulatedUartTransmitter is protected body variable bitTime:time; procedure setBitTime(newBitTime:in time) is begin bitTime:=newBitTime; end procedure setBitTime; procedure sendChar(char:in character) is begin /* use wait statements to wait on bitTime. */ ... end procedure sendChar; end protected body simulatedUartTransmitter; end package body uartPkg; /* The testbench. */ library ieee; use ieee.std_logic_1164.all; entity justTryThisOne is end entity justTryThisOne; architecture noTestbenchInst of justTryThisOne is signal serial_TxD: std_ulogic; alias txGenerator is <<variable @work.uartPkg.uartTx: @work.uartPkg.simulatedUartTransmitter>>; begin tester: process is begin txGenerator.setBitTime(104000); wait for 1 us; txGenerator.sendChar('h'); txGenerator.sendChar('i'); txGenerator.sendChar('!'); wait for 1 us; end process tester; end architecture noTestbenchInst; I haven't tried this with any simulator, but it might just work. regards, daniel --------------------------------------- Posted through http://www.FPGARelated.com