How does clock gating in RTL design work? - verilog

I'm trying to understand how clock gating works in RTL design.
I've an example wave here:
Description:
1st signal is gated_clock
2nd signal is clock_enable
3rd signal is ungated_clock
So there are 3 cycles in this wave (let's say cycle 0,1,2). In cycle 0, clock_enable was low and gated_clock was turned off. In cycle 1 clock_enable goes high and in next cycle (cycle 2) gated_clock turns on.
Now, during simulation I see some cases where an incoming data received at cycle 1 is properly being registered into the module that is gated by the clock (using gated_clock). It's kinda odd to me and I don't quite understand how it's possible.
The logic is like this:
always_ff #(posedge gated_clock, negedge reset) begin
if (~reset) begin
some_val <= 1'b0;
end else begin
if (in_valid==1'b1 && in_ready==1'b1) begin
some_val <= in_val;
end else begin
some_val <= 1'b0;
end
end
end
So I'm seeing that if in_valid and in_ready was high in cycle 1 then some_val will register the incoming in_val data and it'll be available in cycle 2. However in cycle 1, gated_clock was zero. So how did the in_val get sampled here? From what I understand, posedge gated_clock must be 1 if we want to flop in_val in cycle 1 .
I might be missing some core circuit level digital design concept. I'll really appreicate any help.
Updated wave:
1st signal is gated_clock
2nd signal is clock_enable
3rd signal is ungated_clock
4th signal is in_valid
5th signal is in_ready
6th signal is in_val
7th signal is some_val
So here you will see at cycle 0, gated_clock is off but in_val and in_ready is high. The input data in_val is also high. In next cycle some_val goes high. So it looks like in_val captured in cycle 0 even though gated_clock was off.

It's possible there is a glitch on the gated clock that's not showing up on the waveform. You'll need to look at the User Manual of the tool you're using to find out how to record and display glitches. It might also help to see the logic for gating the clock. Is clock_enable assigned using an NBA (<=)?

Your understand of what is clocked seemed off. in_val isn't clocked here (actually, from the snippet, I can't see where it is coming from). It is free to change at will (again, from the point of view of this snippet). At the point that gated_clock goes high then whatever the value of in_val at that time will now be captured in some_val and this will be available until such time as gated_clock goes high again (at which point we will sample a new value).

Based on the new waveform some_val is generated correctly to the posted RTL. On the very first edge of gated_clock signals in_valid and in_ready are both high, thus some_val is going high too in that cycle. On the next edge it toggles back to low because in_valid goes low (and btw in_val too)

Related

Understanding Verilog Code with two Clocks

I am pretty new to Verilog
and I use it to verify some code from a simulation program.
Right now I am struggeling if a verilog code snippet because the simulation programm uses 2 clocks ( one system clock and a pll of this ) where two hardware componentes work together, thus synchronize each other:
module something (input data)
reg vid;
always #(posegde sys_clk)
vid <= data;
always #(posegde pll_clk)
if (vid)
// do something
When reading about non blocking assignments it says the evaluation of the left-hand side is postponed until other evaluations in the current time step are completed.
Intuitive I thought this means they are evaluated at the end of the time step, thus if data changes from 0 to 1 in sys_clk tick "A", this means at the end of "A" and the beginning of next sys_clk tick this value is in vid and so only after "A" the second always block ( of pll_clk) can read vid = 1
Is this how it works or did i miss something ?
Thank you :)
In this particular case it means that
if posedge sys_clk and pll_clk happen simultaneously then vid will not have a chance to update before it gets used in the pll_clk block. So, if vid was '0' before the clock edges (and is updated to '1' in the first block), it will still be '0' in the if statement of the second block. This sequence is guaranteed by use of the non-blocking assignment in the first block
if the posedges are not happening at the same time, then the value of vid will be updated at posedge sys_clk and picked up later at the following posedge of pll_clk.
In simulation non-blocking assignment guarantees that the assignment itself happens after all the blocks are evaluated in the current clock tick. It has nothing to do with the next clock cycle. However, the latter is often used in tutorials to illustrate a particular single-clock situation, creating confusion.
Also being simultaneous is a simulation abstraction, meaning that both edges happen in the same clock tick (or within a certain small time interval in hardware).

Verilog always block with pushbutton activation, FSM

I'm writing some Verilog code to be programmed on an Altera Cyclone II FPGA board, and I have an always block which should be activated on the press of a key switch:
reg START;
...
...
always # (negedge key[3]) begin
if (START != 1) START = 1;
end
I'm writing a program for a finite state machine and this key press is supposed to indicate that the user would like to begin using the program and it should move from its initial state to the next state. Since the initialization of registers is not synthesizable, I can't assume that START begins at 0.
The problem is that once I program the board and turn it on, this always block has already run once before I press the key assigned to key[3]. I've done checks for the value of START at program execution and it is already at 1. I can't figure out why this would be happening, as the key is at its negative edge only upon key press. I've used always blocks with the same condition in previous situations and it worked fine, so I assume this has something to do with the initialization of START?
It should be noted that synthesizability of initial depends on a target you are coding for.
For example, if you code for simulator, initial works just nice. If your target is FPGA, the tool (quartus in your case) has full control over the schematics and over the initial state of every trigger inside it: actually, uploading the firmware to FPGA sets every trigger to a known state, and quartus is able to parse initials to derive each trigger's state.
In contrary, if your target is a bare silicon, every trigger is just a bunch of transistors and its state is totally indefinite upon power-on, so the only way to control it's power-on state is to apply some type of reset, like this:
always #(posedge clk, negedge rst_n)
if( !rst_n )
START <= 1'b0; // no start condition upon reset
else if( some_condition )
START <= 1'b1;
Another point on your code is that when parsing inputs from switches you should do first resynchronization to your design's clock, like this:
reg start_r, start_rr;
always #(posedge clk)
begin
start_r <= START;
start_rr <= start_r;
end
// now use start_rr instead of START
Resynchronization is a key element to avoid metastable states in your synchronous design.
The second point is that you should consider debouncing of any input from mechanic switches, unless your design is tolerant to multiple tripping of switches.
Returning to the original problem Ryan McClure asks for. It could be seen, that in the original code without initial START is undefined at startup, and can trip only to '1' state. Therefore, synthesizer just assumes START is constant, always having it '1'.
You should use an "initial" block to set the startup value of your signals. The value of START and key[3] has to be set.
initial begin
START = 1'b0;
key[3] = 1'b1;
end
You said
Since the initialization of registers is not synthesizable, I can't
assume that START begins at 0.
But this is not true! You can set a default value to any signal in your design with the method above. This value is included in the bitstream of your firmware and the signal startup with this very value.
cheers

Rising edge detection sysverilog

module syncrisedgedetect(input logic sig_a, rst,clk,output logic sig_a_risedge);
logic sig_a_d1;
always #(posedge clk or negedge rst)
begin
if(!rst)
sig_a_d1<=1'b0;
else
sig_a_d1<=sig_a;
end
assign sig_a_risedge=sig_a & !sig_a_d1;
endmodule
Hi, I came across this code in a book regarding rising edge detection for sig_a.
Can anybody explain me its working?
Thanks
This is a basic synchronous edge detection circuit.
The input, sig_a, is sampled on each rising edge of the clock, clk. The sampled value is registered; that is, sig_a_d1 is the value of sig_a delayed by one clock cycle.
The output will go to a 1 when there is a rising edge on the input. The assignment to sig_a_risedge is responsible for this. It says that "there was a rising edge on sig_a if the current value is 1 and the value on the previous clock cycle was 0".
Note that this will only work properly if the frequency of the input signal is lower than that of clock. If the input goes 0 -> 1 -> 0 all within a single clock period of the sampling clock, the edge may be missed.

always block #posedge clock

Let's take the example code below:
always #(posedge clock)
begin
if (reset == 1)
begin
something <= 0
end
end
Now let's say reset changes from 0 to 1 at the same time there's a posedge for the clock. Will something <= 0 at that point? Or will that happen the next time there's a posedge for the clock (assuming reset stays at 1)?
It depends on exactly how reset is driven.
If reset and something are both triggered off the same clock, then something will go to 0 one clock cycle after reset goes to 1. For example:
always #(posedge clock)
begin
if (somethingelse)
begin
reset <= 1;
end
end
If reset is synchronous and based on clock, The simulatore will defiantly see reset on the next clock and not the current. Physical design has clock-to-Q, therefor a rise in reset will not be observed in the same clock that caused it. You may see reset at the same time as clock in waveform. reset <= 1'b1; make the assignment happen near the end of the scheduler (after all code has executed).
To not have to worry about this when looking at a waveform, some logic designers like to put a delay on the assignment creating an artificial clock-to-Q delay (ex reset <= #1 1'b1; and something <=#1 0;). Synthesis tools will ignore the delay, but some will give warnings. That warning can be avoided by using a macro.
`ifdef SYNTHESIS
`define Q /* blank */
`else
`define Q #1
`endif
...
reset <= `Q 1'b1;
...
something <=`Q 1'b1;
...
If reset is asynchronous and being use with synchronous reset, setup time requirements need to be respected. In simulation if clock and reset rise at the same time, it is up to your verilog scheduler to decide if reset will be the new value or old value. Usually it will take the left-hand side value (old value), which means the reset will be missed on the current clock. Physical design uncertainly as well with a meta-stability risk.
The code you have written infers a flip-flop with synchronous reset. This means it is assumed that the "reset" signal is synchronised to the "clock" domain before being used in this way. If the "reset" signal is not synchronised then you should modify the code to infer a flip-flop with asynchronous reset as below:
always#(posedge clock or posedge reset)
begin
if (reset)
something <= 0
else
something <= something_else
end
Coming back to your question and assuming the code you have written is what you want, the outcome depends on how the reset is driven. If it is synchronous then the simulator will see it in the next clock edge. If it is asynchronous then the simulator can assume anything, it can vary from simulator to simulator. Please note that in simulator everything is a sequence of events and there is no such thing as happening at the same time.
In the physical world, what you have coded will result in a flip-flop with reset signal being one of the inputs to the combo driving the input of this flop. Now if the reset is synchronous, you are guaranteed that there will be no setup or hold violation at this flop. Whether the flop will 'see' the reset in this clock or the next depends on the various delays of the synthesised circuit (Usually this is the main reason that the reset is always held for few clock cycles to make sure all the flops in your design sees the reset). If reset is asynchronous then the flop will go into a metastable state. You will never want this in your design.
Hope this clarifies.
The short answer is that either of your two outcomes (immediately, or next cycle) could happen. This is a standard race condition, and simulators are free to handle this any way they want; some will give one answer, and others will give the other one.
For the long answer, look up any introductory text on how VHDL delta cycles work. Verilog doesn't specify 'delta cycles', but any Verilog simulator will work in exactly the same way, with some (irrelevant) changes in the overall scheduling algorithm. In this case, the scheduler finds that it has two events on the queue in a specific delta - reset rising, and clock rising. This is what "at the same time" means. It chooses one in an unspecified way (it might be earlier in the text source, or later, for example), works through all changes associated with that edge, and then goes back and works through all changes associated with the other edge.

How can I create a latch in Verilog

I have a CPLD with a digital input representing a reset button. When the reset button is pressed, the signal goes high. What I need to do is have a register whose value tells if the button has ever been pressed. Basically a latch. When the button goes high, a latch register goes high and stays high forever.
I thought this would be straightforward, but I got a bunch of warnings when I tried to code it up. A little Googling showed "Don't make latches in HDL! Bad practice!", but I don't really see the alternative here.
Here's my attempt. clk_10m is a fast free-running clock, pwr_off_req is the button input.
reg pwr_off_req_latched = 0;
always # (clk_10m or pwr_off_req) begin
if (pwr_off_req == 1'b1)
pwr_off_req_latched <= 1'b1;
else
pwr_off_req_latched <= pwr_off_req_latched;
// I tried this to make sure it's always set to something
end
Can you assume that the pulse length of the button press is much longer than the clock frequency of your device? If it's a physical button I think that is a very safe assumption. In that case I think this would work perfectly fine:
always #(clk_10m)
pwr_off_req_latched <= power_off_req_latched | power_off_req;
Latches are not bad in HDL they just require some consideration, implied latches from forgetting to specify else clauses in combinatorial sections are bad because you do not end up with the hardware you expect, and can create timing problems.
If you are applying a reset you might need to specify a 'pragma' so that the synthesis tool correctly identifies it.
Also latches should use = not <=, when they are enabled they are combinatorial (open) and will not break feedback loops.
This is typical way to create a latch with an asynchronous reset:
//synopsys async_set_reset "rst_an"
always #* begin
if (~rst_an) begin
// Reset
x = 1'b0;
end
else if (latch_open) begin
//next datavalue
x = y ;
end
end
In your case you might want something like :
//synopsys async_set_reset "rst_an"
always #* begin
if (~rst_an) begin
pwr_off_req_latched = 1'b0;
end
else if ( pwr_off_req ) begin
pwr_off_req_latched = 1'b1 ;
end
end
Latches can create problems for timing analysis tools. They also don't map to certain (FPGA) architectures directly, so are much harder for the place-and-route tools. Hence the warnings.
However, what you are asking for is not a latch as I understand the digital logic sense - merely a flipflop which doesn't ever get reset.
So, it can be simplified to a simple d-type flipflop with the D input tied to 1 and the clk input connected to your pwr_off_req signal:
reg pwr_off_req_latched = 0;
always # (posedge pwr_off_req) begin
pwr_off_req_latched <= 1'b1;
end
You'll have no noise rejection on that at all - any positive going edge will latch the flipflop to 1.
If I were doing this, I would run the input into a double-flip-flop synchroniser and then count a few clock pulses of the synchronised signal to make sure it's not noise before setting the latched signal. Unless you are expecting real events shorter than a few clock pulses that'd the way to do it.
Aside:
A "latch" in the digital logic world usually means either
a circuit whose output holds whichever of the two inputs was last high (a Set/Reset or SR latch)
a circuit whose output holds the input value while a control signal is inactive, but follows the input when the control signal is low - a transparent latch
This is in comparison to a flipflop, whose output holds some aspect related to the input(s) when the control signal changes (usually) from low to high, and ignores the inputs except for a tiny time window around that rising edge. These are D-type, T-type and JK-type flipflops, depending on how the output behaves relative to the input.

Resources