目录
一:实验要求
二:程序源代码
2.1 CLKGEN的VHDL源程序及分析
2.2 REG32B的VHDL源程序及分析
2.3 TESTCTL的VHDL源程序及分析
2.4 FREQ的VHDL源程序及分析
三:硬件实验现象
四:对实验步骤详细分析
4.1 RTL图
4.2 引脚锁定
4.3 TESTCTL波形仿真
4.4 FREQ波形仿真
4.5 测频测试结果
设计并调试好8位十进制数字频率计,并用GW48系列或其他EDA实验开发系统(事先应选定拟采用的实验芯片的型号)进行硬件验证
图1: 实验电路
设计思路:数字频率计数器其实就是对数字秒表的进一步深入,其功能是测出某个频率的大小。
要测出某个频率的大小那就是设定一秒钟周期,周期内测试的频率的脉冲上升沿多少。
频率 = 上升沿脉冲个数 / T 当T等于1s时候,则 频率=上升沿脉冲个数。
为了能够在数码管上显示依旧需要加CTRLS(动态扫描)和DISPLAY(动态显示),而1S的周期哪来的呢,这是可以设定由内部产生或者外部产生,这里我设置为内部产生,通过一个分配器的操作来达到输出的周期时间为1S。
为了能够测量多次频率,那么就需要对前面一次频率进行一个保存,当前面频率保存的时候,计数器不工作,并且给一个清零信号将前一次测频的结果清除。
对于上篇文章一致的代码不再讲述,大家可以进行一个移植操作。
其中CLKGEN分析在前一篇文章有详细说明,这里注意的是我选择的时钟是内部时钟50M,为了产生1s的时钟周期,我需要对其进行5M分频,但是为了能够波形仿真,所以还使用了一个分频常数小的分频器。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY CLKGEN IS
PORT(CLK: IN STD_LOGIC;
NEWCLK: OUT STD_LOGIC);
END ENTITY CLKGEN;
ARCHITECTURE ART OF CLKGEN IS
--SIGNAL CNT: INTEGER RANGE 0 TO 10#49999999#;
SIGNAL CNT: INTEGER RANGE 0 TO 10#1#;
BEGIN
PROCESS(CLK) IS
BEGIN
IF CLK'EVENT AND CLK='1' THEN
--IF CNT=10#49999999# THEN CNT<=0;
IF CNT=10#1# THEN CNT<=0;
ELSE CNT<=CNT+1;
END IF;
END IF;
END PROCESS;
PROCESS(CNT) IS
BEGIN
--IF CNT=10#49999999# THEN NEWCLK<='1';
IF CNT=10#1# THEN NEWCLK<='1';
ELSE
NEWCLK<='0';
END IF;
END PROCESS;
END ARCHITECTURE ART;
锁存器的工作原理就是将前一次测评的结果进行保存,并且传输到动态显示端,由于要将前一次测评结果清零所以锁存器的效果能够防止硬件不稳定的现象。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY REG32B IS
PORT(LOAD:IN STD_LOGIC; --为1时候代表锁存器工作
DIN:IN STD_LOGIC_VECTOR(31 DOWNTO 0); --DIN是计数结果
DOUT:OUT STD_LOGIC_VECTOR(31 DOWNTO 0));
END ENTITY REG32B;
ARCHITECTURE ART OF REG32B IS
BEGIN
PROCESS(LOAD,DIN)IS
BEGIN
IF(LOAD'EVENT AND LOAD='1')THEN
DOUT<=DIN;
END IF;
END PROCESS;
END ARCHITECTURE ART;
由于是多次测评,所以需要对程序进行一个整体的控制,测评控制模块非常重要,控制计数器何时工作,控制锁存器何时工作,对测评结果何时清零。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY TESTCTL IS
--其中clk信号由分配器产生
PORT(CLK: IN STD_LOGIC;
TSTEN: OUT STD_LOGIC; --输出时钟信号,用于控制计数器
CLR_CNT: OUT STD_LOGIC; --清零信号,用于清除计数器数据
LOAD: OUT STD_LOGIC); --用于发送给寄存器用于存储数据,其中电平波形于TSTEN相反
END ENTITY TESTCTL;
ARCHITECTURE ART OF TESTCTL IS
SIGNAL DIV2CLK : STD_LOGIC; --2分频时钟信号
BEGIN
PROCESS(CLK) IS
BEGIN
IF CLK'EVENT AND CLK='1' THEN
DIV2CLK<= NOT DIV2CLK; --进行一个翻转
END IF;
END PROCESS;
PROCESS(CLK,DIV2CLK) IS
BEGIN
IF CLK='0'AND DIV2CLK='0' THEN
CLR_CNT<='1';
ELSE CLR_CNT <='0';
END IF;
END PROCESS;
LOAD<=NOT DIV2CLK;
TSTEN <= DIV2CLK;
END ARCHITECTURE ART;
这是数字频率计的顶层文件,利用元件例化语句,将各模块进行一个连接。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL; --六号口为被测频率口,8号口为动态扫描的端口
ENTITY FREQ IS
PORT(FSIN:IN STD_LOGIC;
CLK:IN STD_LOGIC;
CLK2:IN STD_LOGIC;
DOUT:BUFFER STD_LOGIC_VECTOR(31 DOWNTO 0);
COM:OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
SEG:OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END ENTITY FREQ;
ARCHITECTURE ART OF FREQ IS
COMPONENT CNT10 IS
PORT(CLK:IN STD_LOGIC;
CLR:IN STD_LOGIC;
ENA:IN STD_LOGIC;
CQ:OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
CO:OUT STD_LOGIC);
END COMPONENT CNT10;
COMPONENT REG32B IS
PORT(LOAD:IN STD_LOGIC;
DIN:IN STD_LOGIC_VECTOR(31 DOWNTO 0);
DOUT:OUT STD_LOGIC_VECTOR(31 DOWNTO 0));
END COMPONENT REG32B;
COMPONENT TESTCTL IS
PORT(CLK:IN STD_LOGIC;
TSTEN:OUT STD_LOGIC;
CLR_CNT:OUT STD_LOGIC;
LOAD:OUT STD_LOGIC);
END COMPONENT TESTCTL;
COMPONENT CLKGEN IS
PORT(CLK: IN STD_LOGIC;
NEWCLK: OUT STD_LOGIC);
END COMPONENT CLKGEN;
COMPONENT CTRLS IS
PORT(CLK:IN STD_LOGIC;
SEL:OUT STD_LOGIC_VECTOR(2 DOWNTO 0));
END COMPONENT CTRLS;
COMPONENT DISPLAY IS
PORT(SEL:IN STD_LOGIC_VECTOR(2 DOWNTO 0);
DATAIN:IN STD_LOGIC_VECTOR(31 DOWNTO 0);
COM:OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
SEG:OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END COMPONENT DISPLAY;
SIGNAL SD:STD_LOGIC_VECTOR(31 DOWNTO 0);
--SIGNAL DOUT:STD_LOGIC_VECTOR(31 DOWNTO 0);
SIGNAL S0,S1,S2,S3,S4,S5,S6,S7,S8,SC,SE,SL:STD_LOGIC;
SIGNAL S9:STD_LOGIC_VECTOR(2 DOWNTO 0);
BEGIN
U0:CLKGEN PORT MAP(CLK=>CLK,NEWCLK=>S0);
U1:TESTCTL PORT MAP(CLK=>S0,TSTEN=>SE,CLR_CNT=>SC,LOAD=>SL);
U2:CNT10 PORT MAP(FSIN,SC,SE,SD(3 DOWNTO 0),S1);
U3:CNT10 PORT MAP(S1,SC,SE,SD(7 DOWNTO 4),S2);
U4:CNT10 PORT MAP(S2,SC,SE,SD(11 DOWNTO 8),S3);
U5:CNT10 PORT MAP(S3,SC,SE,SD(15 DOWNTO 12),S4);
U6:CNT10 PORT MAP(S4,SC,SE,SD(19 DOWNTO 16),S5);
U7:CNT10 PORT MAP(S5,SC,SE,SD(23 DOWNTO 20),S6);
U8:CNT10 PORT MAP(S6,SC,SE,SD(27 DOWNTO 24),S7);
U9:CNT10 PORT MAP(S7,SC,SE,SD(31 DOWNTO 28),S8);
U10:REG32B PORT MAP(SL,SD(31 DOWNTO 0),DOUT);
U11:CTRLS PORT MAP(CLK2,S9);
U12:DISPLAY PORT MAP(S9,DOUT,COM,SEG);
END ARCHITECTURE ART;
测频器硬件现象
从图中可以看到整体的模块连接,和设计的原理图相一致,并且大家仔细观察:其中的线条粗细是不一样的,对于信号线和一般的连接线相比是粗一些,其中的原理应该是信号传输的特性。
对于数码管的显示端和驱动和第一篇DTCNT9999设置一致,具体分析在第一篇文章
其中不同的是,我使用了内部时钟PIN_T1。将测频的引脚设置为6号引脚,8号引脚为动态扫描端口,本实验不需要使用按键。
可以看出,TSTEN和LOAD的波形是相反的,由于计数器在工作的时候锁存器并不工作,而计数器不工作的时候,LOAD为1代表锁存器开始工作,也可以看到CLR清零信号在TSTEN和CLK为0的时候来到一个上朓沿,代表进行清零,其中CLK有部分时间的延迟证明了信号的延迟特性。
为了能够让波形能够显示出来,除了将DOUT设为可读之外,还需要将分频常数减小,为了达到测评的效果,将测试频率FSIN设置为俩种不同的频率,通过GOUT得出被测频率的大小,其中COM为数码管的公共端,依次动态点亮,其中DOUT的数值对应SEG中数码管的八段管显示。
可以看出测试结果与被测频率之间有一定的误差,其主要原因是硬件存在信号的传输,所以有一定的延迟特性。
最后:如果需要人数较多,我会对项目进行一个开源,如果对你有用,请给一个点赞,多谢!