- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Can somebody verify ? This thing is giving me nightmares ....
module wrong ( inout cs,
output selected,
input enable,
input override,
input something );
always_comb begin
if (override) begin // if 'override'
cs = something; // drive the CS with 'something'
selected = 1'b0; // 'selected' is zero
end
else begin // if not 'override' :
cs = 1'bz; // tristate CS
selected = (cs & enable ); // incoming CS signal AND 'enable'
end
end
endmodule
This produces completely wrong RTL. The else clause does not work. It should logically and the INCOMING value on the CS pin with the 'enable' signal. Look at the RTL output. the bidirectional pin has no input path !!!! how do i fix this ? I have a very large block that switches a whole system around using tristating mechanism there are a bunch of these constructions in there. What's worse : Some work some don't... and they are cut copy and pastes of the above mechanism ...
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It gets worse in Quartus 7. 2 !
the output is even MORE wrong ! This is the circuit i want :
TRI
|
|SOMETHING>--| >------o-----<CS>
|/ | _____
| |_| |
|OVERRIDE>----+--|>0----|AND3 |---<SELECTED|
|-|_____|
|ENABLE>--------------|
if OVERRIDE is low. the SELECTED output is the logical AND of 'ENABLE' and the incoming level on CS. if OVERRIDE is HIGH , SELECTED is zero and the CS pin is controlled by 'SOMETHING'. This is what quartus 7.2 produces ...
|OVERRIDE>--------+----------
| _|_
|ENABLE> (gnd) | | \
| 0-|0 |
| | |--|SELECTED>
| 0-|1 |
| |___/
|
|
|SOMETHING>------| >----<CS>
|/
TRI
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
There's nothing wrong with the software. You're assigning cs = 1'bz (a blocking assignment), then referring to cs in an expression immediately following assignment. Effectively, you're assigning selected = (1'bz & en) in the else statement. The expression returns don't-care according to the Verilog standard. The software is free to select 0 or 1 for the don't care condition. It obviously chooses 0 in this case.
Do you mean to say:
assign selected = (override) ? 1'b0 : cs & enable;
assign cs = (override) ? something : 1'bz;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
and it gets even WORSE !
if i swap the 'Z' assigment and the next line :
This :
cs = 1'bz; // tristate CS
selected = (cs & enable ); // incoming CS signal AND 'enable'
change to:
selected = (cs & enable ); // incoming CS signal AND 'enable'
cs = 1'bz; // tristate CS
it DOES compile correctly ! This is a mayor problem. I have a complex block where,depending on a bunch of control signals i switch this tristate driver either hard to zero , hard to 1 , under control of a logic equasion
cs=1'bz; // by default we are 'z'
if (condition) begin
case (state) // except ...
case 4'b1100 : cs = something;
case 4'b0000 : cs = something_else
case 4'b1010 : cs = 1'b0;
case 4'b1101 : cs = 1'b1;
case 4'b1110 : begin
if yadayada then cs = 1'b1;
else cs = 1'bz;
end
case 4'b1001 : begin
if so_and_so then cs = this;
else cs = 1'bz;
end
default : cs = 1'bz;
end
endcase
( the real decision block is even more complex since there are a lot more sub 'case statements' that decide on the state of CS ) Why does this not work? this is normal scheduled code.... its 'z' excpet if so and so and this and that ... or does scheduling not work in this case ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
An always construct contains a sequential block of code. That is, the statements execute in a particular sequence or order. A blocking assignment updates the value of the target BEFORE any of the following statements execute. So if you reverse the order of the assignments, you don't update cs to 1'bz prior to using it in your expression. Even so, it's not a safe transformation. If the always construct re-executed for any reason, you'd get the result you don't want.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- There's nothing wrong with the software. You're assigning cs = 1'bz (a blocking assignment), then referring to cs in an expression immediately following assignment. Effectively, you're assigning selected = (1'bz & en) in the else statement. The expression returns don't-care according to the Verilog standard. The software is free to select 0 or 1 for the don't care condition. -snip- --- Quote End --- I agree that the synthesizer is free to squash a 'Z' to "don't care" if this would be an OUTPUt or an INPUT. In my case the CS signal is a tristatable (inout) signal ! Assigning a 'Z' means : tristate it. The remaining logic should still sense the real value of CS in the equasion ! There is no other way in verilog to declare ; i want you to 'tristate' this signal , then assigning it a 'Z'. See my previous post about how i control this CS pin from a complex case statement. How on earth do i write the verilog code to reproduce that correctly ? Would defining CS as a reg and using non-blocking assignments solve this ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I tried it. It works.
module wrong ( inout reg cs , output reg selected, input enable, input override , input something);
if (override) begin
cs <= something;
selected <= 1'b0;
end
else begin
selected <= (cs & enable );
cs <= 1'bz;
end
end
endmodule
here i can swap the 'z' assignemt line freely. It works correctly in both cases. This is a source of ambiguity that should not be there. The synthesizer should detect : hey, this is defined as a bidirectional signal (inout) ... If it is assigned 'z' (whether blocking or non-blocking), it means: that signal is tristated, but someone else can still be driving this signal... i should not minimize attached logic away !!!! And even if that is the way verilog works, it does not explain why the RTL generated in Quartus 7.1 is completely different from 7.2 ( for -EXACTLY- the same source code ! ) I coudln't find a mentioning of a verilog bugfix in the release notes.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I avoid blocking statements in always statements like the plague. Unless I really feel they help, and I understand what it's going to synthesize to, they tend to cause much more trouble than they are worth(there are reasons for them, but most HDL books don't sufficiently warn users of their downside). They also can simulate differently than what they synthesize to, and I worked with someone who wasted week/s trying to work around this, where if they had used non-blocking statements they would have been fine.
And of course, the same code can be synthesized in different ways. The one you show for 7.2 looks correct, just not what you wanted. I'm guessing the one for 7.1 was correct too, just different and again, not what you wanted. Anyway, once you stick with non-blocking assignments, you should be a lot happier.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
yep. i converted everything to non blocking and it works fine now.
Still if find it very distrubing that seemingly correct code synthesized completely wrong ! Again , i understand that the synthesizer is free to minimize away 'Z' lines if you assign this to a UNIDIRECTIONAL signal. but assigning a 'Z' to a BIDIRECTIONAL ( inout ) should trigger the synthesizer ; this is bidirectional , all i need to do is tristate the driver. the 'sensing' logic should not be impacted by this. This is an ambiguity in the language. There should be a specific statement for 'make the line 'high impedant' but don;t touch the sensing logic attached to it. The FPGA interfaces to a bunch of external logic that all uses bidirectional data and control buses. That's where i ran into trouble. The really frustrating part is that i originally intende to draw this in a schematic ! there is NO possibility ambiguity there. time for Verilog2008 ?- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I don't disagree that it's unintuitive and I really don't like it, but it's defined by the verilog language, and I believe every synthesizer would give you similar results. So the code was not correct for what you intended. There is definitely an ambiguity to HDLs. This has some great pros(like being able to write high-level transactions, state-machines without encoding them, portability across different targets, parameterizable code, etc.) but that also has issues. You're doing the right thing though, writing some code and looking at what comes out. It'll quickly become second nature where you know approximately how the HDL you write will get synthesized, and it'll be as easy, if not easier, than doing schematics.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This is an excellent paper on blocking and non blocking assignments.
http://csg.csail.mit.edu/6.375/papers/cummings-nonblocking-snug99.pdf (http://http://csg.csail.mit.edu/6.375/papers/cummings-nonblocking-snug99.pdf)- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page