Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
New Contributor II
243 Views

Can you force synthesis of registers?

Jump to solution
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?

0 Kudos

Accepted Solutions
Highlighted
80 Views

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


View solution in original post

21 Replies
Highlighted
Moderator
215 Views

Use the "preserve" or "keep" synthesis attributes to prevent logic from being optimized away.  See the built-in help for the appropriate syntax.

New Contributor II
203 Views

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.

0 Kudos
Highlighted
Valued Contributor II
189 Views

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.

0 Kudos
Highlighted
New Contributor II
183 Views

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?

0 Kudos
Highlighted
New Contributor II
181 Views

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.

0 Kudos
Highlighted
Valued Contributor II
175 Views

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

 

 

Highlighted
New Contributor II
170 Views

@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 ];

 

 

0 Kudos
Highlighted
New Contributor II
165 Views

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.

0 Kudos
Highlighted
Valued Contributor II
152 Views

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.

0 Kudos
Highlighted
New Contributor II
144 Views

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.

0 Kudos
Highlighted
Valued Contributor II
135 Views

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] ;

 

0 Kudos
Highlighted
Valued Contributor II
134 Views

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???????

Highlighted
Valued Contributor II
131 Views

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                                                  ;

 

 

Highlighted
81 Views

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


View solution in original post

Highlighted
78 Views

KhaiChein_Y_Intel_0-1606190123832.jpeg

tempRGB.JPG

Highlighted
New Contributor II
68 Views

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).

0 Kudos
Highlighted
Valued Contributor II
67 Views

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.

Highlighted
New Contributor II
64 Views

@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?

0 Kudos
Highlighted
New Contributor II
62 Views

It's possibly also work mentioning that tempRGB now appears in RTL Viewer even without "keep" and "preserve".

0 Kudos