[Verilog]  Using non-blocking assignments reduces LE's by half!? - Page 1
Forum section: electronics / general

author: vortexnl
author_rank: Contributor
timestamp: July 03, 2014, 04:13:57 pm
content: I just got into SystemVerilog, and I made a simple led blinker that looks like this:Code:module CPLD(input CLK, input BTN, output LED);reg [24:0] counter;always @ (posedge CLK)begincounter <= counter+1;if(BTN)LED <= counter;elseLED <= counter;endendmoduleWhen I compile this, Quartus II says it uses 25 logic elements of the CPLD.However:When I replace all non-blocking assignments with blocking assignments, like this, I use 48 LE's, but it functions exactly the same:Code:module CPLD(input CLK, input BTN, output LED);reg [24:0] counter;always @ (posedge CLK)begincounter = counter+1;if(BTN)LED = counter;elseLED = counter;endendmoduleI thought blocking and non-blocking assignments only affected simulation?Here is the generated schematic for the non-blocking version that uses 25 LE's (I use the Quartus II RTL viewer):And here is the schematic for the blocking version:As you can see, the counter gets swapped with the adder, but functionality remains the same.Please note that I am extremely new to all of this, so I hope some of you HDL guru's can enlighten me.- Nick

author: cyr
author_rank: Frequent Contributor
timestamp: July 03, 2014, 04:41:01 pm
content: They are not quite the same (as you can see from the schematic).One results in you taking the output of the adder, one takes the output of the register. The LE:s probably have internal connections from the logic array to a register, but not the other way around. So in one case the register and adder get put in the same LE, and in the other case they require one each.Edit:No, actually I was right.Basically, in one case your LED is connected to one bit of "counter" (the current value of the register), but in the other case you are connecting it to one bit of "counter+1" (the new value / the output of the adder). The only difference in the end is that your LED is updated one clock cycle earlier.

author: Sailor
author_rank: Regular Contributor
timestamp: July 03, 2014, 11:10:06 pm
content: I've never done any Verilog (or RTL) work, but what's with the +1 representation in those diagrams? h1000000, and not h0000001

author: bwat
author_rank: Frequent Contributor
timestamp: July 04, 2014, 06:31:39 am
content: Yep, it's all about timing as you've been shown. I didn't really understand the difference until I found some problems in a CPU design which had timing problems because blocking assignment was used where non-blocking was needed. Seehttp://www.arctic.umn.edu/vespa/index.htmland compare dff.v in vespa.tar and BWAT.tar.gz on that site.I can recommend the book of which this is the companion website. I like how they constructed the CPU, doing a single cycle RTL Verilog design first, then pipelining the datapath and making the Verilog more structural.

author: mrflibble
author_rank: Super Contributor
timestamp: July 04, 2014, 08:44:07 am
content: Quote from: Sailor on July 03, 2014, 11:10:06 pm25'h1000000 is a 25-bit number in hex notation, as in 0x1000000. So that's the MSB set to 1.As for the OP, as you've noticed there are definitely differences between blocking and non-blocking. See for example:http://www.asic-world.com/tidbits/blocking.html

author: Sailor
author_rank: Regular Contributor
timestamp: July 04, 2014, 11:12:00 am
content: Quote from: mrflibble on July 04, 2014, 08:44:07 amYes, but the counter is supposed to increment by 1, not 2^24Code:counter <= counter+1;

author: vortexnl
author_rank: Contributor
timestamp: July 04, 2014, 05:25:32 pm
content: So to verify:Blocking and non-blocking assignments actually change the hardware as well? I don't really understand it. Because people say you are supposed to use blocking assignments with combinational logic, but I would assume that combinational logic would have to run in parallel right? I don't see logic being sequential. I'm still reading up on all of this, so I hope to understand all of this soon.

author: bwat
author_rank: Frequent Contributor
timestamp: July 04, 2014, 05:50:51 pm
content: Quote from: vortexnl on July 04, 2014, 05:25:32 pmI don't think parallel is a good way of thinking about things. My definitions here:sequential logicandcombinational logic.A sequential logic circuit has the transparency between its inputs and outputs broken. SeeD flip-flopfor an example circuit.If you look at the two designs from the Quartus II translator you gave earlier, you'll see the hardware is different. In the first one, the input to the multiplexer is the last clock period's sum. In the second it is the current period's sum. Note both are sequential circuits.

author: pigtwo
author_rank: Regular Contributor
timestamp: July 05, 2014, 03:36:45 am
content: Quote from: Sailor on July 04, 2014, 11:12:00 amIt is incrementing my one. If you notice in the schematic it says '[24:0]' instead of '[0:24]', that pretty much means that it is reversed. So 10000...000 is 1 in that case.counter <= counter+1;

author: miguelvp
author_rank: Super Contributor
timestamp: July 05, 2014, 04:59:00 am
content: bit 0 usually is the one denominating 1 as in 2^0, so bit 24 would be 2^24.For some reason RTL values are LSB first?

author: Sailor
author_rank: Regular Contributor
timestamp: July 05, 2014, 05:40:39 am
content: @miguelvpExactly! In my ~50 years of design work, I don't recall any serious system that has written numbers like that. So where did it come from??Actually, I think there was one, but I can't remember what it was... Oh, ok. I just read a bit more on defining vectors in Verilog. It seems that you can number your element sequence left-to-right or right-to-left, so you can define a vector A[24:0] or A[0:24]. In the first case (which I would *always* consider the norm) A is the most significant bit of the vector, and in the second case A is the most significant bit. In the OP's code he has defined his register in the 'normal' manner, so the question remains: why does the RTL viewer represent a value of one in the manner that we have seen?It would be interesting to change the original code to defineCode:reg [0:24] counter;and then see what the viewer generates.@OPHere's an extract from Ciletti (Digital Design - With an Introduction to the Verilog HDL) that sums up blocking and non-blocking behaviour, and which you can see exactly in the two schematics in your original post.Quote

author: mrflibble
author_rank: Super Contributor
timestamp: July 05, 2014, 06:48:06 am
content: If that RTL view is for a +1 value then that is indeed a bit curious. You could change it tocounter <= counter + 4'b1101;and see if the bit pattern shows up in reverse in the RTL view.If so that would be a Bad Thing  IMO, because vortexnl did definecounterin the usual MSB:LSB notation.

author: Sailor
author_rank: Regular Contributor
timestamp: July 05, 2014, 07:41:46 am
content: @bwatI've just had a look at the website you recommended. The concept (design, test, compiler, etc) sounds interesting, especially if it hangs together and works as advertised.

author: bwat
author_rank: Frequent Contributor
timestamp: July 05, 2014, 07:50:32 am
content: Quote from: Sailor on July 05, 2014, 07:41:46 amYou mean the VESPA website? (I've linked to two different websites in this thread, I think you mean the VESPA one and not my own, right?)

author: cyr
author_rank: Frequent Contributor
timestamp: July 05, 2014, 08:42:16 am
content: Quote from: vortexnl on July 04, 2014, 05:25:32 pmOne thing to realize is that Quartus will evaluate the block of code you have written, figure out what the end result is, and then synthesize the netlist to realize what you have described in the available hardware. It does *not* take every line of code and translate to one specific type of hardware element.See what happens if you alter your code so that the LED is assigned first and the counter second. The blocking and non-blocking versions should then be equivalent.

author: Sailor
author_rank: Regular Contributor
timestamp: July 05, 2014, 08:51:55 am
content: @bwatYes, it was the VESPA site. But I just had a look at your site. The Everyman Kernel also sounds interesting. Have you ever put it onto a micro, say NXP or ST?

author: bwat
author_rank: Frequent Contributor
timestamp: July 05, 2014, 09:07:11 am
content: Quote from: Sailor on July 05, 2014, 08:51:55 amI think the book is good for someone who knows Verilog and just wants to see a "perfect" design method for a simple pipelined CPU. I say perfect because nobody gets it right first time but it does seem so much simpler the way they do it.Quote from: Sailor on July 05, 2014, 08:51:55 amI remember being sent on some Renesas one day course where you got a development board to take home. I put my kernel on it within an hour of walking through my front door. I ran through their wizard to create the boot sequence and just linked in my code. I think that was a 32-bit microcontroller, though it was a while ago. I usually just run boot it from a PC. In the future it will be ported to run on a homebrew CPU which will have other hard real-time friendly functions.

author: Sailor
author_rank: Regular Contributor
timestamp: July 05, 2014, 09:13:16 am
content: @cyrYes, I guess it would, because you are then forcing the (sequential) blocking code to evaluate the LED (which is dependent on the counter state) before the counter is incremented. The point in all of this being that (a) you need to know exactly what you want your hardware to do, and (b) you need to understand the consequences (and the reasons for those consequences) of using the different types of assignment.Again, it would be interesting to see the two RTL viewer diagrams after altering the sequence in the blocking version, and seeing how the LE consumption varies.I might have to install Quartus and have a play around...

author: free_electron
author_rank: Super Contributor
timestamp: July 05, 2014, 09:51:56 am
content: Since you wrote counter =counter +1 first,And later wanted to pick a bit from counter (which is now actually equal to itself +1) the synthesizer wires into the logic after the adder.Essentially the +1 MUST be executed before you pick the signal off (that is why this is called blocking)With non blocking statements they occur concurrently.You increment but you also pick off the current value. The count value only really changes an infinitesimal amount later (the delay inside the flipflop)

author: Sailor
author_rank: Regular Contributor
timestamp: July 06, 2014, 09:13:28 am
content: Hmmmm, well, strange...I installed Quartus II Web Edition 13.1 this afternoon, and ran the OPs code. I selected a Cyclone IV device. Not only does it use the same number of LEs (25) in both blocking and non-blocking form, the output of the RTL viewer is identical to the OPs EXCEPT that the +1 is correctly indicated i.e. 25'h1 (not 25'h1000000).@vortexnlWhat version are you running?

author: mrflibble
author_rank: Super Contributor
timestamp: July 06, 2014, 09:41:45 am
content: You might also want to check what options were used for synthesis. Presumably default options, but you never know if the OP has been experimenting with shiney buttons in the preferences.

author: Sailor
author_rank: Regular Contributor
timestamp: July 06, 2014, 09:45:02 am
content: Yes, and all pots, inductor cores, etc are just *meant* to be twiddled

author: mrflibble
author_rank: Super Contributor
timestamp: July 06, 2014, 10:02:06 am
content: Actually I was serious.Have had it happen often enough that some clever soul had been mucking about with the options, andit could not possibly have affected the undesired result... except that it did.

author: amyk
author_rank: Super Contributor
timestamp: July 06, 2014, 10:03:59 am
content: Quote from: Sailor on July 06, 2014, 09:13:28 amOP mentioned CPLD, not FPGA, so try something like a Max/Max II instead?Also you should be able to use the Chip Planner to look at how the LEs were used, which should show the difference more clearly compared to RTL.

author: miguelvp
author_rank: Super Contributor
timestamp: July 06, 2014, 10:07:37 am
content: Might be more device dependent than version dependent.So Cyclone IV (DE0-Nano) on Quartus II 13.1 gives me the OP's hex representation but it adds a carry bit of 0?But original Cyclone (I) on Quartus II 10.1 gives me Sailor's representation

author: Sailor
author_rank: Regular Contributor
timestamp: July 06, 2014, 11:23:27 am
content: Whoa there...I'm running Quartus II 13.1, and my device selection is a Cyclone IV. But my RTL diagram is just like the OPs (see attach), except that the +1 value is represented correctly.How did you get the carry involved?P.S. how do you get an attached image to be expanded in the post?P.P.S. the value of +1 is also incorrectly represented in your diagram - just like in the OP's

author: PA0PBZ
author_rank: Super Contributor
timestamp: July 06, 2014, 01:00:32 pm
content: Quote from: Sailor on July 06, 2014, 11:23:27 amExpand it, copy the url from properties and paste it between img tags:

author: Sailor
author_rank: Regular Contributor
timestamp: July 06, 2014, 01:52:30 pm
content: Oh, ok. By an (immediate) edit to your initial post?

author: vortexnl
author_rank: Contributor
timestamp: July 06, 2014, 03:19:44 pm
content: I'm running it on Quartus II 13.1 (x64) edition. And the FPGA development board is the Altera DE0 (not the nano!)Edit:The testing from my original post was indeed done on the Max II CPLD, so that might affect these results.

author: PA0PBZ
author_rank: Super Contributor
timestamp: July 06, 2014, 03:30:42 pm
content: Quote from: Sailor on July 06, 2014, 01:52:30 pm

author: miguelvp
author_rank: Super Contributor
timestamp: July 06, 2014, 07:46:18 pm
content: Quote from: Sailor on July 06, 2014, 11:23:27 amI just copied the code to a file named cpld.sv since the OP mentioned System Verilog and that was the RTL that it produced.My device Cyclone IV EP4CE22F17C6N, maybe Quartus II generates different code for different devices and mine happens to trigger the carry?I haven't studied much at the lower levels so I don't know how the RTL is derived in much detail.

author: Sailor
author_rank: Regular Contributor
timestamp: July 06, 2014, 11:23:11 pm
content: Ok, that's interesting. I also just copied the OP's code, but to a verilog (.v) file, not System Verilog. Apart from that, everything's pure vanilla. The SV aspect may explain the bad presentation of the +1 value (you and the OP). Maybe the carry arises from the combination of SV + Cyclone IV, but doesn't appear in SV + CPLD. Somewhere, recently, I saw a reference to looking at a lower level (gate level?) than the RTL representation. I'll have a look at the Q II manuals tonight, but maybe a guru could provide some early pointers to the method?

author: amyk
author_rank: Super Contributor
timestamp: July 07, 2014, 12:08:32 pm
content: Not gate-level, LE level:Quote from: amyk on July 06, 2014, 10:03:59 am

author: Sailor
author_rank: Regular Contributor
timestamp: July 07, 2014, 01:01:07 pm
content: Thanks for that. I must be going blind