基于FPGA的简易数字频率计+上板测试(小梅哥AC620FPGA开发板

  • 目录
    • 主要架构
    • 1.计数模块
    • 2.数码显示模块
    • 3.控制信号模块
    • 4.分频模块
    • 例化模块
    • 上板测试图
    • 附:74HC595移位寄存器解析(图片)

目录

主要架构

数字频率计的原理很简单,就是计算每秒钟内待测信号的脉冲个数,按照分模块设计的思想,分为:1.计数模块,2.数码管显示模块,3.控制信号模块,4.分频模块。

1.计数模块

计数器用BCD计数器,根据测量频率最大为50M,设计出计数器电路由8个4位BCD计数器级联实现。

2.数码显示模块

BCD计数器的输出值为4位BCD码,经过显示译码电路送至数码管,显示译码电路通过查找表LUT设计方法实现;8位数码管同时显示8个不同的值需要通过16个IO(8位位选,8位段选)动态扫描显示,扫描间隔为1ms,AC620实验板上为了节省IO,通过两片74HC595(串行移位寄存器,可上网查看数据手册)实现串并转换,将16位串行数据转换为16位并行数据,所以采用三个IO口(工作频率SCK,存储频率RCK,数据线DIO)就可以实现数码管动态扫描显示,查阅74HC595数据手册可知,3.3V电压时工作频率SCK为1.25M。

BCD计数器代码:

module BCDcounter(clk,rst_n,en,cin,cout,q);input clk;  //待测信号input rst_n; //复位信号input en;  //使能信号input cin;  //进位输入output reg cout; //进位输出output [3:0]q; //BCD码输出reg [3:0]cnt; //四位计数器//计数器模块(对cin计数,计到9的时候清零)always@(posedge clk,negedge rst_n)if(!rst_n)cnt <= 4'd0;else if(en)beginif(cin == 1'b1)beginif(cnt == 4'd9)cnt <= 4'd0;elsecnt <= cnt + 1'b1;endelsecnt <= cnt;end//产生进位信号always@(posedge clk,negedge rst_n)if(!rst_n)cout <= 1'b0;else if(en)beginif(cin == 1'b1 && cnt == 4'd8)cout <= 1'b1;elsecout <= 1'b0;end//BCD计数器输出assign q = cnt;
endmodule

74HC595驱动代码:

module HC595driver(clk,rst_n,en,seg,sel,sck,rck,si);input clk;   //系统时钟信号input rst_n;  //复位信号input en;   //使能信号input [7:0]seg; //数据输入input [7:0]sel; //数据输入output reg sck;   //移位寄存器控制脉冲output reg rck;   //输出寄存器控制脉冲output reg si;   //串行数据输出parameter CNT_MAX = 4;  //HC595工作频率,50M时钟分频数reg [15:0] divider_cnt;  //分频计数器reg [4:0]SCK_edge_cnt;  //四位计数器//分频计数器模块always@(posedge clk,negedge rst_n)if(!rst_n)divider_cnt <= 16'd0;else if(divider_cnt == CNT_MAX)divider_cnt <= 16'd0;elsedivider_cnt <= divider_cnt + 1'b1;//对clk进行4分频,输出为sck_plusewire sck_pluse;assign sck_pluse = (divider_cnt == CNT_MAX);//对sck_pluse进行计数,用于查找表实现数据的串行输入以及移位时钟sck与存储时钟rck的产生always@(posedge clk,negedge rst_n)if(!rst_n)SCK_edge_cnt <= 5'd0;else if(sck_pluse)beginif(SCK_edge_cnt == 5'd31)SCK_edge_cnt <= 5'd0;elseSCK_edge_cnt <= SCK_edge_cnt + 1'b1;endelseSCK_edge_cnt <= SCK_edge_cnt;//利用查找表产生sck,rck,si脉冲,将16位数据从最高位至最低位送入并输出always@(posedge clk,negedge rst_n)if(!rst_n)beginsck <= 1'b0;rck <= 1'b0;si  <= 1'b0;endelse begincase(SCK_edge_cnt)5'd0:begin sck <= 1'b0;rck <= 1'b1;si <= seg[7];  end5'd1:begin sck <= 1'b1;rck <= 1'b0;      end5'd2:begin sck <= 1'b0;si <= seg[6];      end5'd3:begin sck <= 1'b1;            end5'd4:begin sck <= 1'b0;si <= seg[5];        end5'd5:begin sck <= 1'b1;            end5'd6:begin sck <= 1'b0;si <= seg[4];        end5'd7:begin sck <= 1'b1;          end5'd8:begin sck <= 1'b0;si <= seg[3];        end5'd9:begin sck <= 1'b1;            end5'd10:begin sck <= 1'b0;si <= seg[2];        end5'd11:begin sck <= 1'b1;            end5'd12:begin sck <= 1'b0;si <= seg[1];        end5'd13:begin sck <= 1'b1;           end5'd14:begin sck <= 1'b0;si <= seg[0];        end5'd15:begin sck <= 1'b1;          end5'd16:begin sck <= 1'b0;si <= sel[7];        end5'd17:begin sck <= 1'b1;            end5'd18:begin sck <= 1'b0;si <= sel[6];        end5'd19:begin sck <= 1'b1;            end5'd20:begin sck <= 1'b0;si <= sel[5];        end5'd21:begin sck <= 1'b1;          //送入数据end5'd22:begin sck <= 1'b0;si <= sel[4];        end5'd23:begin sck <= 1'b1;            end5'd24:begin sck <= 1'b0;si <= sel[3];        end5'd25:begin sck <= 1'b1;            end5'd26:begin sck <= 1'b0;si <= sel[2];        end5'd27:begin sck <= 1'b1;            end5'd28:begin sck <= 1'b0;si <= sel[1];        end5'd29:begin sck <= 1'b1;          end5'd30:begin sck <= 1'b0;si <= sel[0];      end5'd31:beginsck <= 1'b1;          endendcaseend
endmodule

8位数码管显示代码:

module HEX8(clk,rst_n,en,disp_data,sel,seg);input clk;     //系统时钟信号50Minput rst_n;    //复位信号input en;     //数码管显示使能信号 1使能,0关闭input [31:0]disp_data; //8位数码管待显示的数据output [7:0]sel;   //位选输出output reg[7:0]seg;   //段选输出reg [15:0]divider_cnt;reg clk_1k;reg [7:0]sel_r;reg [3:0]data_tmp;//分频器计数器模块always@(posedge clk,negedge rst_n)if(!rst_n)divider_cnt <= 15'd0;else if(!en)divider_cnt <= 15'd0;else if(divider_cnt == 24999)divider_cnt <= 15'd0;elsedivider_cnt <= divider_cnt + 1'b1;//利用分频器产生1khz时钟  always@(posedge clk,negedge rst_n)if(!rst_n)clk_1k <= 1'b0;else if(!en)clk_1k <= 1'b0;else if(divider_cnt == 24999)clk_1k <= ~clk_1k;else clk_1k <= clk_1k;//8位循环移位寄存器模块always@(posedge clk_1k,negedge rst_n)if(!rst_n)sel_r <= 8'b0000_0001;else if(sel_r == 8'b1000_0000)sel_r <= 8'b0000_0001;elsesel_r <= sel_r << 1;//8路数据选择器模块,选择数码管段选数据always@(*)case(sel_r)8'b0000_0001: data_tmp = disp_data[3:0];8'b0000_0010: data_tmp = disp_data[7:4];8'b0000_0100: data_tmp = disp_data[11:8];8'b0000_1000: data_tmp = disp_data[15:12];8'b0001_0000: data_tmp = disp_data[19:16];8'b0010_0000: data_tmp = disp_data[23:20];8'b0100_0000: data_tmp = disp_data[27:24];8'b1000_0000: data_tmp = disp_data[31:28];default:   data_tmp = 4'b0000;endcase//数码管显示译码器模块(LUT查找表)always@(*)case(data_tmp)4'h0: seg = 8'b1100_0000;4'h1: seg = 8'b1111_1001;4'h2: seg = 8'b1010_0100;4'h3: seg = 8'b1011_0000;4'h4: seg = 8'b1001_1001;4'h5: seg = 8'b1001_0010;4'h6: seg = 8'b1000_0010;4'h7: seg = 8'b1111_1000;4'h8: seg = 8'b1000_0000;4'h9: seg = 8'b1001_0000;4'ha: seg = 8'b1000_1000;4'hb: seg = 8'b1000_0011;4'hc: seg = 8'b1100_0110;4'hd: seg = 8'b1010_0001;4'he: seg = 8'b1000_0110;4'hf: seg = 8'b1000_1110;endcase//二选一数据选择器,位选输出assign sel = en?sel_r:8'b0000_0000;endmodule

3.控制信号模块

(1)待测信号控制脉冲 —— 产生高电平时长为1s的门控信号,和待测信号经过与门;起到控制待测脉冲到达计数器的作用
(2)锁存信号控制脉冲 —— 计数器在门控信号为低电平时需要清零,以便下次计数,数码管上显示的数据需要保持,通过设计一个32位锁存器实现;在门控信号高脉冲结束时将数据送至锁存器供数码管显示
(3)计数器复位脉冲 —— 将计数结果送至锁存器后,需要将计数器清零

信号产生代码:

module signal(clk,rst_n,signal_10hz,signal_25khz,signal_50mhz,led_test);input clk;      //系统时钟input rst_n;     //系统复位信号output reg signal_10hz;  //10hz测试信号output reg signal_25khz; //25khz测试信号output reg signal_50mhz; //50M测试信号output reg led_test;   //信号输出指示灯reg [21:0]cnt;reg [9:0]cnt2;//计数器模块always@(posedge clk,negedge rst_n)if(!rst_n)cnt <= 22'd0;else if(cnt == 22'd2499999)cnt <= 22'd0;elsecnt <= cnt + 1'b1;//利用计数器模块产生10hz脉冲always@(posedge clk,negedge rst_n)if(!rst_n)signal_10hz <= 1'b0;else if(cnt == 22'd2499999)signal_10hz <= ~signal_10hz;else signal_10hz <= signal_10hz;always@(*)led_test <= signal_10hz; //信号输出指示灯//计数器模块always@(posedge clk,negedge rst_n)if(!rst_n)cnt2 <= 10'd0;else if(cnt2 == 10'd999)  cnt2 <= 10'd0;elsecnt2 <= cnt2 + 1'b1;//利用计数器模块产生25khz脉冲always@(posedge clk,negedge rst_n)if(!rst_n)signal_25khz <= 1'b0;else if(cnt2 == 10'd999)signal_25khz <= ~signal_25khz;else signal_25khz <= signal_25khz;always@(*)  signal_50mhz <= clk;
endmodule

4.分频模块

系统需要0.5hz的门控信号,1hz的脉冲信号,利用分频器将50M系统时钟分频得到

module console(clk,rst_n,clk_1hz,en_cnt,load,rst_cnt);input clk;   //系统时钟50Minput rst_n;  //系统复位信号output reg clk_1hz; //输出到clk_1hz引脚output reg en_cnt; //输出到en_cnt引脚output reg load;  //输出到load引脚output rst_cnt; //输出到rst_cnt引脚
//clk_1hz以1hz的频率闪烁,也就是每500ms翻转一次;时钟周期是20ns,所以应该计数25_000_000次;需要一个25位的寄存器reg [24:0]cnt;//计数器模块always@(posedge clk,negedge rst_n)if(!rst_n)cnt <= 25'd0;else if(cnt == 25'd24_999_999)  //进行仿真的时候可以用24_999;只是功能仿真cnt <= 25'd0;elsecnt <= cnt + 1'b1;
//利用计数器模块产生1hz脉冲always@(posedge clk,negedge rst_n)if(!rst_n)clk_1hz <= 1'b0;else if(cnt == 25'd24_999_999)clk_1hz <= ~clk_1hz;else clk_1hz <= clk_1hz;//产生en_cnt信号always@(posedge clk_1hz,negedge rst_n)if(!rst_n)en_cnt <= 1'b0;else en_cnt <= ~en_cnt;//产生load信号always@(*)load <= ~en_cnt;//产生rst_load信号assign rst_cnt = (clk_1hz || en_cnt);
endmodule

例化模块

module digital_frequency_meter(clk,rst_n,fin,sck,rck,si,led1,led2,signal_10hz,signal_25khz,signal_50mhz);
wire en_cnt;     //计数器使能信号(0.5hz 高电平时长为1s)wire load;      //锁存信号(控制计数器数据输出到数码管)wire rst_cnt;     //BCD计数器清零信号wire [31:0]data_temp;  //计数器与数码管待显示数据的中间变量reg [31:0]data_lock;   //32位锁存寄存器(锁存数码管待显示数据)//例化信号产生模块signal signal(.clk(clk),.rst_n(rst_n),.signal_10hz(signal_10hz),.signal_25khz(signal_25khz),.signal_50mhz(signal_50mhz),.led_test(led2));/例化频率计信号控制模块console console(.clk(clk),.rst_n(rst_n),.clk_1hz(led1),.en_cnt(en_cnt),.load(load),.rst_cnt(rst_cnt));//例化BCD计数器模块(8个)(计数器输出数据是data_temp)BCDcounter_top BCDcounter_top_test(.clk(fin),.rst_n(rst_cnt),.en(en_cnt),.cin(1'b1),.cout(),.q(data_temp));//32位输出数据锁存器(在load的上升沿将输出数据更新,否则锁存,数据不变)always@(posedge load,negedge rst_n)if(!rst_n)data_lock <= 32'd0;elsedata_lock <= data_temp;//例化数码管显示模块(数码管显示的是data_lock中的数据)HEX8_top HEX8_top(.clk(clk),.rst_n(rst_n),.en(1'b1),.disp_data(data_lock),.sck(sck),.rck(rck),.si(si));
endmodule 

RTL:

上板测试图


附:74HC595移位寄存器解析(图片)

AC620 的8位数码管连接方式:


基于FPGA的简易数字频率计+上板测试(小梅哥AC620FPGA开发板)相关推荐

  1. 基于小梅哥AC620开发板的NIOS II LWIP百兆以太网例程移植到自己做的板子上

    原程序是运行在小梅哥AC620开发板上的:基于小梅哥AC620开发板的NIOS II LWIP百兆以太网例程_ZLK1214的专栏-CSDN博客_小梅哥ac620[开发板]开发板型号:小梅哥AC620 ...

  2. 单片机c语言数字频率计的课程设计,基于单片机的简易数字频率计设计报告(最终版)最新版...

    <基于单片机的简易数字频率计设计报告.doc>由会员分享,可免费在线阅读全文,更多与<基于单片机的简易数字频率计设计报告(最终版)>相关文档资源请在帮帮文库(www.woc88 ...

  3. 基于FPGA的简易DDS信号发生器的设计与验证

    基于FPGA的简易DDS信号发生器的设计与验证 一,理论介绍 补充:举例理解 二,代码实现 1,实验目标 2,MATLAB代码 3,verilog代码及实现思路 一,理论介绍 DDS 是直接数字式频率 ...

  4. 基于FPGA的简易DDS信号发生器的设计(一)

    写这篇文章的本意不是为了探讨AD9767怎么使用,因为9767的控制实在是太简单了,准备好数据直接输出即可,和网上大多数的并行DA输出基本上一模一样,更麻烦的反而是硬件方面.发文的原因是最近一位很细心 ...

  5. 频谱仪设计基于FPGA的频谱仪设计,可以测试分析多种频率的频谱,分辨率100HZ

    频谱仪设计基于FPGA的频谱仪设计,可以测试分析多种频率的频谱,分辨率100HZ,配套资料多达100M,东西复杂 ID:982500594354361311卡哇伊2号小宝贝

  6. arduinopn532模块_NFC开发板/nfc芯片标签/PN532开发板/RFID读卡器/NFC模块/Arduino

    带40 kB ROM和1 kB RAM的80C51微控制器内核 高度集成的模拟电路,解调和译码响应 输出缓冲驱动器通过非常少量的外部无源器件连接天线 集成了RF场检测器 集成了数据模式检测器 支持IS ...

  7. 选择的串口 _ 不存在或开发板没有连接_PC 和开发板之间传输文件

    8.1 传输文件的多种方法 在嵌入式开发中,涉及交叉编译:在 PC 上编译,在开发板上运行.所以就涉及 PC 和开发板之间的文件 传输,方法有多种:网络传输.串口传输.USB 传输,当然,还有最笨的方 ...

  8. micropython开发板性能_MicroPython支持的开发板:高性能、低成本创客首选

    原标题:MicroPython支持的开发板:高性能.低成本创客首选 Python的开放.简洁.黏合正符合了现发展阶段对大数据分析.可视化.各种平台程序协作产生了快速的促进作用.自Python3的发布到 ...

  9. 玩转开发板--Linux系统移植至开发板fl2440实践过程

    一.开发板介绍     CPU:S3C2440(SAMSUNG).ARM920T.400MHz     Pone/mic:耳机和话筒 JTAG:可以通过外部插入直接控制CPU,因此在初始化内存时,起到 ...

最新文章

  1. 查询数据(使用聚合函数,还是单表)
  2. Windows 技术篇-设置dns提升网速,刷新dns缓存
  3. 卡夫卡编年史队列基准
  4. [JavaScript]return false;和e.preventDefault();的区别
  5. hadoop为什么出现
  6. Remote branch Develop not found in upstream origin
  7. 根据一个id查找出数组里面的数据并改掉_Excel最强大的VLOOKUP以及INDEXamp;MATCH查找函数...
  8. 关于[知识竞赛现场管理系统-双屏PPT版]内置的第三方答题平台以及[评委计分系统-双屏专业版]的特殊疑难问题 汇编
  9. 基于JQUERY的WEB在线流程图设计器GOOFLOW 0.5版 数据值解析
  10. 环保线绕电阻器的主要特性和应用分析
  11. Fiddler https最新抓包方法(Android 9.0)
  12. c语言中if函数作用,c语言函数if的用法怎么用
  13. cogs426 血帆海盗 最小割定理
  14. ios 图片合成幻灯片_为iPad构建iOS幻灯片应用程序
  15. stm32h7 串口idle_【STM32H7教程】第30章 STM32H7的USART应用之八个串口FIFO实现
  16. (Tekla Structures二次开发)创建多边形板
  17. Qpython SL4A服务调用GPS定位获取获取位置信息
  18. 普通pc机的轻连接到底能建多少?
  19. 撒旦撒旦阿三的撒的撒
  20. 巴西支付Boleto对巴西外贸有多重要!?

热门文章

  1. QCY HT03 王菊同款推荐,主动降噪静享好时光
  2. 百元级树莓派pico四足机器狗设计(并联腿结构)持续更新
  3. 初级前端如何突破瓶颈(瓶颈期怎么办)
  4. 携程--数据运营、数据分析
  5. 源码0604-12-掌握-webView
  6. 卸载sql重新启动计算机,卸载SQL2008遇到问题(重启计算机失败、找不到SQL卸载程序)的解决办法...
  7. Win11安装Mysql提示安装MSVCR120.dll缺失
  8. switch(选择)结构
  9. 视频剪辑软件,如何给视频添加自定义图片作为背景
  10. 怎么能把文字转语音?我来教你几个方法