I've just started with VHDL, and I have a problem understanding how exactly process operates. Here is an example of a simple oscillator:
timer_1Hz: process(clk) is
variable timer : integer := 0;
constant period : integer := 50E6;
begin
--if rising_edge(clk) then
timer := (timer+1) rem period;
if (timer=0) then
led <= not led;
end if;
--end if;
end process timer_1Hz;
clk is an input (clock) signal with 50 MHz frequency, and 50% duty cycle.
Now, as I understand it, the process timer_1Hz will be triggered on any change in the clk signal, whether that be a transition from 0 to 1, or from 1 to 0.
I expected from the above example to flash LEDs with a frequency of 0.5 Hz, since the rising_edge test was commented out. In other words, I expected that the body will be triggered two times in a single clock period, on a rising and a falling edge. However, that doesn't seem to work, i.e., LEDs are never turned on.
If I include the rising_edge test, LEDs blink with a 1 Hz frequency, just as I expected.
Can someone please explain what am I missing in the unexpected case.
The code will not work without the rising edge part you removed. It might work in simulation, but not in a real fpga board. Why? Because sensitivity list is (mostly) important for simulation and not(so much) for synthesis.
For synthesis purpose, you have to always think about the hardware you would be implementing. In a practical sense, a process is NOT "run" when certain events occur.
If you really want 0.5 Hz output, just use 25E6 instead of 50E6 with the original code..
Related
I am learning verilog, trying do make the "hello world" in the VGA world (a bouncing ball) on a ice40LX1K board (olimex ice40HX1K + VGA I/O board).
I have a strange problem: when I simulate my design using iverilog + GTKWave, it seams to work good. But the implementation in hardware does not work.
What is strange is that in the hardware implemention, the ball is doesn't move .. and its position is all zero (0,0) althou the verilog code never should set it overthere.
It looks like changing the value of xpos_ball or ypos_ball does not actually change these values. (a hardware issue? a yosys issue)? In the iverilog simulation, location of the ball does change as expected.
I have no idea if this is a error in my own verilog code (as I am new in this, this is very well possible), an issue in yosys, or a problem in the hardware (speed issue, is the 100 Mhz clock to fast?) or something else?
Any proposals on how to troubleshoot this, or next steps for this kind of issue? Are there other debugging-tricks I can use?
(edit: link to the actual verilog-code removed as not relevant anymore)
Kristoff
is the 100 Mhz clock to fast?
Yes. That design is good for 39.67 MHz:
$ make vga_bounceball.rpt
icetime -d hx1k -mtr vga_bounceball.rpt vga_bounceball.asc
// Reading input .asc file..
// Reading 1k chipdb file..
// Creating timing netlist..
// Timing estimate: 25.21 ns (39.67 MHz)
Edit re comment:
You can always safely divide a clock by a power of two by using FFs as clock dividers:
input clk_100MHz;
reg clk_50MHz = 0; // initialization needed for simulation
reg clk_25MHz = 0;
always #(posedge clk_100MHz) clk_50MHz <= !clk_50MHz;
always #(posedge clk_50MHz) clk_25MHz <= !clk_25MHz;
(A non-power-of-two prescaler is not always safe without making sure with timing analysis that the prescaler itself can run in the high frequency domain.)
So I am having a hard time understanding the time it takes to get values from ram or rom in vhdl. To insert data into ram I know happens on the rising edge of the clock and takes one clock such as the example I have, but in terms of getting data out does it take one clock to get the data from memory and then get then another clock cycle to get the data to output meaning it takes 2 clock cycles to get data?
process(clk)
begin
if(rising_edge(clk)) then
if(write_en = '1') then
mem(to_integer(unsigned(address))) <= incoming_data;--insert data
end if;
end if;
end process;
out_data <= mem(to_integer(unsigned(address))); -- takes 2 clock cycles to get data ?
No, it takes 1 clock cycle:
In your code you have two concurrent processes. One is explicit:
process(clk)
begin
if(rising_edge(clk)) then
if(write_en = '1') then
mem(to_integer(unsigned(address))) <= incoming_data;--insert data
end if;
end if;
end process;
The other is implicit; it is a concurrent signal assignment:
out_data <= mem(to_integer(unsigned(address))); -- takes 2 clock cycles to get data ?
The concurrent signal assignment is exactly equivalent to this:
process(address, mem)
begin
out_data <= mem(to_integer(unsigned(address))); -- takes 2 clock cycles to get data ?
end process;
In other words, it is equivalent to a process with address and mem in the sensitivity list. Any concurrent signal assignment is equivalent to a process with all the inputs in the sensitivity list. An input to a concurrent signal assignment is any signal on the right hand side of the signal assignment operator (<=). So, you get a sensitivity list for free and that is an advantage of using concurrent signal assignments: you cannot accidentally miss out a signal from the sensitivity list, because the compiler creates it for you.
So, lets consider what happens when each process is executed. The first process has just the signal clk in its sensitivity list, so the process executes whenever there is a change (an event) on clk. If this change is not a rising edge then the rising_edge function returns FALSE and the process immediately suspends. If this change is a rising edge then the rising_edge function returns TRUE and if the expression write_en = '1' is also TRUE then this line gets executed:
mem(to_integer(unsigned(address))) <= incoming_data;--insert data
The effect of this line is to put an event on the event queue to drive the correct value of mem on the next delta cycle (assuming there is some change to the signal mem as a result). The event queue is the simulator's "to do" list; a delta cycle is one iteration of the simulator; the next iteration will occur once all the processes that are executing in the current iteration suspend.
So, the next iteration cycle occurs and the signal mem gets its new value. The signal mem is in the implicit sensitivity list of the second (implicit) process (the concurrent signal assignment). So, this second process starts executing and the line with the signal assignment to out_data is executed and (as with the executing of any line containing a signal assignment) an event is put on the event queue to drive the target signal - out_data in this case - to a new value (again assuming the value should change).
So, the change to the signal out_data always occurs one delta cycle after a change on the signal mem. We've already established that the signal mem changes one delta cycle after any rising edge on the signal clk, so we can see that the signal out_data changes two delta cycles after any rising edge on the signal clk.
Whilst it is vital to be aware of delta cycles when writing VHDL, we don't usually need to worry about them if we adopt a good, conventional style. So, we can just say that the signal out_data changes on any rising edge of the signal clk or, in other words, there is a delay of one clock cycle between any changes on the signals write_en, incoming_data or address and any corresponding change on the signal out_data.
I am working with PLCs trying to design a water tank. On one section of the design I am asked to create a clock pulse generator. I am currently trying to do this using ladder diagrams.
I believe I have the logic correct just cant seem to put it together. I want a counter to count the clock pulses that I generate, then I store these pulese in a data memory to ensure the count is retained if the system is switched off and on.
question is how do I design this clock pulse generator.
Kind regards
There are a few different ways to create a pulse generator (or commonly known in the plc world as a BLINK timer). As a matter of fact many plc programming softwares have this function block built in to their function block libraries. But if they don't or you just want to make your own you can do something like this
VAR
ton1: TON;
ton2: TON;
StartPulse: BOOL;
startPulseTrig: R_TRIG;
LatchPulseInitial: BOOL;
PulseOutput: BOOL;
Timer1Done: BOOL;
Timer2Done: BOOL;
PulseWidth:TIME:=t#500ms;
END_VAR
If you would like to count the number of pulses and store this value to a variable you can use a simple CTU (counter up) block available in all plc languages.
Review of functionality
The StartPulse variable can be anything you want that will start the counter. In my case I just used an internal bool variable that I turned on. If you want this timer to start automatically when the plc starts then just initialize this variable to true. Because StartPulse only works on the rising edge of the signal the LatchPulseInitial coil will only ever be set once.
When the LatchPulseInitial variable goes true this will start ton1 a Timer On Delay (TON) function block. This will delay the output of the block from turning on for the time of PT (in my case I have 500ms).
After 500ms has expired the ton1 outputs will turn on. this will turn on the Timer1Done variable and turn off the Timer2Done and LatchPulseInitial. Now that LatchPulseInitial has been turned off it will never interfere with the program again since it can only be turned on by the rising edge of StartPulse. Note: once the block has reached PT the outputs will stay on until the input to the block is removed.
Since Timer1Done is now on ton2 will start counting until PT is reached. Once PT is reached the outputs for that block will turn on. This will reset Timer1Done and set Timer2Done This will start ton1 again and thus starting the whole process over.
For the PulseOutput, which is the actual pulse output you are looking for, I have this being set to true when Timer2Done is true. This is because when this variable is true it is the high state of the pulse generator. When Timer1Done is true it is the low state of the pulse generator.
When the PulseOutput goes true it will trigger the input on the CTU which will increment the count of the variable in CV (current value) by 1.
If you are going to be using this logic in numerous places in your program or you plan on reusing it in the future I would make this into its own function block so you won't have to repeat this logic everytime you want to make this type of timer.
Once I had to create a BLINK FB. It is written in Structured Text. But it is suitable to use in a ladder logic program and IN/OUT Variables are named like TON style. The Blink starts with Q = TRUE. If you want to start with FALSE just invert Q and switch the Times!
FUNCTION_BLOCK BLINK
VAR_INPUT
IN : BOOL;
PT_ON : TIME;
PT_OFF : TIME;
END_VAR
VAR_OUTPUT
Q : BOOL;
ET : TIME;
END_VAR
VAR
rtIN : R_TRIG;
tonBlink : TON;
END_VAR
rtIN(CLK := IN);
IF tonBlink.Q OR rtIN.Q THEN
(*Toggle Output*)
Q := NOT Q;
(*Timer Reset call, important to call timer twice in same cycle for correct Blink Time*)
tonBlink(IN:= FALSE);
(*Set corresponding Time*)
IF Q THEN
tonBlink.PT := PT_ON;
ELSE
tonBlink.PT := PT_OFF;
END_IF
END_IF
(*Timer Run call*)
tonBlink(IN:= IN);
IF IN THEN
ET := tonBlink.ET;
ELSE
ET := T#0S;
Q := FALSE;
END_IF
In my opinion, this is the most straightforward way to do it, using 1 timer, up counter and modulo operator:
Blink function in ladder
Also note, if your PLC doesnt have modulo, then multiply by -1 each time.
I am using a clocking block in my interface for signal aliasing. I want to concatenate some of the bits together to form a bus, and then drive this bus from my driver. So, for example:
interface bus_intf (clk);
input logic clk;
logic[1:0] x_lsb;
logic[1:0] x_msb;
clocking driver_bus #(posedge clk)
default input #1step output #0;
output x_bus = {x_msb, x_lsb};
endclocking
endinterface
Now the problem with this is, in one of my assertions, I need to read bus_intf.driver_bus.x_bus. As stated in the SV manual, an output variable from a clocking block should not be read by the testbench, and if it is, then simulator spits out an error (or warning in my case).
So I modified the interface:
interface bus_intf (clk);
input logic clk;
logic[1:0] x_lsb;
logic[1:0] x_msb;
clocking driver_bus #(posedge clk)
default input #1step output #0;
inout x_bus = {x_msb, x_lsb};
endclocking
endinterface
The problem now is, in my waveform I see two signals being created - x_bus and x_bus__o. I understand why Questasim did this - it is to separate the inout declaration so I can view both versions.
However, the problem now is all my clocking drive is delayed by one clock cycle! so x_bus__o which is connected to the DUT is one clock cycle later than x_bus. This is inspite of me explicitly stating that output skew is #0.
Any idea why this happens? Am I doing something wrong or have I misunderstood?
I've put your code on EDAPlayground and tried it out. It seems to be working as expected. Here's my test harness:
module top;
bit clk;
always #1 clk = ~clk;
bus_intf busif(clk);
initial begin
#busif.driver_bus;
$display("time = ", $time);
busif.driver_bus.x_bus <= 'hf;
repeat (2)
#(negedge clk);
$display("time = ", $time);
busif.driver_bus.x_bus <= 'ha;
#100;
$finish();
end
always #(busif.x_lsb)
$display("time = ", $time, " x_lsb = ", busif.x_lsb);
always #(busif.x_msb)
$display("time = ", $time, " x_msb = ", busif.x_msb);
endmodule
The link is here if you want to try it online: http://www.edaplayground.com/x/Utf
If I drive x_bus at a posedge, then the value will be written immediately, as would be expected due to the #0 output delay. If I drive x_bus at a negedge (or at any other time aside from a posedge), then it will wait until the next posedge to drive the value. I see this behavior regardless of whether x_bus is declared as output or inout.
Check to see when you are scheduling your writes; this might be the reason you see some delays on your waves.
When you have bidirectional flow through a clocking block, the signal from the verification to the hardware and back has to go through two virtual D-FFs. So the original observation is correct. The input of 1-step is one D-FF to the design; then the return is one more D-FF back appearing 0ns (i.e., just after the clock). Clocking blocks are not useful in the situation of a signal that requires a single-cycle turn-around, and for that reason, you avoid them if that is a requirement. For most designs, it is simply not necessary. Monitors will observe the signals with a pipeline delay of one cycle, which is generally not a problem.
I have a basic counter example, counter is 6-bits wide.
reg[5:0] currcounterval_reg;
always #(posedge clk_g0)
currcounterval_reg <= currcounterval_reg+ 1'b1;
My constraints
Clock is running at 83 Mhz 912ns period) on Virtex 7 chip. The counter has no reset and the output is connected to board pins. When I run the circuit, I see switching in the signals as shown in the attached (hardware run) o/p. In the attached screenshot, if you look at the counter, after 7(seven), I should get '8'...but it first switches to '12' as bit-2 goes to zero later than the others. I have an xor gate downstream where I compare o/p of two counters. How to I avoid getting into this problem?
Whatever I do for constraining, it doesn't go away. Please help me with some strategies to remove the switching.
Please feel free to ask me if you have more questions.
You can find a my waveform here
http://i.imgur.com/btEMiFD.png?1
Thanks.
I am guessing that it is an improper constraint issue. But try wiring a synchronous counter explicitly to solve the issue.
reg[5:0] counter;
always #(posedge clk_g0)
begin
counter[0] <= ~counter[0] ;
counter[1] <= (counter[0] ) ? ~counter[1] : counter[1];
counter[2] <= (&counter[1:0] ) ? ~counter[2] : counter[2];
counter[3] <= (&counter[2:0] ) ? ~counter[3] : counter[3];
counter[4] <= (&counter[3:0] ) ? ~counter[4] : counter[4];
counter[5] <= (&counter[4:0] ) ? ~counter[5] : counter[5];
end
You need to make the XOR output synchronous. The XOR output should go to the D input of a FF that is clocked on the same rising edge that increments the counters. Bring the Q output of the FF to an FPGA pin rather than the XOR output.
You shouldn't try to match the combinational logic delays and routing delays of the two counters. The delay paths from two counters to your XOR gates will almost certainly be different so a fast XOR (like on a Virtex 7) will generate glitches. In a good synchronous design that doesn't matter, because you only care that the combinational logic outputs are valid before the next clock edge.