一、设计任务要求
- 1. 设计并实现一个随机数生成电路,每 2 秒 随机生成一个 0~999 之间的数 字,并在数码管上显示生成的随机数。
- 2. 为系统设置一个复位键,复位后数码管显示“000”,2 秒后再开始每 2 秒 生成并显示随机数,要求使用按键复位。
- 3. 实验板上输入时钟选择 1kHz 或更高的频率。
-
二、设计思路
随机数产生:设一个变量f为vector(5 downto 0),随时钟进行计数,其中的,每次抽取其中四位进行相邻位异或运算产生新的数作为这一位数。
如第一个数的有四位,则取f的0~3位,第二个数,则取f的1~4位,第三个数,则取f的2~5位。
第一位数有四位,如第一位数的第0位,则为从取出来的f的0~3位的第0位和第1位异或,第1位,则为从f中取出来的第1位和第2位异或,第2位则为从f中取出来的第2位和第3位异或,第三位则为第3位和第0位异或;第二位数有四位,第0位,则为从取出来的f的1~4位的,第1位和第2位异或,第1位,则为从f中取出来的第2位和第3位异或,第2位则为从f中取出来的第3位和第4位异或,第三位则为第4位和第1位异或;其他以此类推产生随机数。
在译码电路通过对译码电路的的10~15进行赋值0~9,使得16个数都有对应的值。
2.1总体电路为:
输入信号1kHz,对时钟信号进行2000分频,使得数码管能保持2秒不变,通过随机数产生后,通过译码电路,使用时钟频率1kHz进行扫描,使三个数码管交替变亮让肉眼觉得是三个同时亮。
2.2模块划分
2.3总体框图
三、VHDL代码
3.1 2000分频模块
library ieee; --库和程序包声明
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity div2000 is --2000分频器实体描述
port(
clk: in std_logic; --时钟输入端口
clear: in std_logic; --复位键输入端口
clk_out:out std_logic); --时钟分频后输出端口
end div2000;
architecture a of div2000 is --结构体描述
signal tmp: integer range 0 to 999; --整型数,用来记录分频
signal clktmp: std_logic; --信号定义,只能是储存时钟信号
begin
process(clear,clk)
begin
if clear='1' then --如果按下复位键,分频计数归零,重新开始计数
tmp<=0;
elsif clk'event and clk='1' then
if tmp=999 then --从0计数到999,则信号反转一下
tmp<=0;clktmp<=not clktmp;
else
tmp<=tmp+1;
end if;
end if;
end process;
clk_out<=clktmp;
end a;
3.2 防抖模块
此防抖电路为计数型防抖电路。人按动按钮时,相对于高速的时钟频率来说很慢,而抖动则很快,可以通过计数来消除抖动,当按动持续一定时间,则输出正脉冲;若持续时间过短,则为抖动不进行输出。
library ieee; --库和程序包声明
use ieee.std_logic_1164.all;
entity antisk is --防抖电路实体描述
port(clk:in std_logic; --时钟信号
input:in std_logic; --按钮输入端口
output:out std_logic --输出端口
);
end antisk;
architecture a of antisk is
signal a:std_logic;
signal count:integer range 0 to 9;
begin
process(clk)
begin
if input='0' then
count<=0;
elsif (clk'event and clk='1') then --当按钮输入时
if count=9 then --当按钮按动持续一定时间
count<=count;
else count<=count+1;
end if;
end if;
if count=8 then a<='1'; --则输出为正
else a<='0';
end if;
end process;
output<=a;
end;
3.3 随机数生成模块
使用时钟频率1KHz进行三个数码管扫描输出,使人眼以为同时亮。
因为每一个三位的随机数要保持2秒,所以产生的随机数只要2秒变一回就可以。产生随机数的思路是,设一个6位向量,三个数,每一个是4位的向量,从6位向量里面依次取出4位,然后四位进行异或运算,得出新的四位数作为输出。
library ieee; --库和程序包
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity random is
port (clk1000:in std_logic; --时钟输入1KHz
clk2:in std_logic; --时钟输入0.5Hz
clear:in std_logic; --复位
f1_out:std_logic_vector(3 downto 0); --第一个随机数(为了波形能看到)
f2_out:std_logic_vector(3 downto 0); --第二个随机数(为了波形能看到)
f3_out:std_logic_vector(3 downto 0); --第三个随机数(为了波形能看到)
shu:out std_logic_vector(3 downto 0);--送给译码电路译码
cat:out std_logic_vector(7 downto 0));--数码管亮还是不亮控制
end entity;
architecture a of random is
signal tmp:integer range 0 to 2; --用来循环让三个数码管依次亮起
signal f:std_logic_vector(5 downto 0); --计数增加
signal f0:std_logic_vector(5 downto 0); --从f中取数,供以产生三个随机数
signal f1:std_logic_vector(3 downto 0); --第一个随机数
signal f2:std_logic_vector(3 downto 0); --第一个随机数
signal f3:std_logic_vector(3 downto 0); --第一个随机数
begin
process(clk1000,clk2,clear) --开始进程,以时钟clk1000,
begin --和时钟clk2,复位清除clear为敏感信号
if (clk2'event and clk2='1') then f<=f+3; end if; --f每2秒变一回
if clear='1' then f0<="000000"; --当复位信号来了,f0赋值为0
elsif (clk2'event and clk2='1') then --如果复位信号没有来,每两秒
f0<=f; --将f的值赋给f0
end if;
f1(0)<=f0(0) xor f0(1); --第一位数的第0位是f0的第0位与第1位异或
f1(1)<=f0(1) xor f0(2); --第一位数的第1位是f0的第1位与第2位异或
f1(2)<=f0(2) xor f0(3); --第一位数的第2位是f0的第2位与第3位异或
f1(3)<=f0(3) xor f0(0); --第一位数的第3位是f0的第3位与第0位异或
f2(0)<=f0(1) xor f0(2); --第二位数的第0位是f0的第1位与第2位异或
f2(1)<=f0(2) xor f0(3); --第二位数的第0位是f0的第2位与第3位异或
f2(2)<=f0(3) xor f0(4); --第二位数的第0位是f0的第3位与第4位异或
f2(3)<=f0(4) xor f0(1); --第二位数的第0位是f0的第4位与第1位异或
f3(0)<=f0(2) xor f1(3); --第三位数的第0位是f0的第2位与第3位异或
f3(1)<=f0(3) xor f0(4); --第三位数的第1位是f0的第3位与第4位异或
f3(2)<=f0(4) xor f0(5); --第三位数的第2位是f0的第4位与第5位异或
f3(0)<=f0(5) xor f0(2); --第三位数的第3位是f0的第5位与第2位异或
if (clk1000'event and clk1000='1') then --用来判断刷新三个数码管
if tmp=2 then tmp<=0 ;else tmp<=tmp+1;--刷新的频率大于50Hz
end if;end if; --人眼看到就不会抖动
case tmp is
when 0=> shu<=f1;cat<="11110111"; --tmp=0,第3个数码管亮
when 1=> shu<=f2;cat<="11111011"; --tmp=1,第2个数码管亮
when 2=> shu<=f3;cat<="11111101"; --tmp=2,第1个数码管亮
end case;
f1_out<=f1;f2_out<=f2;f3_out<=f3; --看最后总体的输出波形使用
end process;
end;
3.4 数码管译码电路
由于一个数码管只能显示数字0~9,而四位二进制数能显示0~15,所以对于超过10的数进行重新赋值显示
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY seg IS
PORT(
a:IN STD_LOGIC_VECTOR(3 DOWNTO 0); --输入端口
b:OUT STD_LOGIC_VECTOR(6 DOWNTO 0)); --输出端口
END seg;
ARCHITECTURE seg7_1_arch OF seg IS
BEGIN
PROCESS(a)
BEGIN
CASE a IS
WHEN "0000" => b <= "1111110"; --输入是0,则显示0
WHEN "0001" => b <= "0110000"; --输入是1,则显示1
WHEN "0010" => b <= "1101101"; --输入是2,则显示2
WHEN "0011" => b <= "1111001"; --输入是3,则显示3
WHEN "0100" => b <= "0110011"; --输入是4,则显示4
WHEN "0101" => b <= "1011011"; --输入是5,则显示5
WHEN "0110" => b <= "1011111"; --输入是6,则显示6
WHEN "0111" => b <= "1110000"; --输入是7,则显示7
WHEN "1000" => b <= "1111111"; --输入是8,则显示8
WHEN "1001" => b <= "1111011"; --输入是9,则显示9
WHEN "1010" => b <= "1110000"; --输入是10,则显示7
WHEN "1011" => b <= "0110000"; --输入是11,则显示1
WHEN "1100" => b <= "0110011"; --输入是12,则显示4
WHEN "1101" => b <= "1111111"; --输入是13,则显示8
WHEN "1110" => b <= "1011111"; --输入是14,则显示6
WHEN "1111" => b <= "1111110"; --输入是15,则显示0
END CASE;
END PROCESS;
END;
3.5 总体电路连接模块
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity whole is
port (clock,key:in std_logic; --时钟和复位信号
seg0:out std_logic_vector(6 downto 0); --数码管
shu:out std_logic_vector(3 downto 0); --数码管此时译码的数
f1:out std_logic_vector(3 downto 0); --第一个随机数(为了波形看见)
f2:out std_logic_vector(3 downto 0); --第一个随机数(为了波形看见)
f3:out std_logic_vector(3 downto 0); --第一个随机数(为了波形看见)
cat0:out std_logic_vector(7 downto 0));--数码管显示控制
end entity whole;
architecture a of whole is
component div2000 --2000分频器组件声明
port(
clk: in std_logic;
clear: in std_logic;
clk_out:out std_logic);
end component;
component random --随机数组件声明
port (
clk1000:in std_logic;
clk2:in std_logic;
clear:in std_logic;
f1_out:out std_logic_vector(3 downto 0);
f2_out:out std_logic_vector(3 downto 0);
f3_out:out std_logic_vector(3 downto 0);
shu:out std_logic_vector(3 downto 0);
cat:out std_logic_vector(7 downto 0));
end component;
component antisk --防抖电路组件声明
port(clk:in std_logic;
input:in std_logic;
output:out std_logic);
end component;
component seg --译码电路组件声明
port (
a:IN STD_LOGIC_VECTOR(3 DOWNTO 0);
b:OUT STD_LOGIC_VECTOR(6 DOWNTO 0));
END component;
signal clea,cp1000,cp2:std_logic;
signal yi:std_logic_vector(3 downto 0);
begin --电路连接
shu<=yi;
u1:div2000 port map (clk=>clock,clear=>clea,clk_out=>cp2);
u2:antisk port map(clk=>clock,input=>key,output=>clea);
u3:random
port map
(clk1000=>clock,clk2=>cp2,clear=>clea,cat=>cat0,shu=>yi,f1_out=>f1,f2_out=>f2,f3_out=>f3);
u4:seg port map (a=>yi,b=>seg0);
end;
四、仿真波形分析
4.1 2000分频器
图1
图2
图3
图4
仿真波形分析:
如图所示,图1为整体波形,图2为图1的第一个上升沿到来时的放大图,图3是图1的第一个下降沿到来时的放大图,图4是图一的clear复位信号部分的放大图。
由图2和图3可知,每当计数信号tmp从0计数到999时,输出信号就进行一次反转,总体一个周期就是从0计数到1999进行一次反转,即把输入信号进行了2000分频,且占空比为50%。
由图4可知当复位信号出现时,计数信号tmp马上异步清零,重新开始计数。所以,clear为异步复位键。
4.2 防抖电路模块
图1
图2
仿真波形分析:
如图所示,图1为整体仿真波形图,前面较为宽的模拟人手按下按键,后面较为窄的表示机械按键的抖动。图1共表示了按键按动了4次;图2为第一次按键的放大图。
图2,当没有按键时,即input一直是低电平,则计数信号count的值一直是0,当由按键信号时,且持续时间按足够长,即计数信号计数到8时,输出信号output才输出高电平,当计数信号持续时间不够长,即后面产生的毛刺,则输出信号不进行高电平输出。由此,不带有毛刺的输出波形进行了防抖动。
4.3 随机数生成模块
图1
图2
图3
仿真波形分析:
如图所示,图1为整体波形仿真,输出信号随clk2每两秒变一回,送给译码电路的信号shu和控制哪个数码管亮的信号cat变化速度很快,随clk1000进行变化.
图2图1的clk2的第二个上升沿到来时的放大图。由图可知,此时的f1=10,f2=9,f3=0.cat和送给译码电路的shu在f1、f2、f3之间循环切换输出。
图3是图1的复位信号clear到来时的放大图。复位信号到来,此时f0马上转换为0,相应的f1、f2、f3都转换为零。而且转换的时间不是在时钟上升沿到来的时候,是随复位信号出现而进行转变,则可以说明,复位信号是异步复位的。
4.4 译码电路模块
仿真波形分析:
如图所示,当给输入信号a不同的值,则输出信号会有不同的译码输出。b的输出是按照数码管的a、b、c、d、e、f、g进行译码输出。当a的值超过9后,10的译码输出和7一样,11的译码输出和1一样,12的译码输出和4一样,13的译码输出和8一样,14的译码输出和6一样,15的译码输出和0一样。这样,无论前面随机出传进来的数是多少,最后的译码电路总能译出一个数。
4.5 电路综合
图1
图2
仿真波形分析:
如图所示,图1生成的随机信号f1、f2、f3、每两秒变一回,当复位信号key按动时,则f1、f2、f3马上变回0,且能持续两秒,还能说明key是异步信号。
图2为clktmp的第二个上升沿附近的放大图。由图可知,随着clk1000的变化,shu 在f1、f2、f3之间安来回切换,cat0也是与之相对应的切换,告诉变化可以达到迷惑人眼的效果,这样就能最终达到人眼看到的是3个数码管同时亮。
五、故障及问题分析
- 最后电路综合仿真的时候,想要出现的引脚没有。解决方法,最后加上一个输出引脚,这样最后的仿真波形的选项最后就能出现所要选择的。
- 随机数生成电路,最开始设计的时候一按复位键,然后出现的数字都是固定的。要解决这样的问题,可以把计数信号,和给最后的进行运算变换的信号分开,这样即使运算变换的信号变为0,计数信号不是0,这样最后就能达到复位之后,下一个数字不是0的效果。
- 译码的时候要考虑到二进制和十进制之间的区别,把所有的情况都考虑一遍,就是把10~15的情况思考清楚。
六、总结
随机数产生,用电路做出来的最终结果都是伪随机,当时间足够长的时候都会进行循环。文章来源:https://www.toymoban.com/news/detail-475253.html
到由多个时钟信号输入进来的时候,要有清晰的认识,那个时钟是干什么的,否则会产生很多冗余的代码。且一个信号的最后决定它变化的只能有一个,不能同时多个判断,这样编译会不通过。文章来源地址https://www.toymoban.com/news/detail-475253.html
到了这里,关于【数电实验】随机数生成电路的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!