Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20688 Discussions

VHDL robot design not working

Altera_Forum
Honored Contributor II
2,330 Views

Hello everybody I'm new in VHDL and I'm doing a project with DE2 board 

 

In the project I need to build a robot. 

 

My first step was to design a ASM and from that to take out the FSM which i did (hopefully I did it good enough) 

The second step is to check one of my ASM and I choose my engine control ASM 

I wrote a program in VHDL using quartus and burn it into my board  

Instead of using the motors from the beginnig the idea was to used the board's led using a PWM generator that will create a "running led" effect for a curtain direction and in change it in a push of a button 

but it didn't work. 

Can anybody tell me what I did wrong? 

 

I think it's in the pin assignment
0 Kudos
34 Replies
Altera_Forum
Honored Contributor II
1,100 Views

The code: 

 

library IEEE; 

use IEEE.std_logic_1164.all; 

use ieee.std_logic_arith.all; 

use ieee.std_logic_unsigned.all; 

Entity Pwm is 

Port ( Rst : In std_logic; 

Clk : In std_logic; 

s : In std_logic; 

Enable : in std_logic; 

Led : buffer std_logic_vector (7 downto 0); 

Pwm : Out std_logic ); 

 

attribute altera_chip_pin_lc : string; 

attribute altera_chip_pin_lc of clk : signal is "@N2"; 

attribute altera_chip_pin_lc of rst : signal is "@G26"; 

attribute altera_chip_pin_lc of Led : signal is "@AE23, @AF23, @AB21, @AC22, @AD22, @AD23, @AD21"; 

attribute altera_chip_pin_lc of s : signal is "@N25"; 

attribute altera_chip_pin_lc of Enable : signal is "@N26"; 

end entity Pwm; 

Architecture arc_Pwm of Pwm is 

signal Counter : std_logic_vector (16 downto 0); 

signal DC : std_logic_vector (16 downto 0); 

begin 

PwmReg: process (Clk,Rst,s) 

begin 

if (Rst='1') then 

Counter <= (others=>'0'); 

Pwm <= '0'; 

Led <= (others=>'0'); 

DC <= conv_std_logic_vector(32678,17); --duty cycle 50% 

elsif rising_edge(Clk) then 

if (Enable='1') then 

if (Counter = 50000) then 

Counter <= (others => '0'); 

elsif (Counter < DC) then 

Counter <= Counter + 1; 

Pwm <= '1'; 

if (s = '1') then  

led <= Led + 1; 

if(Led = "11111111") then 

Led <= (others=>'0'); 

end if; 

else 

led <= Led - 1; 

if(Led = "00000000") then 

Led <= (others=>'1'); 

end if; 

end if; 

else 

Counter <= Counter + 1; 

Pwm <= '0'; 

end if; 

else  

Pwm <= '0'; 

end if; 

end if; 

end process PwmReg; 

end architecture arc_Pwm;
0 Kudos
Altera_Forum
Honored Contributor II
1,100 Views

Hi rotemkim, 

 

I am changing the name of your thread title to something more specific to your topic of discussion. Also I'm moving it to the General Altera Discussion category. The "Altera Forum Website Related" category is for questions about the forum website or its use, not the use of devices or tools from Altera.  

 

For help with your problem, it would be easier for others to give you advice if you point out some debug steps you've taken. Have you simulated the VHDL code to see if it behaves as you expect? The pinout check is also a good start, but checking the code in simulation is better start.  

 

You may want to add a sanity check output pin that drives an LED on the board. Divide your input clock to a slow speed <= a few Hz and assign it to the output pin that drives the LED. Start small and work your way back to full design functionality.
0 Kudos
Altera_Forum
Honored Contributor II
1,100 Views

your right I do need to simulate the code first... 

 

I wrote a tb for the code but i dont see any waveform way? 

 

library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; --use std.textio.all; --use ieee.std_logic_textio.all; ------------------------------------------------------------------------------ entity tb_pwm is end entity tb_pwm; ------------------------------------------------------------------------------ architecture arc_tb_pwm of tb_pwm is signal Clk : std_logic := '0'; -- signal Rst : std_logic := '0'; -- signal Sw : std_logic_vector (2 downto 0):= "000"; -- signal Enable : std_logic := '0'; -- signal Pwm : std_logic; -- signal Led : std_logic_vector(7 downto 0); -- begin test : entity work.pwm port map ( Clk => Clk, Rst => Rst, Enable => Enable, Sw => Sw, Pwm => Pwm, Led => Led ); Clk <= not Clk after 10 ns; Rst <= '1' after 20 ns; process begin wait until Rst = '1'; wait until rising_edge(Clk); Enable <= '1'; wait until rising_edge(clk); Sw(0) <= '1'; Sw(1) <= '0'; Sw(2) <= '0'; wait for 100ms; wait until rising_edge(clk); Sw(0) <= '0'; Sw(1) <= '1'; Sw(2) <= '0'; wait for 100ms; wait until rising_edge(clk); Sw(0) <= '0'; Sw(1) <= '0'; Sw(2) <= '1'; wait for 100ms; wait until rising_edge(clk); Enable <= '0'; wait for 100ms; wait until rising_edge(clk); Rst <='0'; wait for 100ms; end process; end architecture arc_tb_pwm;
0 Kudos
Altera_Forum
Honored Contributor II
1,100 Views

The testbench doesnt match the PWM code you posted. In your PWM code, there is no SW bus. 

 

One other things: 

 

When you use a std_logic_vector as a counter (I highly recommend you dont, use the numeric_std library instead of std_logic_arith/unsigned) you dont need to reset it if it gets to max. It will roll over if you get to all ones and roll under if you get to all zeros. You only have to check the value if LED was an integer rather than std_logic_vector.
0 Kudos
Altera_Forum
Honored Contributor II
1,100 Views

Your right I changed the code a little. 

 

library IEEE; use IEEE.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; use ieee.numeric_std.all; Entity Pwm is Port ( Rst : In std_logic; Clk : In std_logic; Sw : In std_logic_vector (2 downto 0); Enable : in std_logic; Led : out std_logic_vector (7 downto 0); Pwm : Out std_logic); attribute altera_chip_pin_lc: string; attribute altera_chip_pin_lc of Clk : signal is "@N2"; attribute altera_chip_pin_lc of Rst : signal is "@G26"; attribute altera_chip_pin_lc of Led : signal is "@AE23, @AF23, @AB21, @AC22, @AD22, @AD23, @AD21, @AC21"; attribute altera_chip_pin_lc of Sw : signal is "@N25,@N26, @P25"; attribute altera_chip_pin_lc of Enable: signal is "@AE14"; end entity Pwm; Architecture arc_Pwm of Pwm is signal Counter : std_logic_vector (16 downto 0); signal DC : std_logic_vector (16 downto 0); signal Rd_led : std_logic_vector (7 downto 0); begin PwmReg: process (Clk,Rst,Sw) begin if (Rst='1') then Counter <= (others=>'0'); Pwm <='0'; Led <= (others=>'0'); Rd_led <= (others=>'0'); DC <= conv_std_logic_vector(32678,17); --duty cycle 50% elsif rising_edge(Clk) then if (Enable='1') then if (Counter = 50000) then Counter <= (others => '0'); if (Sw(0) = '1') and (Sw(1) = '0') and (Sw(2) = '0') then Rd_led <= Rd_led + 1; elsif (Sw(0) = '0') and (Sw(1) = '1') and (Sw(2) = '0') then Rd_led <= Rd_led - 1; end if; Led <= Rd_led; elsif (Counter < DC) then Counter <= Counter + 1; Pwm <= '1'; else Counter <= Counter + 1; Pwm <= '0'; end if; else Pwm <= '0'; end if; end if; end process PwmReg; end architecture arc_Pwm;  

 

I am don't know what numeric std library does can you clarify please, and why is it better to use rather then std_logic in general and specific in this code
0 Kudos
Altera_Forum
Honored Contributor II
1,100 Views

The problem is your reset it driven outside and inside the process, leading to rst beign 'X', and none of the internal counters get initialised to 0. Either remove the rst <= after 20ns; line or Rst <= '0' inside the process.  

 

Signals can only be driven from one place. 

 

Secondly - are you sure you meant wait for 100ms? that is 10 million clocks with the clock period you have chosen. 

 

thirdly, you are holding the design in reset for the whole simulation. 

 

 

numeric_std is the official IEEE standard library. std_logic_arith/unsigned are not a real standard, but they allow you to do maths on std_logic_vectors. std_logic_vectors were NOT meant to represent an integer, just a collection of bits. numeric_std contains an unsigned and signed type that do represent numbers. you cannot use numeric_std and std_logic_arith in the same file as they contain clashes.
0 Kudos
Altera_Forum
Honored Contributor II
1,100 Views

I see the Rst problem now and it was supposeto be ns and ms... but still no waves? 

 

library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; --use std.textio.all; --use ieee.std_logic_textio.all; ------------------------------------------------------------------------------ entity tb_pwm is end entity tb_pwm; ------------------------------------------------------------------------------ architecture arc_tb_pwm of tb_pwm is signal Clk : std_logic := '0'; -- signal Rst : std_logic := '0'; -- signal Sw : std_logic_vector (2 downto 0):= "000"; -- signal Enable : std_logic := '0'; -- signal Pwm : std_logic; -- signal Led : std_logic_vector(7 downto 0); -- begin test : entity work.pwm port map ( Clk => Clk, Rst => Rst, Enable => Enable, Sw => Sw, Pwm => Pwm, Led => Led ); Clk <= not Clk after 10 ns; process begin wait until rising_edge(Clk); Enable <= '1'; wait until rising_edge(clk); Sw(0) <= '1'; Sw(1) <= '0'; Sw(2) <= '0'; wait until rising_edge(clk); Sw(0) <= '0'; Sw(1) <= '1'; Sw(2) <= '0'; wait for 0.1us; wait until rising_edge(clk); Sw(0) <= '0'; Sw(1) <= '0'; Sw(2) <= '1'; wait for 0.1us; wait until rising_edge(clk); Enable <= '0'; wait for 0.1us; wait until rising_edge(clk); wait for 0.1us; Rst<= '0'; end process; end architecture arc_tb_pwm;
0 Kudos
Altera_Forum
Honored Contributor II
1,100 Views

Maybe you do mean ms. The rd_led counter only increments once every 50000 clock cycles (thats once every 500 us) so 1ms increments the counter twice

0 Kudos
Altera_Forum
Honored Contributor II
1,100 Views

Plus also the LED output lags the rd counter by 50000 clocks.

0 Kudos
Altera_Forum
Honored Contributor II
1,100 Views

I wanted that the led will light in 1khz so I could see them. 

so if DE2 board have 50Mhz clock I need to count to 50000. 

taking that into account if every cycle I raise the output Led only once it means that the led change once per 0.5ms that means twice in 1khz cycle just like you said and what I wanted it to do. 

once and let say I want it to run at least 50 times so I need 50ms delay 

so far I hope I got it right. 

 

I don't know what you mean when you say that the Led lag the rd_led they update together they are in the same IF Statement suppose to be any way that who I see it . 

 

if the code is good at least reasonable enough to work 

maybe I just dont know who to run the sim and a guide will help?
0 Kudos
Altera_Forum
Honored Contributor II
1,100 Views

 

--- Quote Start ---  

 

I don't know what you mean when you say that the Led lag the rd_led they update together they are in the same IF Statement suppose to be any way that who I see it . 

--- Quote End ---  

 

 

Because you assign LED to rd_LED, LED takes the old value of rd_LED. Signals are not updated immediatly like variables, they are updated when a process suspends.  

 

so whith this code in a clocked process: 

 

b <= a; 

c <= b; 

 

this is what happens: 

 

clk _|-|_|-|_|-|_|-|_|-|_| a 0 1 2 3 4 5 b U 0 1 2 3 4 c U U 0 1 2 3
0 Kudos
Altera_Forum
Honored Contributor II
1,100 Views

your right I should have know that...  

 

that kind of relate to a another problem I notice, if I have a lag and I want to get ride of it I need to change Rd_Led to a variable but then his value want be save after he loop right? so what can I do?. 

 

second problem is about DC it's a lacth and can't work in a real board. 

I need to change it to a constant, but I want it to be more general code so I'll change it to a generic , were and who do I create a generic (entity, architecture ..)?
0 Kudos
Altera_Forum
Honored Contributor II
1,100 Views

To make LED connect to RD_LED, just assign it outside of a process. Or if you want to make it a variable, just assign LED above if counter = 50000 then.., and asign RD_led (as a variable) where it is now. Variables can store values between clocks if you put things in the right order. 

 

For DC, because it is set a value and nothing else, Quartus will probably just assume it is a constant. But making it a generic might be a good idea. Generics are created like ports, in the generic section: 

 

entity my_ent is generic ( DC : integer; ); port ( ); end entity my_ent;  

 

Then when you do the instantiation, you give it a value. 

 

my_inst : entity work.my_ent generic map ( DC => 32678, ) port map ( ... );  

 

Inside your entity, you just treat generics like constants.
0 Kudos
Altera_Forum
Honored Contributor II
1,100 Views

wow thanks, 

 

That should be very helpful I have tests coming up this week I'll let you know who I managed to fix the code later on
0 Kudos
Altera_Forum
Honored Contributor II
1,100 Views

Hii again 

 

the code has changed (add generic and a constant) and I am using the modelsim now insted of the active hdl 

 

but I still don't see any waves in the simulation :mad: 

 

library IEEE; use IEEE.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; use ieee.numeric_std.all; Entity Pwm is generic ( DC : time:=1 ms; clock_period: time:=20 ns ); Port ( Rst : In std_logic; Clk : In std_logic; Sw : In std_logic_vector (2 downto 0); Enable : in std_logic; Led : buffer std_logic_vector (7 downto 0); Pwm : Out std_logic ); attribute altera_chip_pin_lc: string; attribute altera_chip_pin_lc of Clk : signal is "@N2"; attribute altera_chip_pin_lc of Rst : signal is "@G26"; attribute altera_chip_pin_lc of Led : signal is "@AE23, @AF23, @AB21, @AC22, @AD22, @AD23, @AD21, @AC21"; attribute altera_chip_pin_lc of Sw : signal is "@N25,@N26, @P25"; attribute altera_chip_pin_lc of Enable: signal is "@AE14"; end entity Pwm; Architecture arc_Pwm of Pwm is constant duty_cycle: integer:=DC/clock_period; signal Counter : std_logic_vector (16 downto 0); begin PwmReg: process (Clk,Rst,Sw) begin if (Rst='1') then Counter <= (others=>'0'); Pwm <='0'; Led <= (others=>'0'); elsif rising_edge(Clk) then if (Enable='1') then if (Counter = duty_cycle) then Counter <= (others => '0'); if (Sw(0) = '1') and (Sw(1) = '0') and (Sw(2) = '0') then led <= led + 1; elsif (Sw(0) = '0') and (Sw(1) = '1') and (Sw(2) = '0') then led <= led - 1; end if; else Counter <= Counter + 1; end if; end if; if (Counter < duty_cycle) then Pwm <= '1'; else Pwm <= '0'; end if; end if; end process PwmReg; end architecture arc_Pwm;  

 

library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; --use std.textio.all; --use ieee.std_logic_textio.all; ------------------------------------------------------------------------------ entity tb_pwm is end entity tb_pwm; ------------------------------------------------------------------------------ architecture arc_tb_pwm of tb_pwm is signal Clk : std_logic := '0'; -- signal Rst : std_logic := '0'; -- signal Sw : std_logic_vector (2 downto 0):= "000"; -- signal Enable : std_logic := '0'; -- signal Pwm : std_logic; -- signal Led : std_logic_vector(7 downto 0); -- begin test : entity work.pwm port map ( Clk => Clk, Rst => Rst, Enable => Enable, Sw => Sw, Pwm => Pwm, Led => Led ); Clk <= not Clk after 10 ns; process begin wait until rising_edge(Clk); --wait on switch push; Enable <= '1'; -- l1 : loop wait until rising_edge(clk); --wait for 1 ns; Sw(0) <= '1'; Sw(1) <= '0'; Sw(2) <= '0'; wait for 0.025us; wait until rising_edge(clk); Sw(0) <= '0'; Sw(1) <= '1'; Sw(2) <= '0'; wait for 0.025us; wait until rising_edge(clk); Sw(0) <= '0'; Sw(1) <= '0'; Sw(2) <= '1'; wait for 0.025us; wait until rising_edge(clk); Enable <= '0'; wait for 0.025us; wait until rising_edge(clk); Rst <='0'; wait for 0.025us; end process; end architecture arc_tb_pwm;  

 

In the do file I wrote 1us and in the tb iwrote 0.025us in order to see it in the simulaton 

 

thanks in advance
0 Kudos
Altera_Forum
Honored Contributor II
1,100 Views

the duty cycle is 50000, so you need at least this many clock cycles before LED is valid. Your entire simulation runs for 1 us at 100MHz, so you get a grand total of 100 clocks. 

 

Another problem - you dont assert reset so your counter will never count (because it's all 'U' when it does try and count).
0 Kudos
Altera_Forum
Honored Contributor II
1,100 Views

I changed it to dC : time:=100 ns 

that means 5 cycles so it should work right? but still no waves
0 Kudos
Altera_Forum
Honored Contributor II
1,100 Views

your sw settings arnt held for long enough.

0 Kudos
Altera_Forum
Honored Contributor II
1,100 Views

hi, 

 

I changed the sw time to 50 ns even though I dont think its the problme, 

 

because the simulation still needed to display the sw waves and I only see  

 

clk wave and the others are : pwm - 'u' rst- 'x' others - '0'  

 

but know the clock time << sw time , so that solve this issue. 

 

I notice that I didnt included the generic map in the tb before so I did it now  

 

from a VHDL examples folder and I hope I did it right. 

 

but still there no changes in the waves ... so what now?:confused: 

library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; --use std.textio.all; --use ieee.std_logic_textio.all; ------------------------------------------------------------------------------ entity tb_pwm is end entity tb_pwm; ------------------------------------------------------------------------------ architecture arc_tb_pwm of tb_pwm is signal Clk : std_logic := '0'; -- signal Rst : std_logic := '0'; -- signal Sw : std_logic_vector (2 downto 0):= "000"; -- signal Enable : std_logic := '0'; -- signal Pwm : std_logic; -- signal Led : std_logic_vector(7 downto 0); -- begin test : entity work.pwm generic map( DC => 100 ns, clock_period => 20 ns ) a port map ( Clk => Clk, Rst => Rst, Enable => Enable, Sw => Sw, Pwm => Pwm, Led => Led ); Clk <= not Clk after 10 ns; process begin wait until rising_edge(Clk); Enable <= '1'; wait until rising_edge(clk); Sw(0) <= '1'; Sw(1) <= '0'; Sw(2) <= '0'; wait for 100 ns; wait until rising_edge(clk); Sw(0) <= '0'; Sw(1) <= '1'; Sw(2) <= '0'; wait for 100 ns; wait until rising_edge(clk); Sw(0) <= '0'; Sw(1) <= '0'; Sw(2) <= '1'; wait for 100 ns; wait until rising_edge(clk); Enable <= '0'; wait for 100 ns; wait until rising_edge(clk); Rst <='0'; wait for 100 ns; end process; end architecture arc_tb_pwm;
0 Kudos
Altera_Forum
Honored Contributor II
1,024 Views

add a reset at the beginning of the process, like this: 

begin wait until rising_edge(Clk); Enable <= '1'; rst <= '1'; wait until rising_edge(clk); rst <= '0';  

 

and you'll get waves like this:
0 Kudos
Reply