Idea is to generate a delayed pulse when Trig input is activated, both delay and pulse width are adjustable respectively with 'delay' and 'ton'. I use an integer counter to compare delay then delay+ton to toggle the Pulse output.
The issue is that timing sequence starts just after board programming: sigPulseCounter is incremented ... even if signals are initialized. Any tips ?
Reset works well and Trig also but there is an unwanted pulse on startup.
Thanks for your feedback.
library ieee;
use ieee.std_logic_1164.all;
entity DelayedMonostable is
generic(
delay :integer:= 2*40000000;
ton :integer:= 2*40000000);
port (
Clk: in std_logic;
Reset: in std_logic;
Trig: in std_logic;
Pulse: out std_logic;
Debug: out std_logic);
end DelayedMonostable;
architecture Behavioral of DelayedMonostable is
-- Signal declaration
signal sigPulseCounterEnable: std_logic := '0';
signal sigPulseCounter : integer := 0;
signal sigPulse : std_logic :='0';
signal sigDebug: std_logic := '0';
begin
Debug <= not sigPulseCounterEnable;
Pulse <= not sigPulse;
Counter : process(Clk, Reset)
begin
if Reset='0' then
sigPulseCounter <= 0;
sigPulseCounterEnable <= '0';
sigPulse <= '0';
elsif Trig='0' then
sigPulseCounter <= 0;
sigPulseCounterEnable <= '1';
sigPulse <= '0';
elsif rising_edge(Clk) then
if(sigPulseCounterEnable='1') then
if(sigPulseCounter = delay) then
sigPulse <= '1';
end if;
if(sigPulseCounter = delay+ton) then
sigPulse <= '0';
sigPulseCounterEnable <= '0';
sigPulseCounter <= 0;
end if;
sigPulseCounter <= sigPulseCounter + 1;
end if;
end if;
end process Counter;
end Behavioral;
I have tried to invert the Trig logic in the process without success:
elsif Trig='0'
with
elsif Trig='1'
EDIT:
I have split in 3 parts the architecture, each assign value to a signal or port - Works good now.
library ieee;
use ieee.std_logic_1164.all;
entity DelayedMonostable is
generic(
delay : integer := 40000000/2;
ton : integer := 2*40000000);
port(
Clk: in std_logic;
Reset: in std_logic;
Trig: in std_logic;
Pulse: out std_logic;
Debug: out std_logic);
end DelayedMonostable;
---------------------------------------
architecture Behavioral of DelayedMonostable is
-- Signal declaration
signal PWMCounter : integer;
signal sigTrig: std_logic;
begin
Debug <= not sigTrig;
Counter : process(Clk, Reset)
begin
if (Reset='0') then
PWMCounter <= 0;
elsif(rising_edge(Clk) and sigTrig='1') then
if(PWMCounter = ton+delay) then
PWMCounter <= 0;
else
PWMCounter <= PWMCounter + 1;
end if;
end if;
end process Counter;
Trigger: process(Reset, Trig)
begin
if (Reset='0') then
sigTrig <= '0';
elsif (Trig='0') then
sigTrig <= '1';
elsif (PwmCounter = ton+delay) then
sigTrig <= '0';
end if;
end process Trigger;
Generator : process(Clk, Reset)
begin
if (Reset='0') then
Pulse <= not '0';
elsif(rising_edge(Clk)) then
if(PwmCounter=delay) then
Pulse <= not '1';
end if;
if(PwmCounter=delay+ton) then
Pulse <= not '0';
end if;
end if;
end process Generator;
end Behavioral;
Related
I made a counter 1-30. but I got this
My schematic here. I remove counter0-3
and It's here I found the problem here. It's the clock connected with a new loop
So I want to increase the size of the clock. Like this
I'm a rookie here, I don't know how to do that. Please give me an idea, thanks
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity counter0_9x is
port(
clk : in std_logic;
clk_B : in std_logic;
reset : in std_logic;
counter : out std_logic_vector(3 downto 0);
clk_o : out std_logic
);
end counter0_9x;
architecture Behavioral of counter0_9x is
signal counter_up : std_logic_vector(3 downto 0);
begin
process(clk,reset)
variable num : integer := 0;
begin
if(reset='1')then
counter_up <= "0000";
elsif(clk'event and clk = '1')then
if clk_B = '0' then
if num <= 2 then
if counter_up = "1001" then
counter_up <= "0000";
num := num + 1;
clk_o <= '1';
else
counter_up <= counter_up + '1';
clk_o <= '0';
end if;
else
if counter_up = "0000" then
counter_up <= "0000";
num := 0;
clk_o <= '1';
else
counter_up <= counter_up + '1';
clk_o <= '0';
end if;
end if;
end if;
end if;
end process;
counter <= counter_up;
end Behavioral;
Update!!!
I have tried combinational but I still can't shrink "clk_o"
architecture Behavioral of counter0_9x is
signal counter_up : std_logic_vector(3 downto 0);
begin
process(clk,reset)
variable num : integer range 0 to 2 := 0;
begin
if(reset='1')then
counter_up <= "0000";
elsif(clk'event and clk = '1')then
if clk_B = '0' then
if num <= 1 then
if counter_up = "1001" then
counter_up <= "0000";
num := num + 1;
else
counter_up <= counter_up + '1';
end if;
else
if counter_up = "0000" then
counter_up <= "0000";
num := 0;
else
counter_up <= counter_up + '1';
end if;
end if;
end if;
end if;
end process;
counter <= counter_up;
with counter_up select
clk_o <= '1' when "0000",
'0' when others;
end Behavioral;
At firth sight this is caused by assigning the signal ("clk_o") insight a sequential process (process that is (edge) triggered by your clock).
This creates a flipflop that stores the signal value until the next rising edge of the clock.
You want to achive combinational logic. You have to create a separate process for the assignment of signal "clk_o" without any clock. (Don't forget to add the necessary signals to the sensitivity list.)
It might also be helpful to visualize the synthesis of your vhdl code using pen and paper to better predict the extracted logic.
I have been trying to make a generic sequence detector. When i try to simulate my design, I get a simulator 45-1 Fatal run time error. Can somebody please help me with this. Here is my Test bench and design.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Sequence_tb is
end Sequence_tb;
architecture Behavioral of Sequence_tb is
component sequence is
Generic(width: integer;
sequence: std_logic_vector);
Port(din,CLK,RST:in std_logic;
dout: out std_logic;
temp: buffer std_logic_vector(0 to width-1));
end component;
constant CLK_period: time := 10ns;
constant width: integer := 4;
constant sequence0: std_logic_vector(width-1 downto 0) := "1010";
signal din,CLK,RST,dout: std_logic := '0';
signal temp : std_logic_vector(0 to width-1) := (others=>'0');
begin
uut: sequence generic map(width=>width,sequence=>sequence0)
port map(din=>din,CLK=>CLK,RST=>RST,dout=>dout,temp=>temp);
CLK_proc: process
begin
CLK <= not CLK;
wait for CLK_period;
end process;
RST_proc: process
begin
RST <= '1';
wait for 20 ns;
RST <= '0';
wait;
end process;
din_proc: process
begin
din <= '1';
wait for 30 ns;
din <= '0';
wait for 10 ns;
din <= '1';
wait for 10 ns;
din <= '0';
wait for 10 ns;
din <= '1';
wait for 10 ns;
wait;
end process;
end Behavioral;
Design File:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Sequence is
Generic(width: integer;
sequence: std_logic_vector);
Port (din, CLK, rst: in std_logic;
dout: out std_logic;
temp: buffer std_logic_vector(0 to width-1));
end Sequence;
architecture Beh of Sequence is
subtype statetype is integer range 0 to width-1;
signal prstate,nxstate: statetype := 0;
begin
process(RST,CLK)
begin
if RST='1' then
temp <= (others => '0');
nxstate <= 0;
elsif CLK'event and CLK='1' then
temp(prstate) <= din;
for k in prstate downto 0 loop
if temp(k downto 0) = sequence(k downto 0) then
nxstate <= k;
exit;
else temp <= temp(1 to width-1) & '0';
end if;
end loop;
end if;
prstate <= nxstate;
end process;
dout <= '1' when prstate = width-1 and din = sequence(sequence'left) else '0';
end Beh;
I am creating a VHDL code for controlling servo position using 8 switches on DE2 development kit. When the code is done, I tested the code with the servo motor but it is not working. Then I did a waveform simulation with timing analysis, I found that there is some glitches in the wave. Is it glitch the reason why this is not working? If yes, how can I solve this?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity servo_pwm is
PORT (
clk50 : IN STD_LOGIC;
clk : IN STD_LOGIC;
reset : IN STD_LOGIC;
position : IN STD_LOGIC_VECTOR(7 downto 0);
servo : OUT STD_LOGIC
);
end servo_pwm;
architecture Behavioral of servo_pwm is
signal cnt : unsigned(11 downto 0);
signal pwmi: unsigned(7 downto 0);
begin
pwmi <= unsigned(position);
start: process (reset, clk) begin
if (reset = '1') then
cnt <= (others => '0');
elsif rising_edge(clk) then
if (cnt = 2559) then
cnt <= (others => '0');
else
cnt <= cnt + 1;
end if;
end if;
end process;
servo <= '1' when (cnt < pwmi) else '0';
end Behavioral;
Clock divider:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity clk64kHz is
Port (
clk : in STD_LOGIC;
reset : in STD_LOGIC;
clk_out: out STD_LOGIC
);
end clk64kHz;
architecture Behavioral of clk64kHz is
signal temporal: STD_LOGIC;
signal counter : integer range 0 to 195 := 0; --position 8bit
begin
freq_divider: process (reset, clk) begin
if (reset = '1') then
temporal <= '0';
counter <= 0;
--elsif rising_edge(clk) then
elsif (clk'event and clk = '1') then
--if (counter = 390) then
if (counter = 195) then
temporal <= NOT(temporal);
counter <= 0;
else
counter <= counter + 1;
end if;
end if;
end process;
clk_out <= temporal;
end Behavioral;
Vector waveform file:
I'm working on a stopwatch project in VHDL but I don't know how to make the CLK square waveform of the counter? Please help.
Here is my code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;
entity Circuit is
Port ( CLK : in STD_LOGIC := '0';
CLR : in STD_LOGIC;
Q : out STD_LOGIC_VECTOR (5 downto 0));
end Circuit;
architecture Behavioral of Circuit is
signal s: STD_LOGIC_VECTOR := "000000";
begin
process (CLK, CLR)
begin
if rising_edge(CLK) then
if CLR = '1' OR s = "111011" then
s <= "000000";
else
s <= s+1;
end if;
end if;
end process;
Q <= s;
end Behavioral;
Let's say your clock is 1 MHz, but you want the seconds counter process to work at 1 Hz. You would need to divide the incoming clock by 1 million.
constant CLOCK_DIVIDER : integer := 1000000;
signal clock_divide_counter : integer range 0 to CLOCK_DIVIDER-1 := 0;
signal one_hz_pulse : std_logic := '0';
...
process (clk)
begin
if (rising_edge(clk)) then
if (clock_divide_counter = CLOCK_DIVIDER - 1) then
clock_divide_counter <= 0;
one_hz_pulse <= '1';
else
clock_divide_counter <= clock_divide_counter + 1;
one_hz_pulse <= '0';
end if;
end if;
end process;
then modify your existing process to only be enabled when the 1 Hz pulse is high:
process (CLK, CLR)
begin
if rising_edge(CLK) then
if (CLR = '1') then
s <= "000000";
elsif (one_hz_pulse = '1') then
if s = "111011" then
s <= "000000";
else
s <= s+1;
end if;
end if;
end if;
end process;
I haven't run the code, but you should get the idea.
i'm trying to make my own I2C communication and i have a problem with multiply drivers, it's not like i don't understand them i just don't see them (i'm still fresh at vhdl), so please just take a look at my code and tell mi why is there such mistake.
i try to operate on flags to have multiple signal drivers on bus but there's just something not right. The multiple drivers are on scl, sda, start_clk and stop_clk. Is it because those flags are for example in two different processes?
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity I2C_com is
port (
reset_en: in std_logic;
clk: in std_logic;
sda: inout std_logic;
scl: out std_logic;
RD:in std_logic;
WR: in std_logic;
addr: buffer std_logic_vector(7 downto 0)
);
end I2C_com;
architecture MAIN of I2C_com is
signal data :std_logic_vector (12 downto 0):="0000000000010";
signal i2c_clk: std_logic ;
signal clk_count : unsigned(19 downto 0):="00000000000000000100";
type program_state is (start,init,error_rd_wr,slave,ack);
signal state: program_state;
signal write_data: std_logic_vector (7 downto 0):=(others => '0');
signal read_data: std_logic_vector (7 downto 0):=(others => '0');
signal clk_enable: std_logic;
signal reset: std_logic:='1';
signal start_clk: std_logic:= 'Z';
signal stop_clk: std_logic:= 'Z';
signal strech: std_logic := '0';
signal cnt_addr: integer := 0;
signal ack_error: std_logic;
signal sda_data: std_logic;
signal start_data: std_logic:= 'Z';
begin
i2c_clock: process(clk,reset_en,reset)
begin
if reset_en = '1' or reset = '1' then
elsif falling_edge(clk) then
if clk_count < unsigned(data) then
clk_count <= clk_count + 1;
clk_enable <= '1';
else
clk_count <= x"00000";
clk_enable <= '0';
end if;
i2c_clk <= clk_enable;
if start_clk = '1' then
sda <= '0';
scl <= '0';
start_clk <= '0';
end if;
if stop_clk = '1' then
sda <= '0';
scl <= '0';
stop_clk <= '0';
end if;
end if;
end process i2c_clock;
--
process(i2c_clk,reset_en,reset)
begin
if reset_en = '1' or reset = '1' then
reset <= '0';
cnt_addr <= 0;
state <= init;
elsif rising_edge(i2c_clk) then
case state is
when init =>
if RD = '1' or WR = '1' then
state <= start;
else
state <= error_rd_wr;
end if;
when start =>
start_clk <= '1';
state <= slave;
when slave =>
start_data <= '1';
if cnt_addr < 8 then
sda_data <= addr(cnt_addr);
cnt_addr <= cnt_addr + 1;
else
cnt_addr <= 0;
state <= ack;
end if;
when error_rd_wr =>
reset <= '1';
when ack =>
start_data <= '0';
ack_error <= sda;
if ack_error = '1' then
stop_clk <= '1';
reset <= '1';
else
end if;
if RD = '1' then
elsif WR = '1' then
else
stop_clk <= '1';
reset <= '1';
end if;
end case;
end if;
end process;
sda <= sda_data when start_data = '1' else 'Z';
scl <= i2c_clk when start_clk = '0' and stop_clk = '0' else 'Z';
end MAIN;
A signal for synthesis can be driven from only one process or one continuous assign; for simulation multiple drivers are possible using resolved signals like std_logic.
The scl and sda are driven both from the i2c_clock process and the continuous assign in the end of the file.
The start_clk and stop_clk are driven both from the i2c_clock process and the other unnamed process.
One possibility for scl and sda is to only drive these from the continuous assign, since synthesis tools often prefer tri-state output to be written like:
q <= value when en = '1' else 'Z';