用verilog语言编写的4位秒表实现

用verilog语言编写的4位秒表实现,第1张

3 六、PCB图七、系统软件设计 在设计电路时,要遵循从上到下的设计原则。首先从系统设计入手,在顶层进行功能划分和结构设计,顶层模块核拍的每个层次模块均可完成一个较为独立的功能,次模块在调试成功后可生成一个默认符号,以供上一层模块调用。本系统由4个模块组成,分别是分频电路模块、模10计数模块和动态译码显示模块。本设计最小计时单位为0.1s,设计时需获得一个比较精确的10Hz(周期为0.1s)的计时脉冲。由于最终的设计结果要下载到可编程逻辑器件中测试,因此可利用Altera DE2开发板的12M晶振时钟。将12M时钟信号CLK送到分频器CLKGEN进行60万分频后,得到10Hz的频率由NEWCLK输出。采用Verilog语言编程,编译无误通过后创建默认文件符号CLKGEN以供上层电路调用。程序实现如下: module clock(clk,key,dig,seg)//模块名clock input clk//输入时钟 input[1:0] key//输入按键 output[7:0] dig//数码管选择输出引脚 output[7:0] seg//数码管段输出引脚 reg[7:0] seg_r//定义数码管输出寄存器 reg[7:0] dig_r//定义数码管选择输出寄存器 reg[3:0] disp_dat//定义显示数据寄存器 reg[24:0]count//定义计数寄存器裂让 reg[15:0]hour//定义现在时刻寄存器 图二、数字秒表PCB图4 reg sec,keyen //定义标志位 reg[1:0]dout1,dout2,dout3//寄存器 wire[1:0]key_done//按键消抖输出 assign dig = dig_r//输出数码管选择 assign seg = seg_r //输出数码管译码结果 //秒信号产生部分 always @(posedge clk) //定义clock上升沿触发 begin count = count + 1'b1if(count == 25'd6000000) //0.5S到了吗? begin count = 25'd0//计数器清零 sec = ~sec //置位秒标志 end end //按键消抖处理部分 assign key_done = (dout1 | dout2 | dout3)//按键消抖输出 always @(posedge count[17]) begin dout1 <= keydout2 <= dout1dout3 <= dout2end always @(negedge key_done[0]) begin keyen = ~keyen//将琴键开关转换为乒乓开关 end //数码管动态扫描显示部分 always @(posedge clk) //count[17:15]大约1ms改变一次 begin case(count[17:15]) //选择扫描显示数据 3'd0:disp_dat = hour[3:0]//秒个位 3'd1:disp_dat = hour[7:4]//秒十位 3'd2:disp_dat = hour[11:8]//分个位 3'd3:disp_dat = hour[15:12]//分十位 endcase case(count[17:15]) //选择数码管显示位5 3'd0:dig_r = 8'b11111110//选择第一个数码管显示 3'd1:dig_r = 8'b11111101//选择第二个数码管显示 3'd2:dig_r = 8'b11111011//选择第三个数码管显示 3'd3:dig_r = 8'b11110111//选择第四个数码管显示 endcase end always @(posedge clk) begin case(disp_dat) 4'h0:seg_r = 8'hc0//显示0 4'h1:seg_r = 8'hf9//显示1 4'h2:seg_r = 8'ha4//显示2 4'h3:seg_r = 8'hb0//显示3 4'h4:seg_r = 8'h99//显示4 4'h5:seg_r = 8'h92/改源羡/显示5 4'h6:seg_r = 8'h82//显示6 4'h7:seg_r = 8'hf8//显示7 4'h8:seg_r = 8'h80//显示8 4'h9:seg_r = 8'h90//显示9 //4'ha:seg_r = 8'hbf//显示- default:seg_r = 8'hff//不显示 endcase //if((count[17:15]== 3'd2)&sec) //seg_r = 8'hffend //计时处理部分 always @(negedge sec or negedge key_done[1])//计时处理 begin if(!key_done[1]) //是清零键吗? begin hour = 16'h0//是,则清零 end else if(!keyen) begin hour[3:0] = hour[3:0] + 1'b1//秒加1 if(hour[3:0] == 4'ha) begin hour[3:0] = 4'h0hour[7:4] = hour[7:4] + 1'b1//秒的十位加一 if(hour[7:4] == 4'h6) begin 6 hour[7:4] = 4'h0hour[11:8] = hour[11:8] + 1'b1//分个位加一 if(hour[11:8] == 4'ha) begin hour[11:8] = 4'h0hour[15:12] = hour[15:12] + 1'b1//分十位加一 if(hour[15:12] == 4'h6) hour[15:12] = 4'h0end end end end end endmodule 在QuartusII环境下,打开一个新的原理图编辑窗口,然后调入秒表电路设计所需要的50万分频器CLKGEN、十进制计数器/分频器CNT10(4片),译码器DISP,以及电路需要的输入/输出元件。完成电路元件之间和输出/输入之间的连接,并通过QuartusII的编译 八、焊接调试 电路板组装心得: 收集资料,设计出电路原理图,选择元件型号,清点元器件的个数。测试元件,包括测电阻的阻值,根据电路图和电路板本身的实际连通情况开始整体布局连接电路。 电路板焊接心得: 在设计过程中,应该了解其难易,考虑一下焊接的难度。如果比较难就要追求速度(但是也要尽量焊好),如果简单一点,那么在焊接的同时要考虑到焊接工艺。一般情况下,工艺方面的要求就是焊点的光滑、亮度、毛刺这几个方面。一般不会要求电阻的方向之类的。焊接的方式:焊接前看一下元器件,了解一下它们的尺寸规格。然后从低到高开始焊接。 电路板调试心得: 首先,在上电源前先用万用表测试下电源和地之间是否有短路,这样可防止可能烧坏IC等元件。其次,测试电路板的各项功能,须从极端的角度去测试可能会出现的问题。再次,根据产品的性能要求,逐次测试其各个功能是否符合产品要求。最后,调试过程中会遇到各种问题,下面一一分析:第一,电源连接不上,就要查查电源连接电路。第二,电源连接上了,却不能工作,查其他电源是不是供电正常,然后查晶振是否工作。第三,还是工作不正常,目测下主要元件是否有焊反、焊错、短路等现象出现。包括元件用错了,型号不对,元件方向反了,元件的脚有损坏、虚焊、短路等,连接线有损坏或接触不良,电容的正负极焊反等。第四,加密IC焊错了,或没有加载相应的程序。 九、性能指标测试 首先,按照性能指标,测试每项功能是否达到,记录实际测试结果,分析误差、误差原因,以及解决办法。严格按照测试步骤:首先认真调查测试需求和仔细分析测试任务,然后 一、设计要求 用 verilong 语言编写程序,结合实际电路,设计一个 4 位 LED 数码显示 “ 秒表 ” ,显示 时间为 99.9~00.0 秒, 每秒自动减一, 精度为 0.1 。 另设计一个 “ 开始 ” 按键和一个 “ 复位 ” 按键。 再增加一个 “ 暂停 ” 按键。 按键说明:按 “ 开始 ” 按键,开始计数,数码管显示从 99.9 开始每秒自动减一;按 “ 复位 ” 按键, 系统复位, 数码管显示 99.9 ; 按 “ 暂停 ” 按键, 系统暂停计数, 数码管显示当时的计数。 二、设计目的 1 、 通过本次课程设计加深对 verilong 语言课程的全面认识、 复习和掌握, 对 EPM7064 芯片的应用达到进一步的了解。 2 、 掌握定时器、外部中断的设置和编程原理。 3 、 通过此次课程设计能够将软硬件结合起来,对程序进行编辑, 调试。使其能够通过 电脑下载到芯片,正常工作。 4 、实际 *** 作 Quartus II 软件,复习巩固以前所学知识。三、总体设计 本秒表系统具有复位、 暂停、 秒表计时等功能。 clk 为系统工作时钟, 采用 Altera DE2 上的 50M 时钟信号,经过分频器产生秒表计时周期为 0.01s 的时钟,再经过计数器,分别 对秒表的百分位、 十分位、秒、秒十位、 分、 分十位进行计数。 onoff 为启动 / 暂停控制信号, 当它为 0 时,启动计时,当它为 1 时,计时暂停。 clr 为复位信号,当该信号有效时,计数 器和译码清零,此时数码管显示输出为 00 : 00 : 00 。在总体电路图中,根据设计要求,需 要两个输入控制信号 onoff 和 clr 。由于开发板上除了拨动开关就是瞬时的按键开关 , 且按键 开关平时都呈高电平 , 按一下为低电平。 故在实际测试时采用了拨动开关 SW0 来控制秒表的 启动 / 暂停,通过 KEY0 来控制秒表的清零。 四、设计思路描述 该实验要求进行计时并在数码管上显示时间, 通过相关软件 Quartus II 编译, 利用 JTAG 下载电路到核心芯片,驱动硬件工作 。 Altera_EPM7064(84PIN) 有四个引脚 GCLK1(83 脚 ),GCLRn(1 脚 ),OE1(84 脚 ),OE2(2 脚 ) 。 GCLK1 是全局时钟, GCLRn(1 脚是全局清零, OE1(84 脚 ),OE2(2 脚 ) 是全局使能实现 “ 开始 ” 按键的功能; 实现 “ 清零 (复位) ” 按键的功能;做为时 钟信号 CLK 输入的入口地址。 可将开关设计与此, 其优势在在于到达延迟时间相等。 其中 “ 开 始 ” 按键当开关由 1 拨向 0 (由上向下拨)时开始计时; “ 清零(复位) ” 按键当开关由 1 拨 向 0 (由上向下拨)时数码管清零(复位) ,此时若再拨 “ 开始 ” 按键则又可重新开始计时。 1) 电源部分需要并联四个电容,以达到滤波作用,获得实验所需的电压; 2) 利用三极管分别连接 LED 数码管和 EPM7064, 起到放大(电流)作用; 3) 本实验时钟信号的产生有晶振直接提供,同时由编写的子程序决定输出频率; 4) 芯片所需程序由计算机编译,采用 Quartus II 软件,编译调试无误后,进行下载; 5 ) IDI 、 TMS 、 TCK 、 TDO 是 JTAG 的标准线。用来实现连接芯片,实现下载功能。 五、原理图 http://download.csdn.net/detail/elia2008/686695

(1)先做一个消抖,存到圆贺文件debounce.vhd

library IEEE

use IEEE.std_logic_1164.all

use IEEE.std_logic_arith.all

use IEEE.std_logic_unsigned.all

entity debounce is

generic (

CLK_FREQ_MHz : integer := 20--in MHz

BUTTON_PRESS_STATUS : std_logic := '0'

)

port (

reset_n : in std_logic

clk : in std_logic

btnIn : in std_logic

btnPressed: out std_logic

)

end debounce

architecture debounce_arch of debounce is

constant MAX_MS_CNT : integer := CLK_FREQ_MHz * 1000 - 1

signal msCnt: integer range 0 to MAX_MS_CNT

signal msClk: std_logic --做一个毫秒脉冲,每1毫秒对按钮采样一次

signal btnIn_q: std_logic_vector(9 downto 0) --记住最后10次采样

signal btn : std_logic

signal btn_q: std_logic

begin

--产生毫秒脉冲

process(reset_n, clk)

begin

if reset_n = '0' then

msCnt <= 0

msClk <= '0'

elsif rising_edge(clk) then

if msCnt >= MAX_MS_CNT then

msCnt <= 0

msClk <= '1'

else

msCnt <= msCnt + 1

msClk <= '0'

end if

end if

end process

--记住最后10次采样

process(reset_n, clk)

begin

if reset_n = '0' then

btnIn_q <= (others =>not BUTTON_PRESS_STATUS)

elsif rising_edge(clk) then

if msClk = '1' then

btnIn_q <= btnIn_q(btnIn_q'left-1 downto 0) &btnIn

else

btnIn_q <= btnIn_q

end if

end if

end process

process(reset_n, clk)

variable all_samples_are_pressed : std_logic_vector(btnIn_q'left downto 0) := (others =>BUTTON_PRESS_STATUS)

begin

if reset_n = '0' then

btn <= '0'

btn_q <= '0'

elsif rising_edge(clk) then

if btnIn_q = all_samples_are_pressed then

btn <= '1' --最后10次采样都是按下状态,就确认按钮按下(10ms消抖)

elsif btnIn_q = not all_samples_are_pressed then

btn <橘唯派= '0' --最后10次采样都是抬起状态,就确认按钮抬起(10ms消抖)

else

btn <= btn --否则保持不变

end if

btn_q <山行= btn

end if

end process

btnPressed <= '1' when btn = '1' and btn_q = '0' else '0' --按钮按下上升沿检测

end debounce_arch

(2)做一个加法器,存到文件adder.vhd

library IEEE

use IEEE.std_logic_1164.all

use IEEE.std_logic_arith.all

use IEEE.std_logic_unsigned.all

entity adder is

port (

reset_n : in std_logic

clk : in std_logic

adderEn : in std_logic

data : out std_logic_vector(3 downto 0)

dataValid: out std_logic

)

end adder

architecture adder_arch of adder is

signal cnt : std_logic_vector(3 downto 0)

begin

process(reset_n, clk)

begin

if reset_n = '0' then

cnt <= x"0"

dataValid <= '0'

elsif rising_edge(clk) then

if adderEn = '1' then--将被替换成,按钮按下时,计数+1

if cnt >= x"9" then

cnt <= x"0"

else

cnt <= cnt + 1

end if

dataValid <= '1'

else

cnt <= cnt

dataValid <= '0'

end if

end if

end process

data <= cnt

end adder_arch

(3)做7段数码管显示,存到文件SevenSegment.vhd

library IEEE

use IEEE.std_logic_1164.all

use IEEE.std_logic_arith.all

use IEEE.std_logic_unsigned.all

entity SevenSegment is

generic (

LED_ON : std_logic := '0'

)

port (

reset_n : in std_logic

clk : in std_logic

data : in std_logic_vector(3 downto 0)

dataValid: in std_logic

ledOut : out std_logic_vector(6 downto 0)

)

end SevenSegment

architecture SevenSegment_arch of SevenSegment is

constant LED_OFF : std_logic := not LED_ON

signal led : std_logic_vector(6 downto 0)

begin

-- --a--

-- |f|b

-- --g--

-- |e|c

-- --d--

process(reset_n, clk)

begin

if reset_n = '0' then

led <= LED_ON &LED_ON &LED_ON &LED_ON &LED_ON &LED_ON &LED_OFF--display 0

elsif rising_edge(clk) then

if dataValid = '1' then

case data is --a b c d e f g

when x"0" =>

led <= LED_ON &LED_ON &LED_ON &LED_ON &LED_ON &LED_ON &LED_OFF--display 0

when x"1" =>

led <= LED_OFF &LED_ON &LED_ON &LED_OFF &LED_OFF &LED_OFF &LED_OFF--display 1

when x"2" =>

led <= LED_ON &LED_ON &LED_OFF &LED_ON &LED_ON &LED_OFF &LED_ON --display 2

when x"3" =>

led <= LED_ON &LED_ON &LED_ON &LED_ON &LED_OFF &LED_OFF &LED_ON --display 3

when x"4" =>

led <= LED_OFF &LED_ON &LED_ON &LED_OFF &LED_OFF &LED_ON &LED_ON --display 4

when x"5" =>

led <= LED_ON &LED_OFF &LED_ON &LED_ON &LED_OFF &LED_ON &LED_ON --display 5

when x"6" =>

led <= LED_ON &LED_OFF &LED_ON &LED_ON &LED_ON &LED_ON &LED_ON --display 6

when x"7" =>

led <= LED_ON &LED_ON &LED_ON &LED_OFF &LED_OFF &LED_OFF &LED_OFF--display 7

when x"8" =>

led <= LED_ON &LED_ON &LED_ON &LED_ON &LED_ON &LED_ON &LED_ON --display 8

when x"9" =>

led <= LED_ON &LED_ON &LED_ON &LED_ON &LED_OFF &LED_ON &LED_ON --display 9

when others =>

led <= (others =>LED_OFF)

end case

else

led <= led

end if

end if

end process

ledOut <= led

end SevenSegment_arch

(4)最后,综合到一起,存到文件top.vhd

library IEEE

use IEEE.std_logic_1164.all

use IEEE.std_logic_arith.all

use IEEE.std_logic_unsigned.all

entity top is

generic (

CLK_FREQ_MHz : integer := 20--可以修改成你的系统时钟频率,以MHz为单位

BUTTON_PRESS_STATUS : std_logic := '0' --指定按钮按下时,是逻辑0还是1

LED_ON : std_logic := '0'--指定数码管点亮需要输出0还是1

)

port (

reset_n : in std_logic

clk : in std_logic

btnIn : in std_logic

ledOut : out std_logic_vector(6 downto 0)

)

end top

architecture top_arch of top is

component debounce

generic (

CLK_FREQ_MHz : integer := 20--in MHz

BUTTON_PRESS_STATUS : std_logic := '0'

)

port (

reset_n : in std_logic

clk : in std_logic

btnIn : in std_logic

btnPressed: out std_logic

)

end component

component adder

port (

reset_n : in std_logic

clk : in std_logic

adderEn : in std_logic

data : out std_logic_vector(3 downto 0)

dataValid: out std_logic

)

end component

component SevenSegment

generic (

LED_ON : std_logic := '0'

)

port (

reset_n : in std_logic

clk : in std_logic

data : in std_logic_vector(3 downto 0)

dataValid: in std_logic

ledOut : out std_logic_vector(6 downto 0)

)

end component

signal btnPressed : std_logic

signal data : std_logic_vector(3 downto 0)

signal dataValid : std_logic

begin

debounce_inst : debounce

generic map (

CLK_FREQ_MHz =>CLK_FREQ_MHz, --in MHz

BUTTON_PRESS_STATUS =>BUTTON_PRESS_STATUS

)

port map(

reset_n =>reset_n,

clk =>clk,

btnIn =>btnIn,

btnPressed=>btnPressed

)

addr_inst : adder

port map (

reset_n =>reset_n,

clk =>clk,

adderEn =>btnPressed,

data =>data,

dataValid=>dataValid

)

SevenSegment_inst : SevenSegment

generic map (

LED_ON =>LED_ON

)

port map (

reset_n =>reset_n,

clk =>clk,

data =>data,

dataValid=>dataValid,

ledOut =>ledOut

)

end top_arch

(5)你只要修改top.vhd里generic的定义,设定时钟频率、按钮按下状态和数码管点亮状态即可

想加的话可以加的,我目前在用8.0都,用哪个都无所谓啊,相比还老旁是7.2更好用吧,个人认为的,quartus的仿弯碧真软件是自带的,建立一个仿真文件就可以了 点击开始 新建一个vector waveform file 文件 加载波形就好了 然后不要忘记生成网表文件 在编译就好了 书上的讲解都很详细的。

闹钟模块很好写的,就是在计数的基础上,记到某个数值输出标志位,控制灯亮或者播放音乐都可以,如果是按键去抖的话 就是都到输入的1后,延迟一个时钟周期,就可以了,如果是按键的输入引脚为pin的话

if clk'event and clk = '1' then----这段是很常用的D触发器的写侍闹橡法 其实就是pin_yan<=pin

if pin = '1' then

pin_yan<='1'

else

pin_yan<='0'

end if

end if

主要是利用D出发器,当时钟上升沿捕捉到‘1’后,将该信号延迟了一个时钟周期,在下一个时钟周期变为‘0’。具体的是

if ret = '1' then ----复位

pin_yan <='0'

elsif clk'event and clk = '1' then

if pin_yan = '0' then

if pin = '1' then

pin_yan<='1' ---经过去抖后的按键信号

else

pin_yan<='0'

end if

end if

if pin_yan = '1' then -------使得该信号为一个周期的信号

pin_yan<='0'

end if

end if

这样就该能够更好的去抖吧


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12523683.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-26
下一篇 2023-05-26

发表评论

登录后才能评论

评论列表(0条)

保存