Signal "ADDR" has a setup time constraint of 1ns with respect to the rising edge of signal "WR".
During every new clock cycle, I need to assign a value to "ADDR" and then make "WR" 0->1 after 1ns.
The clock cycle is 10ns. How do I do this in structural verilog?
There are many ways. I would use:
`timescale 1ns/1ps
...
assign #1.2 wr_out = wr; // (wr_out is a wire)
or
always #(wr)
wr_out <= #1.2 wr; // (wr_out is a reg)
The 1.2 is to have 200ps slack.
The first one is an inertial delay, which is more in line with how most real logic behaves. (If the signal change is faster then 1.2ns it is not seen. Like a signal that gets filtered out by a capacitor)
The two second one gives a 1.2ns transport delay no matter what the waveform of wr is. (Like a chain of gates delay where the pulse travels through)
I come from a world where we do NOT change the resulting gates but if you want to add delay to a gate it is very similar:
buf #(1.2,1.2) delaybuf (out,in);
You can add such a buffer with delay, alternative you have to find the last gate in the design which outputs the signal and add a delay there.
Related
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).
I have a design I am working on in Verilog. In part of my design a counter is incremented by a clock - this occurs a half clock cycle before the output of the counter is latched into a parallel load shift register.
In some circumstances I want to HOLD the counter. To do this I have gated the clock:
assign sync_gated = i_sync || !r_en;
This is combinational logic, but I don't see any issue as there is a full clock cycle (we run at 2MHz) for the output of the counter to settle. A few ns of propagation delay will not cause a problem.
The code synthesises OK, but I get this warning:
y_ctr/sync_gated_inv(y_ctr/sync_gated_inv1:O)|
NONE()(y_ctr/r_axis_address_15)| 16 |
x_ctr/sync_gated_inv(x_ctr/sync_gated_inv1:O)|
NONE()(x_ctr/r_axis_address_15)| 16 |
---------------------------------------------+---------------------------------+-------+ (*) These 2 clock signal(s) are generated by combinatorial logic, and
XST is not able to identify which are the primary clock signals.
Please use the CLOCK_SIGNAL constraint to specify the clock signal(s)
generated by combinatorial logic
Is this bad design? if so, why? or do I just need to add some constraint here to reassure the compiler?
Thank you.
You can't 'just' gate the clock. You can get all kind of clocking artifacts.
Look here for how to gate a clock.
I'm connecting a DDR model in the test bench using wires with net delay to model the trace delay on the board. The trace can hold 1 or 2 bits in its transmission line, but because the simulators models the net delay as inertial delay, all the bits get filtered out as glitches. I don't even get the clock this way. The SystemVerilog spec is not explicit on this subject. So, I'm guessing that the simulators don't want to incur the cost on performance and storage to model it as transport delay. However, I strongly believe transport delay is the right way to use for net delay, because otherwise the hassle of modeling each bidir signal with its own delay is huge. What do you think?
Here's my test case.
`timescale 1ps/1ps
module sim_top ();
parameter realtime NET_DELAY = 80ps;
parameter realtime PULSE_DELAY = 50ps;
logic driver;
initial begin
driver = 0;
forever #PULSE_DELAY driver = !driver;
end
wire #NET_DELAY a;
assign a = driver;
always #(posedge a or negedge a) begin
$display("a=%b # %t", a, $time);
end
logic b;
always #(*) begin
b <= #NET_DELAY driver;
end
always #(posedge b or negedge b) begin
$display("b=%b # %t", b, $time);
end
initial begin
#1ns;
$finish;
end
endmodule
Transport delay could be simulated by using #delays with non-blocking assighments:
always #*
out <= #delay input;
this is close to an inertial delay:
assign
#delay out = input;
The rest are mostly behavioral simulation artifacts which should be used in testbench only.
I had found this paper very informative for this issue:
http://www-inst.eecs.berkeley.edu/~cs152/fa06/handouts/CummingsHDLCON1999_BehavioralDelays_Rev1_1.pdf
So, I'm guessing that the simulators don't want to incur the cost on performance and storage to model it as transport delay.
I can imagine how you got that reasoning. From what I have learned, your assumptions is incorrect.
Real logic gates have inertial delay. This delay is caused by RC (resistance & capacitance) that is inherit to the device, from routing, or intentionally added. Verilog uses inertial delay to emulate delay behavior of real logic.
I cannot find a citation, but from discussions with engineers with pre-Verilog experience, early Verilog only modeled gates (think Verilog primitives and,or,nand,bufif0, etc.). Assign statements and always blocks were added some time later along with the possibility of synthesis. Non-blocking (<=) assignments were added much later (and copied from VHDL from what I've heard), but sill before Verilog by IEEE.
Assign statement handle delay the same way as gates. See IEEE1800-2012 ยง 10.3.3 Continuous assignment delays
A delay given to a continuous assignment shall specify the time duration between a right-hand operand value change and the assignment made to the left-hand side. If the left-hand references a scalar net, then the delay shall be treated in the same way as for gate delays; that is, different delays can be given for the output rising, falling, and changing to high impedance (see 28.16).
I'm guessing assign statements use the same type of delay as gates to reuse existing code (inside the simulator, not Verilog code) for managing delay and maintains continuity for the definition of delay. It also mapping easier, ex: assign #1 out = in; is the same as buf #1 (out,in);.
With real circuits, when you want a delay of 10 with a filter of 0.5, you need chain of 20 delay cells with small RC. If you want a delay and filter of 10 you use one delay cell with large RC. In theory synthesizers could use this delay information for target delay and filtration control (I cannot think of any synthesizer that actually does this; all synthesizers I know of ignore RTL delays).
Generally non-blocking (<=) assignments are used for synchronous logic (edge-sensitive flops and level-sensitive latches). Transport delay is the main exception but should only be used for behavioral modeling that will not be synthesized. If you know the amount of filtering your real delay path will have, I suggest coding it as follows:
reg out;
wire #(FILTER) in_filtered = in;
always #* out <= #(TOTAL_DELAY-FILTER) in_filter; // must be >=0.0
Which is cleaner and less CPU intensive then the pure inertial delay approach:
localparam LENGTH = TOTAL_DELAY/FILTER; // must be an integer >=2
wire out;
wire [LENGTH-2 : 0] delay_chain;
assign #(FILTER) {out,delay_chain} = {delay_chain,in};
Assume we have a D-flip-flop.
in RTL simulation (No t_hold and t_setup here), If its data input and clk changes at the same time, what the output should be ? The value before clk rise or the value after it ?
To make it even harder,
If a data_in and clock are connected to same wire. what should be the flop's output be ? zero all time ? or one all time ?
I tried the last case in ModelSim, and I get that the output is 1 all the time, while I expect it to be 0.
I expect that the flop in RTL-simulation should simulate the value before the clock edge.
When you use a simulation you will see results depend on how this case interpreted in the simulator what you use.
As you wrote in simulation t_setup = 0, it means that you don't need to keep signal in that level (what should be caught by flip flop) some time before rising (or falling) edge of clock signal, but can be applied exactly in the same time with the rising (or falling) edge of clock.
Because you see all time of the simulation '1' on the output of flip flop
This code is supposed to increment a counter (outputting to LEDs) when one button is pushed and decrement it when the other one is pushed. It works OK with decrementing but on incrementing it changes LEDs to random configuration instead.
module LED_COUNTER( CLK_50M, LED, Positive, Negative );
input wire CLK_50M;
input wire Positive;
input wire Negative;
output reg[7:0] LED;
always#( posedge Positive or posedge Negative )
begin
if(Positive == 1)
LED <= LED + 1;
else
LED <= LED - 1;
end
endmodule
I am using this board: http://www.ebay.com/itm/111621868286. The pin assignment is:
The connections:
After swapping pin assignments for buttons the behavior stays the same.
As others have already pointed out, you should be clocking with the CLK_50M and you should de-bounce your inputs (some FPGAs do it for you automatically, check your manual).
The reason you see partial functionality is from the way the synthesizer interprets the RTL. If the sensitivity list is edge triggered and that signal is referenced in the body of the always block, then the synthesizer will think it is an asynchronous level sensitive signal. This is intend for asynchronous reset & set (sometimes named clear & preset). ASIC design typically use flops with asynchronous reset in most the design. FPGAs tend to have a limited number of flops with asynchronous set or rest, so check your manual and use sparingly.
With your code, Negative is the clock and Positive is treated as an active high asynchronous input.
Modify the code to a functional behavioral equivalent (in simulation) seen below, then Positive will be the clock and Negative will be the active high asynchronous input.
always#( posedge Positive or posedge Negative )
begin
if(Negative == 1)
LED <= LED - 1;
else
LED <= LED + 1;
end
There are several resource for learning Verilog available online (use your favorite search engine), and I have some resources posted on my profile though more aimed at SystemVerilog.
Here is some pseudo code to point you in the correct direction for your project:
always #(posedge CLK_50M)
begin
past_Positive <= Positive;
// ...
case({/* ... , */ past_Positive,Positive})
4'b0001 : LED <= LED + 1;
4'b0100 : LED <= LED - 1;
// ...
endcase
end
First, update the design to a synchronous design where state only changes at rising edge of the CLK_50M, like
always#( posedge CLK_50M)
begin
...
end
Then add de-bounce logic logic for the two switch inputs; see contact bounce. This can be done with a small module you write yourself; that is a good exercise.
Output from the contact de-bounce logic can then be used for change detection, to make a single cycle indication each time a contact is pressed, and this indication can then be used to update the counter.
You have no debounce circuitry or logic. A mechanical switch will physically bounce a lot, so your 50MHz clock is going to see many, many transitions on the input signal, leading to erratic behavior.
I forgot to mention that you're not even using that 50MHz clock in a synchronous design. Rather you're asynchronously looking for transitions.
You need a low-pass filter somewhere. Either implemented with analog components on the input signal, or as a counter in hardware.