counter - Count Edges over specific Period of Time in VHDL -
for speedmeasurement of electric motor count amount of rising , falling edges of encoder-input in time-intervall of 10ms.
to have implementet clock divider 40 mhz clock follows:
entity speedclk port ( clk : in std_logic; clkspeed : out std_logic); end speedclk; architecture behavioral of speedclk signal counterclk : natural range 0 400001; begin speedcounter : process begin wait until rising_edge(clk); counterclk <= counterclk + 1; if counterclk < 400000 clkspeed <= '0'; else clkspeed <= '1'; counterclk <= 0; end if; end process speedcounter; end behavioral;
this should make clkspeed '1' every 10 ms. use block component in toplevel vhdl-module. in next block count edges encoderinput(qepa) shift register debounce input signal.
entity speedmeasure port ( qepa : in std_logic; clk : in std_logic; clkspeed : in std_logic; speed : out integer -- in rpm ); end speedmeasure; architecture behavioral of speedmeasure begin edges : process(clkspeed, clk) variable detect : std_logic_vector(5 downto 0) := "000000"; variable edgespertime : integer := 0; variable countqepa : integer := 0; begin if clkspeed = '1' edgespertime := countqepa; countqepa := 0; elsif (clk'event , clk = '1') detect(5 downto 1) := detect(4 downto 0); detect(0) := qepa; if (detect = "011111") or (detect = "100000") countqepa := countqepa + 1; else countqepa := countqepa; end if; end if; speed <= edgespertime; end process edges;
end behavioral;
this should write current value of countqepa in variable edgespertime every 10 ms , reset counter afterwards. signal speed gets transmitted via uart. unfortunatly reset of countqepa every 10ms receive constant value of 0 edgespertime. if remove reset line in code, can receive increasing value edgespertime until largest number integer (2^16) reached, @ point counter resets 0.
what correct implementation in vhdl count rising , falling edges in set period of time?
any apreciated still new vhdl.
you're building latch using variable. synthesis tool inferred asynchronous reset clkspeed
countqepa
, since latch edgespertime
latches countqepa
when write enable clkspeed
asserted, see reset countqepa
value of 0
.
you should build proper synchronous logic:
signal countqepa : integer := 0; signal detect : std_logic_vector(5 downto 0) := (others => '0'); begin edge_cnt_p : process ( clk ) begin if (rising_edge(clk)) -- synchronous reset if (clkspeed = '1') countqepa <= 0; elsif ((detect = "011111") or (detect = "100000")) countqepa <= countqepa + 1; end if; end if; end process edge_cnt_p; edge_debounce_p : process ( clk ) begin if (rising_edge(clk)) detect <= detect(detect'left downto 1) & qepa; end if; end process edge_debounce_p; count_register_p : process ( clk ) begin if (rising_edge(clk)) -- synchronous write enable if (clkspeed = '1') speed <= countqepa; end if; end if; end process count_register_p;
i'm not big fan of variables, seems synthesis tools got lot smarter these days. can see, made 3 separate processes show want going on. countqepa , debounce signals now, because need readable other processes.
i assume clkspeed synchronous clk (40 mhz). if isn't, should think handshaking between clock domains.
you can of course make single process out of these individual processes. in general, try avoid variables, because can used describe behavior not synthesizable, found out hard way.
i'm not sure how long encoder bounces, if sample @ 40 mhz, 6 bit shift register not work that's 125 ns debounce (you use lower 5 bits debouncing, top bit noticing state changes).
speaking of debouncer. consider following case:
debounce qepa 111111 1 111111 0 <-- glitch/bounce on encoder line; 25 ns wide 111110 1 111101 1 111011 1 110111 1 101111 1 011111 1 <-- fake edge detected
that's not want. should compare debounced signal last stable state instead of assuming state'delayed(5 * clk_period) being stable state.
as said above, i'm assuming clk 40 mhz clock. needn't sample encoder signal fast, because proper debouncer take large number of shift register bits @ no added value you, because have divide clock down 1 khz anyway time-slot counting.
instead, take account maximum frequency of encoder signal. want oversample @ least double frequency, quadruple frequency safe. have 4 samples per "bit time".
since you're expecting many edges @ 1 khz, assume encoder @ least 2 orders of magnitude fast, i.e. 100 khz. scale 40 mhz down 400 khz , shift in qepa debouncing. sample these 400 khz down 1 khz time slot measurements.
on side note: kind of motor encoding uses single bit? sure you're not dealing quadrature encoder?
Comments
Post a Comment