Author Topic: Verilog shift register question  (Read 1168 times)

0 Members and 1 Guest are viewing this topic.

Online moffyTopic starter

  • Super Contributor
  • ***
  • Posts: 1890
  • Country: au
Verilog shift register question
« on: April 12, 2024, 06:16:44 am »
I am quite a noob at Verilog and am starting with a simple SPI I/F that of course needs shift registers.
One thing I've noticed with the RTL schematic is that implementation 1 has a 2 input mux for every FF because the clock is ungated so when 'enable' is low the output of the FF feeds into it's input holding the last value.
1.
Code: [Select]
module shift_reg_en #(parameter WIDTH=4)(clk, en, din, dout);

input clk;
input en;
input din;

output reg[WIDTH-1:0] dout;

always @(posedge clk)
begin
  if(en)
    dout <= {dout[WIDTH-2:0], din};
end

endmodule
There is always the possibility of gating the clock signal, which is frowned upon because of introducing a local delay to the clock and possible glitches, but in this case (2) it looks to be guaranteed glich free with only a single 'and gate' delay. Are there any other issues with this gating or should I just accept the resource cost of the 1st solution?

2.
Code: [Select]
module shift_reg_enclk #(parameter WIDTH=4)(clk, en, din, dout);

input clk;
input en;
input din;

output reg[WIDTH-1:0] dout;

wire iclk;
reg  ien;

always @(negedge clk)
begin
  ien <= en;
end

and (iclk, ien, clk);

always @(posedge iclk)
begin
    dout <= {dout[WIDTH-2:0], din};
end

endmodule
 

Offline microbug

  • Frequent Contributor
  • **
  • Posts: 568
  • Country: gb
  • Electronics Enthusiast
Re: Verilog shift register question
« Reply #1 on: April 12, 2024, 10:59:53 am »
In most FPGAs, registers do have a clock enable port. I am surprised that your tool doesn't know about this.

The datasheet for your FPGA referred me to this user guide with more details. On page 14-15 it does appear that there are clock enable ports on registers. However, there is a note saying

Quote
At present, only GW1N-2, GW1N-1P5, GW1N-2B, GW1N-1P5B, GW1NR-2, GW1NR-2B devices support REG of CLS3, and CLK, CE, and SR of CLS3 and CLS2 are driven by the same source.

My understanding is that your shift register should be using the clock enable ports, since there is only one source for the CE for all registers. I wonder if there is some configuration option or additional optimisation step that might get the tool to use the clock enable ports?

If not, I wouldn't use clock gating unless you can't take the area hit from the mux implementation. You may find that the logic resources used are similar anyway, as the LUTs of the CLS blocks (groups of logic elements) may not be accessible when the block's registers are used. Unfortunately I can't find a diagram of the CLS anywhere.

Some more information in this document, section 2.1.6.
« Last Edit: April 12, 2024, 11:03:39 am by microbug »
 
The following users thanked this post: moffy

Online moffyTopic starter

  • Super Contributor
  • ***
  • Posts: 1890
  • Country: au
Re: Verilog shift register question
« Reply #2 on: April 12, 2024, 11:36:17 am »
Thanks microbug for your advice and research, I will have to look further into it, especially as I only have their freebee IDE which while simplistic is easy to use. I am thinking that if resource utilisation is acceptable to go with solution 1 unless there is a CE. The chip I have is the GW1NR-9 for reference.
 

Offline microbug

  • Frequent Contributor
  • **
  • Posts: 568
  • Country: gb
  • Electronics Enthusiast
Re: Verilog shift register question
« Reply #3 on: April 12, 2024, 12:41:06 pm »
Yes that sounds sensible. I think from the datasheet that your chip does have CE ports but the tools might not be showing them.
 

Offline xvr

  • Frequent Contributor
  • **
  • Posts: 371
  • Country: ie
    • LinkedIn
Re: Verilog shift register question
« Reply #4 on: April 12, 2024, 12:56:08 pm »
Clock gating is a very bad idea.
There are 2 ways of physical implementation of clock gating:
  • Special clock buffers with clock gating (and sometimes clock switching) capability. I don't know support Gowin them or not, but in any case this is a very scared resource, and using it to implement shift register is a worst idea
  • Using fabric logic to produce derived clock. FPGA has special clock tree, routed through whole chip. And syntheses process use it to achieve best possible frequencies. If you used derived clock synthesizer have to use much worse clock setup/delay timing that can be achieved by dedicated clock tree.
 
The following users thanked this post: moffy

Online moffyTopic starter

  • Super Contributor
  • ***
  • Posts: 1890
  • Country: au
Re: Verilog shift register question
« Reply #5 on: April 14, 2024, 03:34:50 am »
I tried the same design in Altera Quartus and there were CE pins available as microbug suggested, and I much prefer the Quartus environment and support so I think I will migrate my design efforts over to this board: https://www.amazon.com.au/Intel-Altera-Cyclone-Development-Board/dp/B0188D4ENO
which also has a high speed USB interface for communicating to the FPGA projects, not just for programming purposes.
 

Online fourfathom

  • Super Contributor
  • ***
  • Posts: 1911
  • Country: us
Re: Verilog shift register question
« Reply #6 on: April 14, 2024, 04:40:18 am »
Quote
always @(posedge clk)
begin
  if(en)
    dout <= {dout[WIDTH-2:0], din};
end

This will not use clock gating, but instead will implement multiplexers at the shift register stage inputs, controlled by the en signal.  When en is active D[n] <= Q[n-1], otherwise D[n] <= Q[n].  The "else" is implied.

In other words, this is a fully synchronous design, not clock-gated.

[edit: As was noted in the original post, which I misread!]
« Last Edit: April 14, 2024, 05:22:16 am by fourfathom »
We'll search out every place a sick, twisted, solitary misfit might run to! -- I'll start with Radio Shack.
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7852
  • Country: ca
Re: Verilog shift register question
« Reply #7 on: April 14, 2024, 04:56:29 am »
D-Flip-flopping your 2 inputs, en and din, can be used to improve input synchronous timing and FMAX.  (Not that such a small design will have trouble with FMAX)

However, do not d-latch and re-clock your shift register on a latch of your clock.  Otherwise, your d-out will be out of phase with your official system master CLK.  This lowers FMAX by destroying your system's synchronous clock.

Also, a minor logic bomb with your second code, the 'iclk' will never do anything.  It will always read a stuck value if you try to shift as data through a D-FF clocked by that same signal.
 

Online moffyTopic starter

  • Super Contributor
  • ***
  • Posts: 1890
  • Country: au
Re: Verilog shift register question
« Reply #8 on: April 14, 2024, 05:08:20 am »
Quote
always @(posedge clk)
begin
  if(en)
    dout <= {dout[WIDTH-2:0], din};
end

This will not use clock gating, but instead will implement multiplexers at the shift register stage inputs, controlled by the en signal.  When en is active D[n] <= Q[n-1], otherwise D[n] <= Q[n].  The "else" is implied.

In other words, this is a fully synchronous design, not clock-gated.
Thanks, that is correct as noted in the original post it is the second example that is clock gated.
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7852
  • Country: ca
Re: Verilog shift register question
« Reply #9 on: April 14, 2024, 05:13:55 am »
Another way to avoid the non-system sync clock.

This is how I would re-write this code assuming I had a system clock of 100MHz, knowing that my data input clock was at least less than ~33MHz, my data output will be synced with my 100MHz sys clock.  (Meaning that your SPI interface is not synchronous to master system clock...)

My added output 'dout_ready_strobe' will pulse for only 1x 100MHz master clock when the output data is ready...

Code: [Select]
module shift_reg_en #(parameter WIDTH=4)(sys_clk_100MHz, din_clk, en, din, dout, dout_ready_strobe);

input sys_clk_100MHz;
input din_clk;
input en;
input din;

output reg[WIDTH-1:0] dout;
output reg dout_ready_strobe;

reg din_clk_prev = 0;
reg en_prev = 0;

always @(posedge sys_clk_100MHz)
begin

din_clk_prev <= din_clk; // store the last state of the data input clk.
en_prev       <= en;  // store the previous state of the data input enable.

dout_ready_strobe <= ~en && en_prev ; // What I have done here is when the data input 'en' goes low, but was previously high, signifying the end of a transmitted byte, I strobe the 'dout_ready_strobe' for 1x 100Mhz clock cycle.

if (din_clk && ~din_clk_prev) begin  // If the 'din_clk' just went high while the previous state was low, we have determined that a low to high transition on the din_clk just occurred, now we can trigger the rest of the shift register code once.
    if(en)
      dout <= {dout[WIDTH-2:0], din};
  end
end

end
endmodule

Note that it is possible to mix and match part of my code, basically the detection of the data input 'en' dropping at your system clock speed with a secondary data latch, and clocking your data input using the true data input 'clk' allowing your SPI to run at frequencies beyond you master system FPGA clock, like the example 100mhz I provided.  This eats an additional byte of logic cells, but can allow for 200mhz or 400mhz SPI clock speed even if the rest of your FPGA is running at 100MHz.
« Last Edit: April 14, 2024, 05:25:07 am by BrianHG »
 

Online moffyTopic starter

  • Super Contributor
  • ***
  • Posts: 1890
  • Country: au
Re: Verilog shift register question
« Reply #10 on: April 14, 2024, 05:25:45 am »

Also, a minor logic bomb with your second code, the 'iclk' will never do anything.  It will always read a stuck value if you try to shift as data through a D-FF clocked by that same signal.
Sorry I am not sure I understand what you mean? If 'en' is low before a -ve edge of 'clk', 'ien' will go low blocking the 'clk' i.e. 'iclk' to the shift register stopping any shift, but if 'en' is high before a '-ve' edge of 'clk' then 'ien' goes high and the 'clk' i.e. 'iclk' feeds through to the shift register causing a shift on each +ve 'iclk' edge, 'iclk' changes from low to 'clk'.
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7852
  • Country: ca
Re: Verilog shift register question
« Reply #11 on: April 14, 2024, 06:00:07 am »

Also, a minor logic bomb with your second code, the 'iclk' will never do anything.  It will always read a stuck value if you try to shift as data through a D-FF clocked by that same signal.
Sorry I am not sure I understand what you mean? If 'en' is low before a -ve edge of 'clk', 'ien' will go low blocking the 'clk' i.e. 'iclk' to the shift register stopping any shift, but if 'en' is high before a '-ve' edge of 'clk' then 'ien' goes high and the 'clk' i.e. 'iclk' feeds through to the shift register causing a shift on each +ve 'iclk' edge, 'iclk' changes from low to 'clk'.

Based on what you written, here is what I saw:

reg iclk;
always @(posedge clk) begin\
iclk <= clk;
ien <= en;
idin <= din;
end

always @(posedge iclk) begin
*** all your shift register logic based on the 'i___' regs...
end

Correct?  (your and (xxx,xxxx,xxx) did not make any sense to me...)

Now if I got this correct, the problem is only with the 'iclk'.

In the first part, look at it like a 74LS74 D-FlipFlop.

You tied the 'clk' input to the 74LS74 D-FF's clock input.  No problem.
You also tied the 'iclk' to the 74LS74 D-FF's Q data output.  Ok.
However, you also tied the 74LS74's D-FF's D, data input, to the 'clk', the same as it's clock input which is also wired to the 'clk'.
How is the 'Q' data output supposed to function, or even cycle is that D-FF's clock input and it's data input are both wired together?

If I made a mistake and you line of code:
Code: [Select]
and (iclk, ien, clk);actually does something weird, I have never come across such a line before.  At no point do you even make 'iclk' equal to anything at all.

Are you defining new module IO ports?
are you trying to say

wire iclk = ien && clk;

If your goal was an 'and' gate delay, unfortunately, FPGA compilers have gotten smart and might erase such a delay by hard-wiring direct through their logic cell's product terms.

Again, what kind of SPI speed do you need and what's your system clock frequency?
When receiving the SPI, does you din and en precede, setup ready, before your clk transition?  If so, all you need is your solution #1.  If you go really high speed, then you will need to set you FPGA IO timing constraints to deal with that, but, we are then talking about an above 200MHz SPI bus.  If your SPI bus is below 50MHz, almost anything will do.
 

Online moffyTopic starter

  • Super Contributor
  • ***
  • Posts: 1890
  • Country: au
Re: Verilog shift register question
« Reply #12 on: April 14, 2024, 06:14:17 am »
Thanks BrianHG for that clarification, my code is not:

reg iclk;
always @(posedge clk) begin\
iclk <= clk;
ien <= en;
idin <= din;
end

as you posted, but:

wire iclk;
reg  ien;

always @(negedge clk)
begin
  ien <= en;
end

and (iclk, ien, clk);

If you look at the first RTL picture attached to the OP the logic is a bit more obvious.
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7852
  • Country: ca
Re: Verilog shift register question
« Reply #13 on: April 14, 2024, 06:44:18 am »
That 'and (iclk, ien, clk);' is not a valid verilog code...
I can only assume someone made a module called 'and',

Since I did not see a timing diagram of your SPI inputs, I would have to say that solution number 1 is superior, even if it looks like more logic is being used.

I don't know why you want to gate the clock.

However, it is possible to do a dumb DFF serial shift register while wiring the 'en' to the serial DFF's enable inputs instead of using the 'MUX's you see in your RTL.  I do not know how to do this in Gowin, but in Altera Quartus, you may assert directives to nets (in your case the 'en') so that the compiler knows to use the FF logic cell's 'enable' input allowing for what will look to be an asynchronous input with regard to the 'clk' input.  Then it is your choice whether to use a posedge or negedge clk for the shift registers.

If you want to do it this way, the way you would expect to see in a TTL shift register with enable input, then you would need to consult Gowin's reserved keywords to force the use of it's enable lines.

The other way is to get rid of the 'if (en) begin' in your code #1 and just add a:
wire iclk = clk && en;

And use the 'iclk' for your always posedge clk in your first code.

The question is do you want to gate the 'en'.  If so, then your code #2 is one way of doing it, however, it would be simpler using one posedge clk and doing this:

Code: [Select]
module shift_reg_en #(parameter WIDTH=4)(clk, en, din, dout);

input clk;
input en;
input din;

output reg[WIDTH-1:0] dout;
reg ien,idin;

always @(posedge clk)

ien <= en;
idin<=din;

begin
  if(ien)
    dout <= {dout[WIDTH-2:0], idin};
end

endmodule

Now, data and enable is synced sampled to 'clk'.
Remember, your 'dout' will now be delayed by 1 additional clock, however, that is trivial to deal with as you may make a data valid strobe on the fall of 'ien' to tell the rest of your code a package was received.
« Last Edit: April 14, 2024, 06:45:52 am by BrianHG »
 
The following users thanked this post: moffy

Online moffyTopic starter

  • Super Contributor
  • ***
  • Posts: 1890
  • Country: au
Re: Verilog shift register question
« Reply #14 on: April 14, 2024, 07:02:42 am »
That 'and (iclk, ien, clk);' is not a valid verilog code...
It would be better to have given it a name 'and a1(iclk, ien, clk);', but according to the book, 'Verilog HDL by Samir Palnitkar' page 63 of the pdf I have it is valid verilog syntax.
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7852
  • Country: ca
Re: Verilog shift register question
« Reply #15 on: April 14, 2024, 07:26:08 am »
My apologies, I exclusively learned to use the 'data flow modeling' version:

IE:
assign y = ~a ;   // y = not a
assign y = a & b ; // y = a and b
assign y = a | b ;  // y = a or b
assign y = a ^ b; // y = a xor b
assign y = a ^ ((b & c & ~d) | e) ; //  y = a xor ((b and c and not d) or e) 

do the last one with a pile of 'and/or (out, in1, in2) with a group of interconnecting wires.

See link:
https://circuitfever.com/logic-gates-verilog-code

then try this one with manual single gates:

assign y = (dout[7:0] == 8'b00001011) ;
or
assign y = (dout[7:0] == 8'd13) ;
 

Online moffyTopic starter

  • Super Contributor
  • ***
  • Posts: 1890
  • Country: au
Re: Verilog shift register question
« Reply #16 on: April 14, 2024, 07:40:05 am »
I'll give it a try BrianHG and no doubt learn something also. :)
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf