- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
bit [ 11 : 0 ] colorRGB[ 7 : 0 ];
bit [ 11 : 0 ] tempRGB;
..
tempRGB = colorRGB[ dataH ];
..
dataR = tempRGB[ 11 : 8 ];
When the above code is synthesized, tempRGB does not appear in the RTL Viewer. It has been optimized/removed from the synthesized design.
Is there a way to force Quartus into synthesizing registers? ie. Is there a keyword I can use so that tempRGB must appear in my design?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
You may change to below:
if( ( hcount >= hdat_begin ) && ( hcount <= hdat_last ) )
begin
if( hcount[ 0 ] == 0 )
begin
tempRGB <= colorRGB[ dataH ];
end
else
begin
tempRGB <= colorRGB[ dataL ];
end
dataR <= tempRGB[ 11 : 8 ];
dataG <= tempRGB[ 7 : 4 ];
dataB <= tempRGB[ 3 : 0 ];
end
Thanks
Best regards,
KhaiY
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Use the "preserve" or "keep" synthesis attributes to prevent logic from being optimized away. See the built-in help for the appropriate syntax.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for that.
wire keep_wire /* synthesis keep */;
reg reg1 /* synthesis preserve */;
Oh my goodness - what an awful language hack - a directive inside a comment.
Shame Verilog didn't support #pragma directives like C.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The 'comment' form is only one way to do it. There are others. See:
https://www.intel.com/content/www/us/en/programmable/quartushelp/17.0/hdl/vlog/vlog_file_dir.htm
for what Quartus accepts. The (* directive *) form to add attributes to a declaration won't be mistaken as a generic comment.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I don't get it. I must be doing something wrong. I have tried all 3 forms below:
bit [ 11 : 0 ] tempRGB /* synthesis keep */;
bit [ 11 : 0 ] tempRGB /* synthesis preserve */;
(* preserve *) bit [ 11 : 0 ] tempRGB;
tempRGB still doesn't appear in the "Signal Tap: pre-sythesis" or RTL Viewer after I recompile. It compiles
I cannot find any references to tempRGB in the System/Processing compiler output tabs either.
I am using a SystemVerilog (.sv) file as opposed to a standard Verilog (.v) file.
I definitely reference tempRGB in the code as well:
if( hcount[ 0 ] == 0 )
begin
tempRGB = colorRGB[ dataH ];
end
else
begin
tempRGB = colorRGB[ dataL ];
end
dataR = tempRGB[ 11 : 8 ];
dataG = tempRGB[ 7 : 4 ];
dataB = tempRGB[ 3 : 0 ];
What's going on here?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I've attached my project if anyone is keen to help. I have looked through the various nodes of the Compilation Report and I cannot find tempRGB anywhere.
Can someone please help me - I may not be looking for the right error/warning messages but I thought I would have found a reference to tempRGB somewhere.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well, it is because tempRGB is never instantiated as a real register. You use it as a temp variable only.
So tempRGB is a memoryless construct that basically maps to a 2:1 mux because of the '=' (blocking assignment).
If you want to map to a physical register, add another definition as tempRGB1 and insert this in the block as I indicate.
(* preserve *) bit [11:0] tempRGB1;
always (posedge iClk)
begin
if( hcount[ 0 ] == 0 )
begin
tempRGB = colorRGB[ dataH ];
end
else
begin
tempRGB = colorRGB[ dataL ];
end
tempRGB1 <= tempRGB; // <<<============= ADD THIS
dataR = tempRGB[ 11 : 8 ];
dataG = tempRGB[ 7 : 4 ];
dataB = tempRGB[ 3 : 0 ];
end
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@ak6dnThanks for the quick response. It's still not working for me though. Are you sure there isn't something else required?
I did a full recompile and it isn't appearing in the Signal Tap Node Finder or RTL Viewer. I wonder if I should be declaring tempRGB1 as 'logic' or 'reg' instead?
bit [ 11 : 0 ] tempRGB;
(* preserve *) bit [ 11 : 0 ] tempRGB1;
...
if( hcount[ 0 ] == 0 )
begin
tempRGB = colorRGB[ dataH ];
end
else
begin
tempRGB = colorRGB[ dataL ];
end
tempRGB1 <= tempRGB; // Here it is
dataR = tempRGB[ 11 : 8 ];
dataG = tempRGB[ 7 : 4 ];
dataB = tempRGB[ 3 : 0 ];
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I gave this a try as well:
bit [ 11 : 0 ] tempRGB;
(* preserve *) reg [ 11 : 0 ] tempRGB1;
assign tempRGB1 = tempRGB;
This time I got the warning 'object "tempRGB1" assigned a value but never read'. Unfortunately I didn't get the opportunity to read it either from Signal Tap since it still can't be found in the Node Finder.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well that won't work for sure, as you can only assign to a wire type, not a reg type.
I have used Verilog as the language with the (* preserve *) attribute on a reg type and it has worked.
reg vs bit in system verilog is just the difference between a 4state ZX01 vs 2state 01 data storage.
Since I have not used SystemVerilog in Quartus, it may be something to do with the language support.
IDK.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I just converted my VGAController.sv module into Verilog -removed all the SystemVerlog bits, renamed to a .v file and it still won't work.
The Verilog module is still functioning the same as the SystemVerilog version - complete with it's bug.
Guess I'll have to find another way to debug this.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well, I did a simple test in one of my designs.
I changed a source file to this:
(* preserve *) reg [7:0] spi_prescale; // spi clock prescale counter
(* preserve *) reg [7:0] spi_divisor; // spi clock prescale divide value
(* preserve *) reg spi_enable; // set to 1 to send a bit
And then the DESIGN.map.rpt file changed to this. Where some bits previously of the spi_prescale reg were removed and replaced by constants (and listed in the Registers Removed by Synthesis table), they now all exist and are 'protected' (I wish the code boxes had a horizontal scrolling option ... Intel are you listening?
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
; Registers Protected by Synthesis ;
+------------------------------------------------------------------------------+------------------------------------------------------------------+--------------------------------------------+
; Register Name ; Protected by Synthesis Attribute or Preserve Register Assignment ; Not to be Touched by Netlist Optimizations ;
+------------------------------------------------------------------------------+------------------------------------------------------------------+--------------------------------------------+
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_enable ; yes ; yes ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_prescale[0] ; yes ; yes ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_prescale[1] ; yes ; yes ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_prescale[2] ; yes ; yes ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_prescale[3] ; yes ; yes ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_prescale[4] ; yes ; yes ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_prescale[5] ; yes ; yes ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_prescale[6] ; yes ; yes ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_prescale[7] ; yes ; yes ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_divisor[0] ; yes ; yes ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_divisor[1] ; yes ; yes ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_divisor[2] ; yes ; yes ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_divisor[3] ; yes ; yes ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_divisor[4] ; yes ; yes ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_divisor[5] ; yes ; yes ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_divisor[6] ; yes ; yes ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_divisor[7] ; yes ; yes ;
+------------------------------------------------------------------------------+------------------------------------------------------------------+--------------------------------------------+
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
; Registers Removed During Synthesis ;
+-----------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+
; Register name ; Reason for Removal ;
+-----------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|dualport:mem|r_addr_b[7,8] ; Stuck at GND due to stuck port data_in ;
; mm8e_memory:mem|ext_ce_l ; Stuck at GND due to stuck port data_in ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_rdwr_block[14..31] ; Merged with rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_rdwr_block[13] ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|err[1,2,6] ; Merged with rx8e_ctlr:rx|rx0n_drive:rx0n_drive|err[0] ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sts[3,4] ; Merged with rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sts[1] ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|cmd_arg[23..29,31] ; Merged with rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|cmd_arg[22] ;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ha! My bad. The horizontal scrolling boxes show up in the final display, but not when entering/editing!!
ALSO: Can you PLEASE bring back the capability to EDIT past posts? Why was it removed???????
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
For reference, here is the .map.rpt prior to adding the (*preserve*) attribute on those registers. Note that the Registers Preserved section no longer exists, and some spi_divisor[] bits were removed.
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
; Registers Removed During Synthesis ;
+-----------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
; Register name ; Reason for Removal ;
+-----------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|dualport:mem|r_addr_b[7,8] ; Stuck at GND due to stuck port data_in ;
; mm8e_memory:mem|ext_ce_l ; Stuck at GND due to stuck port data_in ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_divisor[4] ; Merged with rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_divisor[2] ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_divisor[7] ; Merged with rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_divisor[3] ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_rdwr_block[14..31] ; Merged with rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_rdwr_block[13] ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|err[1,2,6] ; Merged with rx8e_ctlr:rx|rx0n_drive:rx0n_drive|err[0] ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sts[3,4] ; Merged with rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sts[1] ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|cmd_arg[23..29,31] ; Merged with rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|cmd_arg[22] ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_divisor[1] ; Merged with rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_divisor[0] ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_divisor[3] ; Merged with rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_divisor[2] ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_divisor[6] ; Merged with rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_divisor[5] ;
; rx8e_ctlr:rx|rx0n_drive:rx0n_drive|sd_card_ctlr:sd_card_ctlr|spi_divisor[2] ; Stuck at GND due to stuck port data_in ;
; kl8e_async:serdisk|uart:uart|rxperr ; Stuck at GND due to stuck port data_in ;
; kl8e_async:serterm|uart:uart|rxperr ; Stuck at GND due to stuck port data_in ;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
You may change to below:
if( ( hcount >= hdat_begin ) && ( hcount <= hdat_last ) )
begin
if( hcount[ 0 ] == 0 )
begin
tempRGB <= colorRGB[ dataH ];
end
else
begin
tempRGB <= colorRGB[ dataL ];
end
dataR <= tempRGB[ 11 : 8 ];
dataG <= tempRGB[ 7 : 4 ];
dataB <= tempRGB[ 3 : 0 ];
end
Thanks
Best regards,
KhaiY
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Wow. That was the culprit!
I know everyone keeps saying "use non blocking assignments" but I didn't think blocking assignments would cause me this much trouble.
I will definitely be making notes about this. As soon as I changed my code as you'd suggested @KhaiChein_Y_Intel , tempRGB appeared in the RTL Viewer.
Thanks @ak6dn for the additional info. I had a look at my .map.rpt file and tempRGB was nowhere to be found - so it was getting removed long before with no evidence that it had been removed whatsoever.
It's really difficult trying to debug what has gone wrong in the process when there is no track record. @KhaiChein_Y_Intel , if possible could we make a suggestion to the developers to log something in the report for cases such as this? If you attach my project to a ticket, I am sure they will find it easy to recreate. Any message would do such as 'Removed "tempRGB" because you keep using blocking assignments'
So I have a solution, thank you - but I still don't know why was removed (without a trace).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It was removed because it never really existed as a physical register.
In coding verilog, you can use register variables to simplify computations WITHOUT ever creating a real register.
thus:
wire W1,W2,W3,W4;
reg R1,R2,R3;
always @(posedge clk)
begin
R1 = W1+W2;
R2 = W3+W4;
R3 = R1+R2;
end
will only create a single real register R3. R1 and R2 don't really need to exist, they are transient. It is really the same as if you wrote:
wire W1,W2,W3,W4;
reg R1,R2,R3;
always @(posedge clk)
begin
R3 = (W1+W2)+(W3+W4);
end
But this will be very different:
wire W1,W2,W3,W4;
reg R1,R2,R3;
always @(posedge clk)
begin
R1 <= W1+W2;
R2 <= W3+W4;
R3 <= R1+R2;
end
because R1 and R2 will be computed in time state 'N', but R3 won't get the sum until time state 'N+1'.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That solution is NOT going to produce the exact same result however.
Changing the assignment from blocking (=) to non-blocking (<=) is going to cause a one-clock pipeline delay to occur.
tempRGB will be assigned in clock state 'N+0'
dataR/DataG/dataB will get that value in clock state 'N+1'
This may or may not be significant, depending on the desired behavior.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@ak6dn, yeah its 7pm and my brain is too flat to try it out but I hear you. I would have thought the blocking assignments would have required more clock cycles.. or do you mean that because it's "continuous" now that it may take an extra cycle to stabilise, so to speak?
I've never felt comfortable with using non-blocking assignments in conjunction with if() statements because they don't behave the same as a software if() statement (and I'm a software developer).
Still, there are 3 things here:
1) I need to be able to see values in SignalTap so I can make sense of my bugs
2) I need to understand what Quartus does to help and what it does to hinder
3) I should get my design working properly - but that can wait until the weekend
and possible 4) I really need to get my brain around how non-blocking assignments and if() statements work. Any tutorial material I find seems contradictory or poorly written for my brain to absorb. I kind of got the impression that non-blocking assignments are effectively evaluated at the end of the clock cycle.. but then that does that mean that the if() conditions use the value at the start of the clock cycle.. or are the if() statements themselves continuous in nature like any logic gate would be?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It's possibly also work mentioning that tempRGB now appears in RTL Viewer even without "keep" and "preserve".

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page