3. 戏说VHDL之入门游戏一:流水灯
2016-01-26 17:15
134 查看
一. 流水灯
1.1流水灯原理
流水灯是每个学电子的入门“游戏” ,示意图如图1,其原理极其简单,但是可玩性却极强,可以就8个LED写出不同花样的程序。在1.2中我们列出两个不同思路的代码作为VHDL的入门例程。
图1 流水灯电路图
1.2 流水灯例程
这里提供两个不同的代码。
第一个代码的思路是先对系统时钟分频,产生1s信号(即变量count取值到25000000,这样分频时间=20ns*25000000*2=1s),然后使用移位操作符指令进行操作。该指令是在VHDL93中引入的,包括sll,srl,sla,sra,rol,ror6个指令,指令操作如图2一目了然。值得注意的是,使用该指令,左操作数必须是BIT_VECTOR类型,右操作数必须是INTEGER类型(前面可以有负号)。
图2 移位操作符示意图
例如:令x <= “10110”,则
y <= x sll 2 ;--逻辑左移两位,y <= “ 11000”,空余位填充0
y <= x srl 2 ;--逻辑右移两位,y <= “00101”,空余位填充0
y <= x sla 2 ;--算术左移两位,y <= “11000”,空余位复制最右边上的数值
y <= x sra 2 ;--算术右移两位,y <= “11101”,空余位复制最左边上的数值
y <= x rol 2 ;--循环逻辑左移两位,y <= “11010”,左侧移出位填补到右侧
y <= x ror 2 ;--循环逻辑右移两位,y <= “10101”,右侧移出位填补到左侧
例程一:
--------------------------------------------------------------------------------------------------
仿真波形:
从仿真波形中,可以验证例程的正确性。
第二个代码的思路是先对系统时钟分频,产生1s信号,然后对该1s信号进行模8计数,再利用case-when语句进行判断,进而控制LED。
例程二:
仿真波形:
从仿真波形中,可以验证例程的正确性。
1.3 总结
其实,肯定还有其他精妙的想法,这里只列举了两种代码作为学习的开头。不过通过两个代码的学习,也熟悉了移位操作符和case-when语句的使用。下一节将开始数码管的学习。
参考文献:
[1] Volnei A.Pedroni.VHDL 数字电路设计教程[M].北京:电子工业出版社,2009:39-40;
[2] http://leonmoon.blog.hexun.com/4609284_d.html
1.1流水灯原理
流水灯是每个学电子的入门“游戏” ,示意图如图1,其原理极其简单,但是可玩性却极强,可以就8个LED写出不同花样的程序。在1.2中我们列出两个不同思路的代码作为VHDL的入门例程。
图1 流水灯电路图
1.2 流水灯例程
这里提供两个不同的代码。
第一个代码的思路是先对系统时钟分频,产生1s信号(即变量count取值到25000000,这样分频时间=20ns*25000000*2=1s),然后使用移位操作符指令进行操作。该指令是在VHDL93中引入的,包括sll,srl,sla,sra,rol,ror6个指令,指令操作如图2一目了然。值得注意的是,使用该指令,左操作数必须是BIT_VECTOR类型,右操作数必须是INTEGER类型(前面可以有负号)。
图2 移位操作符示意图
例如:令x <= “10110”,则
y <= x sll 2 ;--逻辑左移两位,y <= “ 11000”,空余位填充0
y <= x srl 2 ;--逻辑右移两位,y <= “00101”,空余位填充0
y <= x sla 2 ;--算术左移两位,y <= “11000”,空余位复制最右边上的数值
y <= x sra 2 ;--算术右移两位,y <= “11101”,空余位复制最左边上的数值
y <= x rol 2 ;--循环逻辑左移两位,y <= “11010”,左侧移出位填补到右侧
y <= x ror 2 ;--循环逻辑右移两位,y <= “10101”,右侧移出位填补到左侧
例程一:
-------------------------------------------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; -------------------------------------------------------------------------------------------------- entity VHDL_LEDWATER1 is port ( Clk : in STD_LOGIC; --创建时钟端口,连接开发板PIN23 Rst : in STD_LOGIC; --创建复位端口,连接开发板PIN116 Output : out BIT_VECTOR(7 downto 0) --创建输出端口,对应8个LED。分别 --为PIN142-PIN133,要使用移位操作符 ); --其左侧必须为BIT_VECTOR类型 end VHDL_LEDWATER1; -------------------------------------------------------------------------------------------------- architecture behave of VHDL_LEDWATER1 is signal Clk1 : STD_LOGIC; --建立中间时钟信号 begin P1:process(Clk) variable count : INTEGER range 0 to 25 := 0; --变量初始值不可综合,在仿真中使用,并 variable count1: STD_LOGIC := '1'; --且为便于仿真,这里取到25,当烧写到开 --发板时候,改写为25000000即可 begin if(Rst = '0') then count := 0; elsif(Clk'event and Clk = '1') then count := count + 1; if(count = 25) then --这里使用=,而不是>=,可以防止产生比较器,节省硬件资源 count := 0; count1 := not count1; end if; end if; Clk1 <= count1; end process P1; P2:process(Clk1) variable temp : BIT_VECTOR(7 downto 0) := "11111110";--注意左操作数类型 begin if(Clk1'event and Clk1 = '1') then temp := (temp rol 1); end if; Output <= temp; end process P2; end architecture;
--------------------------------------------------------------------------------------------------
仿真波形:
从仿真波形中,可以验证例程的正确性。
第二个代码的思路是先对系统时钟分频,产生1s信号,然后对该1s信号进行模8计数,再利用case-when语句进行判断,进而控制LED。
例程二:
-------------------------------------------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all;--该库定义了std_logic(8值)和std_ulogic(9值)多值逻辑结构 -------------------------------------------------------------------------------------------------- entity LEDWATER is port ( Clk : in STD_LOGIC; --创建时钟端口,连接开发板PIN23 Rst : in STD_LOGIC; --创建复位端口,连接开发板PIN116 Output : out STD_LOGIC_VECTOR(7 downto 0) --创建输出端口,连接开发板PIN142-PIN133 ); end LEDWATER; -------------------------------------------------------------------------------------------------- architecture BEHAVIOR_LEDWATER of LEDWATER is signal Clk1 : STD_LOGIC; --建立中间时钟信号 begin P1: process(Clk) --进程1,对时钟信号进行N分频 variable count : INTEGER range 0 to 25 := 0;--变量初始值不可综合,在仿真中使用 variable count1: STD_LOGIC := '1'; begin if(Rst = '0') then count := 0; elsif(Clk'event and Clk = '1') then count := count + 1; if(count = 25) then count := 0; count1:= not count1; end if; Clk1 <= count1; end if; end process; P2: process(Clk1) --进程2,对分频信号进行计数,进而控制LED亮灭 variable count2 : INTEGER range 0 to 8 := 0;--变量初始值不可综合,在仿真中使用 begin if(Clk1'event and Clk1 = '1') then count2 := count2 + 1; if(count2 = 8) then count2 := 0; end if; end if; case count2 is when 0 => Output <= "11111110"; when 1 => Output <= "11111101"; when 2 => Output <= "11111011"; when 3 => Output <= "11110111"; when 4 => Output <= "11101111"; when 5 => Output <= "11011111"; when 6 => Output <= "10111111"; when 7 => Output <= "01111111"; when others => Output <= (others => 'Z'); end case; end process; end BEHAVIOR_LEDWATER;
仿真波形:
从仿真波形中,可以验证例程的正确性。
1.3 总结
其实,肯定还有其他精妙的想法,这里只列举了两种代码作为学习的开头。不过通过两个代码的学习,也熟悉了移位操作符和case-when语句的使用。下一节将开始数码管的学习。
参考文献:
[1] Volnei A.Pedroni.VHDL 数字电路设计教程[M].北京:电子工业出版社,2009:39-40;
[2] http://leonmoon.blog.hexun.com/4609284_d.html
相关文章推荐
- AC自动机(模板)
- SpringMVC Web配置启动
- 有了Jenkins,为啥还需要一个独立的部署系统?
- Boost 学习之算法篇 is_permutation
- chrome 谷歌浏览器 C:\fakepath\xx解决办法
- iOS---Foundation(NSURLCache.h)简介
- MATLAB Floyd算法求最短路
- web 前端学习
- C#中remoting和webservice的区别
- js编写的简单日历
- SQL SERVER 递归
- 前端笔记七,级联样式单与CSS选择器(二)
- XML——文档类型定义(DTD-Document Type Definition)
- css3学习笔记
- JUnit 4
- 数据库取出的数据含有html标签处理办法
- 欢迎使用CSDN-markdown编辑器
- Hdu 1166 敌兵布阵 -- 线段树
- leetcode 63. Unique Paths II
- Eclipse验证码