Can you force synthesis of registers? - Can you force synthesis of registers? 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? Replies: Re: Can you force synthesis of registers? It is critical to understand the difference between blocking (=) and non-blocking (<=) assignments. Blocking assignments work just like, for example, programming in C with assignments. So: B = A; C = B; D = C; at the end D will have whatever value A had in it. Computations and assignments strictly follow sequentially. However, in a non-blocking sequence: B <= A; C <= B; D <= C; each right hand side gets evaluated with the current values of the variables, but no assignment is performed. Once all right hand sides are evaluated, then, at the end of the event block, all the computed right hand sides are stored in the corresponding left hand sides. So the above sequence will take 3 time states to propagate the initial value in A to the final register D. Replies: Re: Can you force synthesis of registers? 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'. Replies: Re: Can you force synthesis of registers? It's possibly also work mentioning that tempRGB now appears in RTL Viewer even without "keep" and "preserve". Replies: Re: Can you force synthesis of registers? @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? Replies: Re: Can you force synthesis of registers? 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. Replies: Re: Can you force synthesis of registers? 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). Replies: Re: Can you force synthesis of registers? Replies: Re: Can you force synthesis of registers? 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 Replies: Re: Can you force synthesis of registers? 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 ; Replies: Re: Can you force synthesis of registers? 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??????? Replies: Re: Can you force synthesis of registers? 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] ; Replies: Re: Can you force synthesis of registers? 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. Replies: Re: Can you force synthesis of registers? 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. Replies: Re: Can you force synthesis of registers? 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. Replies: Re: Can you force synthesis of registers? @ak6dn Thanks 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 ]; Replies: Re: Can you force synthesis of registers? 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 Replies: Re: Can you force synthesis of registers? 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. Replies: Re: Can you force synthesis of registers? 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? Replies: Re: Can you force synthesis of registers? 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. Replies: Re: Can you force synthesis of registers? 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. Replies: Re: Can you force synthesis of registers? Use the "preserve" or "keep" synthesis attributes to prevent logic from being optimized away. See the built-in help for the appropriate syntax. - 2020-11-17

external_document