这个星期做EDA的课程设计,终于得用VHDL写一些东西了,而不仅仅是实验课的时候那样十几行就能解决了。
写长一点的时候,发现两个相当棘手的禁令啊:
1、一个进程内不能进行两次边沿检测。
2、不同进程不能对同一信号进行赋值。
正因为这两条“禁令”,让本来看上去很简单的东西搞得我焦头烂额了。
于是,我打算把事情简单化,做了两个这样的练习:
1、两个按键,分别控制一个值的加和减。(这个主要是为了解决“禁令1”)
2、一个按键,按下按键输出一个固定时间脉冲。(解决“禁令2”)
我先做的是第二个练习。如果没有禁令,我的想法是,一个进程内检测到按键信号上升沿的时候对信号A写‘1’,然后另外一个进程检测到信号A为‘1’时开始用时钟信号计时并输出,到时间后对这个信号A写‘0’。看上去十分简单,天衣无缝,但是因为“禁令2”,这个简单的方法不能实现。
我的解决方法是用了两个信号,并且还有优先级的区别:
1 Library IEEE; 2 Use IEEE.STD_LOGIC_1164.ALL; 3 4 Entity KeyClk Is 5 Port( 6 clk:in std_logic; 7 c_in:in std_logic; 8 c_out:out std_logic 9 ); 10 End; 11 12 Architecture one of keyclk is 13 signal out_flag,stop_flag:std_logic; 14 begin 15 16 17 process(c_in,out_flag) 18 begin 19 if c_in='1' then 20 out_flag<='1'; 21 elsif stop_flag='1' then 22 out_flag<='0'; 23 end if; 24 end process; 25 26 c_out<=in_flag; 27 28 process(clk,in_flag) 29 variable cnt:integer range 0 to 100; 30 begin 31 if rising_edge(clk) then 32 if out_flag='1' then 33 stop_flag<='0'; 34 if cnt<5 then 35 cnt := cnt+1; 36 37 else 38 cnt := 0; 39 stop_flag<='1'; 40 end if; 41 end if; 42 end if; 43 end process; 44 end;
第二个练习是这样的,貌似有点纠结:
1 library ieee; 2 use ieee.std_logic_1164.all; 3 use ieee.std_logic_unsigned.all; 4 5 entity twokey is 6 port( 7 clk:in std_logic; 8 key1,key2:in std_logic; 9 key_rst:in std_logic; 10 qout:out std_logic_vector(7 downto 0) 11 ); 12 end entity; 13 14 architecture one of twokey is 15 signal key1_down,key2_down:std_logic; 16 signal qout2:std_logic_vector(7 downto 0); 17 begin 18 process(key1,key2,key_rst,clk) 19 begin 20 if rising_edge(clk) then 21 if key_rst='1' then 22 qout2<=(others=>'0'); 23 else 24 if key1='1' and key1_down='0' then 25 key1_down<='1'; 26 qout2<=qout2+'1'; 27 elsif key1='0' then 28 key1_down<='0'; 29 end if; 30 if key2='1' and key2_down='0' then 31 key2_down<='1'; 32 qout2<=qout2-'1'; 33 elsif key2='0' then 34 key2_down<='0'; 35 end if; 36 end if; 37 end if; 38 end process; 39 qout<=qout2; 40 end;