I have a weird question which sounds self explanatory in vhdl, but the code does not output to an oscilloscope even though the logic seems okay. I need to drive 0's and 1's for each bit in the vector below, and I need to do this with combinations of sliderswitches. I am using the Digilent Nexys 3.
My problem is that when I run this code or any code that has more than 3 outputs per if statement, one of the outputs does not output to logic '1' when given the right combination.
I gave my code below, which seems extremely simple. Can someone tell me why I can only output 3 things per if statement? I need to be able to output 20 or more signals per if statement.
I have tried everything I can think of, from using bit_vector, to using different syntax. Any help on why I can only get 3 outputs at most would be greatly appreciated.
Library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.all ;
entity pulse_gen_toVGA is port (
clk_50,sw0,sw1,sw2,sw3 : in std_logic ;
rst : in std_logic;
output : out std_logic_vector(3 downto 0));
end pulse_gen_toVGA;
architecture top of pulse_gen_toVGA is
begin
process(sw0,sw1,sw2,sw3)
begin
if (sw0='0' and sw1='0' and sw2='0' and sw3='0') then
null;
end if;
if(sw0='1') then
output<="0001";
elsif(sw1='1') then
output<="0010";
elsif(sw2='1') then
output<="0100";
elsif(sw3='1') then
output<="1000";
end if;
end process;
end top ;
Here is my ucf file of the outputs that I am using.
net "clk_50" loc="v10";
net "output<0>" loc="t12";
net "output<1>" loc="n10";
net "output<2>" loc="p11";
net "output<3>" loc="h3";
net "sw0" loc="t10";
net "sw1" loc="t9";
net "sw2" loc="v9";
net "sw3" loc="m8";
Well, your code is not exactly O.K.. Let's see:
if (sw0='0' and sw1='0' and sw2='0' and sw3='0') then
null;
end if;
This if does nothing, except waste precious bytes on your hard drive and several microseconds of cpu time everytime you synthesise or simulate. Having these lines or not changes absolutely nothing, so might as well remove them.
if(sw0='1') then
output<="0001";
elsif(sw1='1') then
output<="0010";
elsif(sw2='1') then
output<="0100";
elsif(sw3='1') then
output<="1000";
end if;
What happens if none of the switches is '1'? Implicitely, that a signal must not change its value if it is not assigned, which requires a memory element since when all switches are '0', output depends on the last switch that was active.
In that case, the synthesizer will infer a latch. Latches are known to behave erratically and should really only be used by experts. They appear every time you forget to assign a signal in one logical path of a combinational process.
You have two choices to fix your code, either you add an else to your if statement, setting output to 0 for example, or you use a proper memory element known as a register. In the first case, you will have a combinational circuit, containing only logic gates with no latch/register. In the second case, you will have the same behaviour as the latch circuit, but without the erratically of the latch. Here's how to implement a register:
process(clk_50)
begin
if rising_edge(clk_50) then
if(sw0='1') then
output<="0001";
elsif(sw1='1') then
output<="0010";
elsif(sw2='1') then
output<="0100";
elsif(sw3='1') then
output<="1000";
end if;
end if;
end process;
I have to add that the register route is not entirely fine, and encourage you to search for metastability, asynchronous input and resynchronization. Basically, using asynchronous signals (like your switches) without synchronizing it can cause problem.
Finally, it may not solve your problem, but we can look into that once you have a "clean" code.
Before you go making changes there are a couple of thing you can check.
There are not outputs labelled output in Nexys3_Master.ucf. Show us how (where) output goes that you're detecting it doesn't occur.
We can't replicate your problem with what you've provided, it isn't an Minimal, Complete, and Verifiable example.
Next, simulate your design.
Here is a simple testbench:
library ieee;
use ieee.std_logic_1164.all;
entity pgtv_tb is
end entity;
architecture foo of pgtv_tb is
signal clk_50: std_logic;
signal sw0, sw1, sw2, sw3: std_logic;
signal rst: std_logic;
signal output: std_logic_vector (3 downto 0);
begin
DUT:
entity work.pulse_gen_toVGA
port map (
clk_50 => clk_50,
sw0 => sw0,
sw1 => sw1,
sw2 => sw2,
sw3 => sw3,
rst => rst,
output => output
);
STIMULUS:
process
begin
wait for 100 ms;
sw0 <= '0';
sw1 <= '0';
sw2 <= '0';
sw3 <= '0';
wait for 100 ms;
sw0 <= '1';
wait for 100 ms;
sw0 <= '0';
wait for 100 ms;
sw1 <= '1';
wait for 100 ms;
sw1 <= '0';
wait for 100 ms;
sw2 <= '1';
wait for 100 ms;
sw2 <= '0';
wait for 100 ms;
sw3 <= '1';
wait for 100 ms;
sw3 <= '0';
wait for 100 ms;
wait;
end process;
end architecture;
And it produces:
(clickable)
Now the first thing we see is the inferred latches Jonathan Drolet was concerned with from the null statement in the first if statement.
Changing all the switch inputs to '0' didn't affect output, this happens four more times in the simulation.
But you can see we actually do get four outputs, which says
... when I run this code or any code that has more than 3 outputs per if statement, one of the outputs does not output to logic '1' when given the right combination
Isn't evident in the VHDL code. And that strongly suggests there's something wrong somewhere getting output to show up, and it's not evident in your code.
(Your code doesn't reproduce the problem for which you are asking help, regardless of whether you want those latches there or not).
Related
I have an animation shown on LEDs. When the button is pressed, the animation has to stop and then continue after the button is pressed again.
There is a method that processes working with the button:
void checkButton(){
GPIO_PinState state;
state = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_15);
if (state == GPIO_PIN_RESET) {
while(1){
state = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_15);
if (state == GPIO_PIN_SET){
break;
}
}
//while (state == GPIO_PIN_RESET) {
//state = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_15);
//}
}
}
GPIO_PIN_SET is the default button position. GPIO_PIN_RESET is the condition when the button is pressed. The commented section is what I tried instead of the while(1){...} loop. The checkButton() method is called in the main loop from time to time to be run. The program runs on STM32 with an extension module (here the type of an extension module does not matter).
The fact is that this method stops animation just for a moment and does not work as I would like it to. Could you correct anything about this program to make it work properly?
Could you correct anything about this program to make it work
properly?
My guess is that you are trying to add a 'human interaction' aspect to your design. Your current approach relies on a single (button position) sample randomly timed by a) your application and b) a human finger. This timing is simply not reliable, but the correction is possibly not too difficult.
Note 1: A 'simple' mechanical button will 'bounce' during it's activation or release (yes, either way). This means that the value which the software 'sees' (in a few microseconds) is unpredictable for several (tbd) milliseconds(?) near the button push or release.
Note 2: Another way to look at this issue, is that your state value exists two places: in the physical button AND in the variable "GPIO_PinState state;". IMHO, a state value can only reside in one location. Two locations is always a mistake.
The solution, then (if you believe) is to decide to keep one state 'record', and eliminate the other. IMHO, I think you want to keep the button, which seems to be your human input. To be clear, you want to eliminate the variable "GPIO_PinState state;"
This line:
state = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_15);
samples the switch state one time.
HOWEVER, you already know that this design can not rely on the one read being correct. After all, your user might have just pressed or released the button, and it is simply bouncing at the time of the sample.
Before we get to accumulating samples, you should be aware that the bouncing can last much more than a few microseconds. I've seen some switches bounce up to 10 milliseconds or more. If test equipment is available, I would hook it up and take a look at the characteristics of your button. If not, well, you can try the adjusting the controls of the following sample accumulator.
So, how do we 'accumulate' enough samples to feel confident we can know the state of the switch?
Consider multiple samples, spaced-in-time by short delays (2 controls?). I think you can simply accumulate them. The first count to reach tbr - 5 (or 10 or 100?) samples wins. So spin sample, delay, and increment one of two counters:
stateCount [2] = {0,0}; // state is either set or reset, init both to 0
// vvv-------max samples
for (int i=0; i<100; ++i) // worst case how long does your switch bounce
{
int sample = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_15); // capture 1 sample
stateCount[sample] += 1; // increment based on sample
// if 'enough' samples are the same, kick out early
// v ---- how long does your switch bounce
if (stateCount[sample] > 5) break; // 5 or 10 or 100 ms
// to-be-determined --------vvv --- how long does switch bounce
std::this_thread::sleep_for(1ms); // 1, 3, 5 or 11 ms between samples
// C++ provides, but use what is available for your system
// and balanced with the needs of your app
}
FYI - The above scheme has 3 adjustments to handle different switch-bounce durations ... You have some experimenting to do. I would start with max samples at 20. I have no recommendation for sleep_for ... you provided no other info about your system.
Good luck.
It has been a long time, but I think I remember the push-buttons on a telecom infrastructure equipment bounced 5 to 15 ms.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.all;
entity reset40 is
Port ( CLOCK : in STD_LOGIC; --50MHz
CIKIS : out STD_LOGIC
);
end reset40;
architecture Behavioral of reset40 is
signal A:std_logic;
begin
process(CLOCK) --line20
variable fcounter: unsigned(24 downto 0);
variable counter_A:integer range 0 to 40:=0;
begin
if rising_edge (CLOCK) then
fcounter := fcounter+1;
end if;
A<=fcounter(6); --fa=fclock/2^6
if ((rising_edge (A)) and (counter_A/=40)) then
counter_A:= counter_A+1;
CIKIS<=A;
else
CIKIS<='0';
end if;
end process;
end Behavioral;
ERROR:Xst:827 - "C:/Users/reset40/reset40.vhd" line 20: Signal CIKIS
cannot be synthesized, bad synchronous description. The description
style you are using to describe a synchronous element (register,
memory, etc.) is not supported in the current software release.
What is the error about clock? How come is it a 'bad synchronous description'?
Your basic mistake is that all the code that is in the process needs to run only on the rising edge of the clock. This is because the target chip only has flipflops which can respond on one edge.
The process you have written is sensitive to changes in clock due to this line:
process(clock)
so it is sensitive to both clock edges.
You have then put part of the code inside an
if rising_edge(clock) then
which limits activity to just the rising edge, which is good. The rest of your code is unfortunately outside of that if clause, and so is described as operating on every edge of the clock, either rising or falling. In simulation this will be fine, but the synthesiser cannot find any flipflops which can do that, hence the error.
Other things to note - you need to reset or initialise your counter somehow. Either with a reset signal, so that any time the reset signal is high, the counter is set back to all zeros. Or using an initialisation statement.
You can get away without them for pure synthesis, as the sythesiser will (in the absence of init or reset code) automatically set the counter to all zeros when the FPGA starts up. It's poor-form though as:
it won't work in simulation and simulation is vital. You may not have realised this yet, but you will eventually!
if you port the code to another architecture which cannot magically initialise things, you wil get random 1s and 0s in the counter at startup. This may or may not matter, but it's best to avoid having to decide.
Besides the bad synchronous description there is also bad coding style :)
First off all you should not use variables in a process if you want to describe a counter. So use a signal declared in the architecture region.
2.
Decide what signal type you want to use for counters: unsigned or integer. I would advice unsigned.
3.
Signal A is not in the sensitivity list. But adding A to the sensitivity list of your process is no solution, because having two different clocks (clock and A) in one process is (a) not supported by every synthesis tool and (b) bad coding style => so use a second process for the second counter which is using a second clock.
4.
You are using A in a 'if rising_edge(...) then' statement. Synthesis tools would infer a (new) clock signal for the signal given in brackets. So your description would lead to an asynchronous description which is also bad style. A good style would be to derive a clock enable signal from fcounter(x) which enables a second counter (counter_A). counter_A is also clocked with your main clock 'clock'
5.
fcounter has no init value despite it's a register.
6.
Why has fcounter 25 bits? you are using only 7 bits.
Besides that, using bit 6 in fcounter(6) will result in a by 128 (2^7) divided clock.
Using fcounter(0) represents a toggle flip flop, which outputs f/2. fcounter(1) -> f74 and so on...
So, how should it look like?
architecture [...]
[...]
signal fcounter : unsigned(6 downto 0) := (others => '0');
signal counter_a : unsigned(5 downto 0) := (others => '0');
begin
process(clock)
bein
if rising_edge(clock) then
-- I'm using one more bits for the counter overflow, which resets the fcounter
if (fcounter(6) = '1') then
fcounter <= (others => '0');
else
fcounter <= fcounter + 1;
end if;
-- enable counter_A every 64 cycles
if (fcounter(6) = '1') then
counter_A <= counter_A + 1;
[...]
end if;
end if;
end process;
end;
But in the end there is another question: What should this module do? Do you want to create a new /64 clock or do you want to create some kind of a reset? There are other ways to generate these kinds of signals.
Reply to Mehmet's comment:
Normally a pulse train is generated by a shift register of n bits, which is reseted to all ones and the input is assigned with '0'. For short pulse trains it's a good solution, but in your case a counter is more resource efficient :)
Example for short pulse (constant) trains
input <= '0';
--input <= any_signal;
process(clock)
begin
if rising_edge(clock) then
if (reset = '1') then
pulse_train <= (others => '1');
else
pulse_train <= pulse_train(pulse_train'high - 1 downto 0) & input;
end if;
end if;
end process;
output <= pulse_train(pulse_train'high);
Ok, in the case of supplying an external low frequency IC with a derived clock, it's ok to use a counter. If the counter can't supply the recommended frequency and duty cycle, you can use a counter to produce f_out*2 and feed this signal through a toggle flip flop. The T-FF restores the duty cycle to 50/50 and divides the clock by two to f_out.
Well i have process a in my main component and process b in my other sub component(inmplemented in the main one).
both process a and b have only the clock in their sensitivity list:
process a control eneable signal called ready which if 1 process b can work , 0 process b will do nothing.
Problem is in process a , when process a changes value of enable signal to 0 , it has to take to the next clock cycle to change so process b ends up and run an extra clock cycle.
a:process(clk)
begin
if(rising_edge(clk)) then
if(output/=old_output) then
enable<='0';
end if;
end if;
end process;
b:process(clk)
begin
if(rising_edge(clk)) then
if(enable='1') then
--do anything
end if;
end if;
end process;
The reason is that the value is latched/sampled at the exact rising_edge of the clock. At that time, 'enable' is still equal to one. In that simulation delta, enabled will get the value zero, but it won't be available until AFTER the first delta.
This is also true for when enable BECOMES one (given that it is also generated on a rising clock edge), the process will latch the value exactly when clock rises, and in the simulator, enabled will look high for a whole clock period, even though "--do anything" will not happen.
You can think of this as real electrical circuits instead of a programming language. Consider that the evaluation of "output/=old_output" will consume time, and that you as a designer want that to be DONE before the next rising clock edge.
Hope this helps, but this is how the language works. I could give you a better answer if both the setting and resetting of the enable.
I hope someone could help me with this (And english is not my native language so I'm sorry in advance for any grammar or spelling mistakes):
As part of a project I'm coding, I need to time some commands. More specifically: I have 2 sets of commands (Lets call them set A and set B) - I need to to execute set A, then wait for a specific number of milliseconds (calculated in set A), then execute set B. I did it using the Sleep(time) command between the sets.
Now, I need to incorporate another set of commands (Set C) that will run in a loop in the time between the sets A and B instead of simply doing nothing. Meaning, instead of the time the program was idle before (waiting the specified number of milliseconds) I need it to loop the C set - but the catch is that it has to loop C exactly the same time it would have waited in the idle time.
How can I do this without using threads? (And generally keep it as simple as possible)
I guess the "work-time" for the set of commands in C is known. And C is a loop which can/shall finish when the wait time has expired.
In this case I'd suggest to use a performance counter to count down the wait time. Depending on what is calculated and what overhaed is introduced in C the accuracy to obtain can be in the microseconds range.
Pseudo code:
Delay = 1000
Do A
CounterBegin = GetCounter()
// and now the C loop
while ((GetCounter() - CounterBegin) < Delay) {
Do C
}
Do B
Note: The counter values are to be converted into times by using the counter frequency. See the link above to get the details.
if you had a process like this for example:
process (clk)
if (var = '1') then
var2 = '1';
end if;
if (var2 = '1') then
//do something
end if;
end process;
Would the 2nd if statement get executed on the next clock cycle, or would it get executed as soon as var2 = '1' is executed?
Would the below code do exactly the same thing as the code above?
process (clk)
if (var = '1') then
var2 = '1';
end if;
end process;
process (var2)
if (var2 = '1') then
//do something
end if;
end process;
If someone could explain the timing issues that would be great.
If your vars are variables, then you can't sensibly do the second option as you can't use variables across processes (in most circumstances, see later). If they are actually signals, then yes you can.
In the first code - if they are variables, then yes, they will update immediately and the second part of the code will run.
If they are signals then the second if block will only run next time around, as signals are only updated at the end of the process that writes to them.
The second example code will run the second process in the next "delta cycle" after the first one runs, as it is sensitive to the change on var2.
You can use variables between processes, but they have to be specified as shared variables. If you do that with "straight" shaed variables, you run the risk of hideous Verilog-like race conditions as the order of reading and updates is undefined.
You should make them of a protected type which is a bit OO-like and has methods to operate on the values which allows accesses to be atomic across multiple processes.
In your first piece of code - As var2 is a variable it will get the new value immediately. Therefore the if statement will see the new value, and //do something would happen in the same time slice.
(// comments? Really? This is VHDL. We used --)
Your second piece of code wont work. Variables are scoped to a process, and can't be used to transfer values between processes. You have to use signals, and so the rules change. Consider this code:
signal sig : std_logic := 1;
signal sig2 : std_logic := 0;
process (clk)
if (sig = '1') then
sig2 <= '1';
end if;
if (sig2 = '1') then
-- do something
end if;
end process;
process (sig2)
if (sig2 = '1') then
-- do something else
end if;
end process;
Initial conditions: sig is 1 and sig2 is 0, so we're just waiting for a clk edge.
When the clock edge arrives we enter the first process we see that sig is 1 and assign 1 to sig2. All simple so far, but because sig2 is a signal the assignment wont happen until the process completes. Than means than when we compare sig2 to 1 on the next line, it will be false (sig2 is still 0 for now), and we won't -- do something. We then end the process.
Now, because at the end of the first process sig2 changed value 0 -> 1 the second process will be triggered (it's sensitive to sig2). It sees that sig2 is 1 and so it will -- do something else.
When the next clock edge comes (and it could be a negative edge with this code), sig2 is still 1 and so now we'll -- do something, and we'll do that for every clock edge.
In summary the order of events for this code would be:
Clk : 0->1
Sig2 : 0->1
-- Do Something Else
Clk : 1->0
-- Do Something
Clk : 0->1
-- Do Something
Clk : 1->0
-- Do Something
Clk : 0->1
-- Do Something
.........
When you understand that ordering, you'll understand an important part of how VHDL schedules things.