十三、四通道数字电压表

本文由山东大学研友袁卓贡献,特此感谢

实验目的

设计一个四通道的数字电压表

实验平台

芯航线FPGA核心板、AD/DA模块

实验现象

实现一个四通道的数字电压表,其中可以用按键切换测量通道并在4位数码管上显示对应的测量值。

实验原理及步骤

数字电压表的工作原理即为,被测信号接入ADC模块的输入引脚,FPGA控制ADC的转换进程以及原始数据的采集,并将其采集到的二进制数据转换为数码管的显示数据。其中按键可以选择ADC模块不同的通道。其系统工作原理图如图1所示。

图1 系统工作原理图

由工作原理图可以暂时将本系统划分为ADC控制模块、码制转换模块、按键数据模块以及数码管驱动模块组成。

ADC控制模块之TLV1544

本系统采用的是TLV1544芯片,其为10位的ADC。因此其理论测量精度为,且当其输出为’dx时,实际电压为V。本模块的设计在基础课程已经讲解,此处不再详述。其模块接口示意图如下所示。

图2 ADC模块接口示意图

数据预处理模块

ADC模块输出还是一个十位二进制数,因此需要先将数据转换成实际电压值。

上式中3.42为满量程电压,data为输出的二进制数,1024为ADC总的阶梯数。之所以是3.42,是本模块基准电源TL341输出电压。

这样得出的数据太小,因此先将其放大倍。这里也可以放大其他倍数。

经过上式的转换,还是一个小数,这里再放大1000倍以消除小数。即实际显示的数据为实际电压的1000倍。这样就完成了二进制数到实际电压的转换。

由于在上面TLV1544驱动设计中,数据更新速度为4000ns/次。这样已足够用做电压表显示,但是此处为了使数据稳定,加入均值滤波程序。本模块接口示意图如图3所示,其接口功能列表如表1所示。

图3 数据预处理模块接口示意图

表1 数据预处理模块接口功能描述

先将原始数据进行累加1024次。

    reg [:]Hex_SUM;
reg [:]Hex; reg [:]cnt;
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
cnt <= 'b0;
else if(ADC_flag)
cnt <= cnt + 'b1;
else
cnt <= cnt; always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
Hex_SUM <= 'd0;
else if(cnt == && ADC_flag)
Hex_SUM <= 'd0;
else if(ADC_flag)
Hex_SUM <= Hex_SUM + Hex_data;
else
Hex_SUM <= Hex_SUM;

将累加后的数据除以1024,也就是右移10位,这里数据总位数为20直接取其高10位即可。

    always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
Hex <= 'b0;
else if(cnt == && ADC_flag)
Hex <= Hex_SUM[:];
else
Hex <= Hex;

利用上面推导的公式即可输出最后的数据。

   assign Voltage = ( * Hex) >> ;  

码制转换模块

由于ADC输出的为10位二进制数而数码管需要的是BCD码的格式,因此需要将其进行码制的转换。

首先,先了解二进制与BCD码的位数对应关系。比如一个8位二进制码,可以表示的最大十进制数为255,转换成BCD码为 0010_0101_0101,共需12位,其中每4位组成一个BCD单元。n位二进制码转换成D个BCD码的n~D对应关系表见表2。

表2  n~D对应关系

此处采用加3移位法进行转换,附件中列举了另一种方式来进行转换。以8位二进制转换为3位BCD码为例,转换步骤是:将待转换的二进制码从最高位开始左移BCD的寄存器(从高位到低位排列),每移一次,检查每一位BCD码是否大于4,是则加上3,否则不变。左移8次后,即完成了转换。需要注意的是第八次移位后不需要检查是否大于5。

注意:为什么检查每一个BCD码是否大于4,因为如果大于 4(比如 5、6),下一步左移就要溢出了,所以加 3,等于左移后的加 6,起到十进制调节的作用。

表3给出了一个二进制码11101011转换成8421BCD码的时序。

表3  B/BCD时序

首先进行判断一个BCD码是否大于4,是则进行加3处理,否则输出原来数值。

module bcd_single_modify(bcd_in,bcd_out);

    input [:] bcd_in;
output [:] bcd_out; reg [:] bcd_out; always @ (bcd_in)
begin
if (bcd_in > )
bcd_out = bcd_in + 'd3;
else
bcd_out = bcd_in;
end endmodule

由以上原理可看出,这里需要定义一个10+12位的寄存器。同时从表3克拿出有几位二进制数就需移位几次。这里为了增加适用范围,将输入定位20位的二进制数,因此输出为7*4位BCD数。这样定义一个48位的移位寄存器。低20位为二进制数,高28位为BCD码。

每移位一次就需验证高28位BCD码是否大于4因此,编写以下代码。

module bcd_modify(data_in, data_out);

    input [:] data_in;
output [:] data_out; bcd_single_modify bcd6(.bcd_in(data_in[:]), .bcd_out(data_out[:]));
bcd_single_modify bcd5(.bcd_in(data_in[:]), .bcd_out(data_out[:]));
bcd_single_modify bcd4(.bcd_in(data_in[:]), .bcd_out(data_out[:]));
bcd_single_modify bcd3(.bcd_in(data_in[:]), .bcd_out(data_out[:]));
bcd_single_modify bcd2(.bcd_in(data_in[:]), .bcd_out(data_out[:]));
bcd_single_modify bcd1(.bcd_in(data_in[:]), .bcd_out(data_out[:]));
bcd_single_modify bcd0(.bcd_in(data_in[:]), .bcd_out(data_out[:]));
assign data_out[:] = data_in[:]; endmodule

现在编写顶层文件,其端口示意图及功能描述如下所示/

图4 码制转换模块接口示意图

表4 码制转换模块接口功能描述

    reg [:] shift_reg;
wire [:] shift_reg_out;
wire [:]tmp;
reg [:]bcd_tmp; reg [:] cnt = 'b0; assign tmp = {'b0,Bin};

向左移位20次。

    always@(posedge Clk or negedge Rst_n)
begin
if(!Rst_n)
begin
Done_Sig <= 'b0;
cnt <= 'd0;
shift_reg <= 'd0;
end
else
begin
case(cnt)
:begin
Done_Sig <= 'b0;
if(Do_Translate)
begin
cnt <= cnt + 'b1;
shift_reg <= tmp<<;
end
else
cnt <= 'b0;
end ,,,,,,,,,,,,,,,,,:
begin
shift_reg <= (shift_reg_out<<);
cnt <= cnt + 'b1;
end :
begin
bcd_tmp <= shift_reg_out<<;
Done_Sig <= ;
cnt <= 'b0;
end
default :cnt <= 'b0;
endcase
end
end

校验以及输出最终输出数据。

    assign Bcd = bcd_tmp[:];

    bcd_modify bcd_modify
(
.data_in(shift_reg),
.data_out(shift_reg_out)
);

按键输入模块

本部分在基础课程中也有介绍,此处只给出其端口示意图。

图5 按键输入模块接口示意图

通道选择模块

通过按键进行ADC四通道的选择,本模块接口示意图以及功能描述如下所示。

图6 通道选择模块接口示意图

表5 通道选择模块接口功能描述

内部除了例化还需产生通道选择信号,这里用的模块有四个通道但是为何按键一来就加’d2,是因为通道选择实际信号需为0000、0010、0100、1000,这样我们就需要加’d2。

    wire key_state;
wire key_flag; always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
ADC_CHSEL <= ;
else if(key_flag && !key_state)begin
if(ADC_CHSEL == 'b0110)
ADC_CHSEL <= 'd0;
else
ADC_CHSEL <= ADC_CHSEL + 'd2;
end
else
ADC_CHSEL <= ADC_CHSEL;

数码管驱动模块

本部分在基础课程中也有介绍,此处只给出其端口示意图。

图7 数码管模块接口示意图

顶层设计

此处只需例化各个模块即可,顶层模块接口示意图如下所示。

图8 顶层模块接口示意图

综合后的RTL视图如图9所示。

图9 RTL Viewer视图

分配好引脚下载后可以看到改变输入电压,数码管上均有正常的显示,且切换通道时数据可以随之更新。

至此一个四通道数字电压表设计完毕。

附:基于查找表的数据电压换算

前面指出了一种数据处理及码制的方式,这里再列举利用查找表的实现方式。

这里因为是输入的10位二进制数,也就是说每一位变化对应的变化量为即为精度,这样就可以得出以下待转换数据与实际电压的对照表。这样当3.296v

这样就可以建立一个查找表,来分别计算其对应位的电压值的BCD码,然后相加。

     reg [:] data1;
reg [:] data2;
reg [:] data3;
case(ADC_DATA[:])
'b0000:data1[15:0] = 16'b0000_0000_0000_0000;
'b0001:data1[15:0] = 16'b0000_0000_0000_0011; //.003
'b0010:data1[15:0] = 16'b0000_0000_0000_0110; //.006
'b0011:data1[15:0] = 16'b0000_0000_0001_0000; //.010
'b0100:data1[15:0] = 16'b0000_0000_0001_0011; //.013
'b0101:data1[15:0] = 16'b0000_0000_0001_0110; //.016
'b0110:data1[15:0] = 16'b0000_0000_0001_1001; //.019
'b0111:data1[15:0] = 16'b0000_0000_0010_0011; //.023
'b1000:data1[15:0] = 16'b0000_0000_0010_0110; //.026
'b1001:data1[15:0] = 16'b0000_0000_0010_1001; //.029
'b1010:data1[15:0] = 16'b0000_0000_0011_0010; //.032
'b1011:data1[15:0] = 16'b0000_0010_0011_0101; //.035
'b1100:data1[15:0] = 16'b0000_0010_0011_1001; //.039
'b1101:data1[15:0] = 16'b0000_0010_0100_0010; //.042
'b1110:data1[15:0] = 16'b0000_0010_0100_0101; //.045
'b1111:data1[15:0] = 16'b0000_0010_0100_1000; //.048
endcase
case(ADC_DATA[:])
'b0000:data2[15:0] = 16'b0000_0000_0000_0000;
'b0001:data2[15:0] = 16'b0000_0000_0101_0010; //.052
'b0010:data2[15:0] = 16'b0000_0001_0000_0011; //.103
'b0011:data2[15:0] = 16'b0000_0001_0101_0101; //.155
'b0100:data2[15:0] = 16'b0000_0010_0000_0110; //.206
'b0101:data2[15:0] = 16'b0000_0010_0110_1000; //.258
'b0110:data2[15:0] = 16'b0000_0011_0000_1001; //.309
'b0111:data2[15:0] = 16'b0000_0011_1000_0001; //.361
'b1000:data2[15:0] = 16'b0000_0100_0001_0011; //.413
'b1001:data2[15:0] = 16'b0000_0100_0110_0100; //.464
'b1010:data2[15:0] = 16'b0000_0101_0001_0110; //.516
'b1011:data2[15:0] = 16'b0000_0101_0011_0111; //.567
'b1100:data2[15:0] = 16'b0000_0110_0001_1000; //.618
'b1101:data2[15:0] = 16'b0000_0110_0111_0000; //.670
'b1110:data2[15:0] = 16'b0000_0111_0010_0001; //.722
'b1111:data2[15:0] = 16'b0000_0111_0111_0011; //.773
endcase
case(ADC_DATA[:])
'b00: data3[15:0] = 16'b0000_0000_0000_0000;
'b01: data3[15:0] = 16'b0000_1000_0010_0101; //.825
'b10: data3[15:0] = 16'b0001_0110_0101_0000; //1.650
'b11: data3[15:0] = 16'b0010_0100_0101_0111; //2.457
endcase

如果0~3位相加大于9,则加6调整为BCD码,并产生进位信号。再进行4~7位相加加上进位信号判断,再判断8-9位。

reg[:] c1; //低4位BCD进位信号
reg[:] c2; //中
reg[:] c3;
if(data1[:]+data2[:]+data3[:] < 'b01010) begin
disp_data[:] = data1[:]+data2[:]+data3[:];
c1 = ;
end
else begin
disp_data[:] = data1[:]+data2[:]+data3[:]-'b1010;
c1 = ;
end if(c1+data1[:]+data2[:]+data3[:] < 'b01010) begin
disp_data[:] = c1+data1[:]+data2[:]+data3[:];
c2 = ;
end
else begin
disp_data[:] = c1+data1[:]+data2[:]+data3[:]-'b1010;
c2 = ;
end if(c2+data1[:]+data2[:]+data3[:] < 'b01010) begin
disp_data[:] = c2+data1[:]+data2[:]+data3[:];
c3 = ;
end
else begin
disp_data[:] = c2+data1[:]+data2[:]+data3[:]-'b1010;
c3 = ;
end if(c3+data1[:]+data2[:]+data3[:] < 'b01010) begin
disp_data[:]=c3+data1[:]+data2[:]+data3[:] ;
end
else begin
disp_data[:]='bz;
end

这样再将以上两个部分放置到一个always块中即可。同样可以看到实际效果。将输入数据显示格式修改为十进制后,输入512时输出0001_0110_0101_0000。此时实际电压为512*3.296/1024=1.648,显示为1.650。输入256时实际电压0.824,显示为0.825。

如有更多问题,欢迎加入芯航线 FPGA 技术支持群交流学习:472607506

小梅哥

芯航线电子工作室

关于学习资料,小梅哥系列所有能够开放的资料和更新(包括视频教程,程序代码,教程文档,工具软件,开发板资料)都会发布在我的云分享。(记得订阅)链接:http://yun.baidu.com/share/home?uk=402885837&view=share#category/type=0

赠送芯航线AC6102型开发板配套资料预览版下载链接:链接:http://pan.baidu.com/s/1slW2Ojj 密码:9fn3

赠送SOPC公开课链接和FPGA进阶视频教程。链接:http://pan.baidu.com/s/1bEzaFW 密码:rsyh

【小梅哥FPGA进阶教程】第十三章 四通道数字电压表的更多相关文章

  1. 【小梅哥FPGA进阶教程】第九章 基于串口猎人软件的串口示波器

    九.基于串口猎人软件的串口示波器 1.实验介绍 本实验,为芯航线开发板的综合实验,该实验利用芯航线开发板上的ADC.独立按键.UART等外设,搭建了一个具备丰富功能的数据采集卡,芯航线开发板负责进行数 ...

  2. 【小梅哥FPGA进阶教程】第十四章 TFT屏显示图片

    十四.TFT屏显示图片 本文由杭电网友曾凯峰贡献,特此感谢 学习了小梅哥的TFT显示屏驱动设计后,想着在此基础上通过TFT屏显示一张图片,有了这个想法就开始动工了.首先想到是利用FPGA内部ROM存储 ...

  3. 【小梅哥FPGA进阶教程】第十二章 数字密码锁设计

    十二.数字密码锁设计 本文由山东大学研友袁卓贡献,特此感谢 实验目的 实现数字密码锁设计,要求矩阵按键输出且数码管显示输入密码,密码输入正确与否均会有相应标志信号产生. 实验平台 芯航线FPGA核心板 ...

  4. 【小梅哥FPGA进阶教程】第十一章 四通道幅频相可调DDS信号发生器

    十一.四通道幅频相可调DDS信号发生器 本文由山东大学研友袁卓贡献,特此感谢 实验目标 实现多通道可调信号发生器 实验平台 芯航线FPGA核心板.ADDA模块 实验现象 实现基于FPGA的多通道可调信 ...

  5. 【小梅哥FPGA进阶教程】MC8051软核在FPGA上的使用

    十.MC8051软核在FPGA上的使用 本教程内容力求以详细的步骤和讲解让读者以最快的方式学会 MC8051 IP core 的应用以及相关设计软件的使用,并激起读者对 SOPC 技术的兴趣.本实验重 ...

  6. 【小梅哥FPGA进阶教程】串口发送图片数据到SRAM在TFT屏上显示

    十五.串口发送图片数据到SRAM在TFT屏上显示 之前分享过rom存储图片数据在TFT屏上显示,该方法只能显示小点的图片,如果想显示TFT屏幕大小的图片上述方法rom内存大小不够.小梅哥给了个方案,利 ...

  7. 【小梅哥FPGA进阶学习之旅】基于Altera FPGA 的DDR2+千兆以太网电路设计

    DDR2电路设计 在高速大数据的应用中,高速大容量缓存是必不可少的硬件.当前在FPGA系统中使用较为广泛的高速大容量存储器有经典速度较低的单数据速率的SDRAM存储器,以及速度较高的双速率DDR.DD ...

  8. 小梅哥FPGA数字逻辑设计教程——基于线性序列机的TLC5620型DAC驱动设计

    基于线性序列机的TLC5620型DAC驱动设计 目录 TLC5620型DAC芯片概述:    2 TLC5620型DAC芯片引脚说明:    2 TLC5620型DAC芯片详细介绍:    3 TLC ...

  9. javascript进阶教程第三章--匿名和闭包--案例实战

    javascript进阶教程第三章--匿名和闭包--案例实战 一.学习任务 通过几个小练习回顾学过的知识点 二.实例 练习1: 实例描述:打开页面后规定时间内弹出一个新窗口,新窗口指定时间后自动关闭. ...

随机推荐

  1. BIO模型

    基本模型 代码: 客户端 package bhz.bio; import java.io.BufferedReader; import java.io.IOException; import java ...

  2. RabbitMQ双活实践(转)

    有货RabbitMQ双活实践   消息服务中间件在日常工作中用途很多,如业务之间的解耦,其中 RabbitMQ 是比较容易上手且企业使用比较广泛的一种,本文主要介绍有货在使用 RabbitMQ 的一些 ...

  3. 【302】C# TreeView 控件使用说明

    参考:C# 中treeview 树节点图标的动态加载,及选中时图标改变 参考:C# TreeView 控件的综合使用方法 参考:TreeView 类 参考:TreeNode 类 1. 添加根和子级 通 ...

  4. python调用函数

    1.同一包内的调用 直接使用import 文件名 或者from 文件名 import 函数名 a.py def p(): print("abc") b.py from a impo ...

  5. drbd switch off

    DRBD secondary to primary: drbdadm disconnect all drbdadm primary r0 --force mount /dev/drbd0 /mnt [ ...

  6. java算法 第七届 蓝桥杯B组(题+答案) 6.方格填数

    6.方格填数  (结果填空) 如下的10个格子 (如果显示有问题,也可以参看[图1.jpg]) 填入0~9的数字.要求:连续的两个数字不能相邻.(左右.上下.对角都算相邻) 一共有多少种可能的填数方案 ...

  7. 压缩包法安装mysql

    之前一直安装mysql,我一直是用压缩包安装的.如果之前安装过Mysql,必须要删除注册文件,才能把Mysql彻底删除了. 先在官网下载mysql的版本.下载package版本,即.zip版本的.下载 ...

  8. 【hdu6148】Valley Numer【数位dp模板题】

    题意 对于每组数据给出一个整数n(length(n)<=100),找出不大于n的数字中有多少是Valley Numer.对于Valley的定义是它每一位的数字要么是递增,要么是递减,要么是先递减 ...

  9. 刷题向》一道逆向思维题(BZOJ1046)(NORMAL)

    这道题对于一类题都有一个通用思路:反向递减序列即为正向字典序. 对于逆向思维的题还要多做才能培养这种对于逆向思维的感觉. 想到这种方法之后,就很简单了. 因为n×m不会炸,所以反向LIS叠一个贪心就能 ...

  10. HTML标签及属性

    HTML 标签大全及属性  来源:http://www.cnblogs.com/Mr-liyang/p/5797976.html 基本结构标签:<HTML>,表示该文件为HTML文件< ...