设计背景:
数模转换器是连接数字世界和模拟世界的桥梁。人类生活在模拟世界。虽然数字器件和设备的比例日益增加,但数模转换器的发展仍然是必要的。
DAC应用涉及航空空航天、国防和军事、民用通信、多媒体和数字信号处理。DAC基本上由四部分组成,分别是权重电阻网络、运算放大器、参考电源和模拟开关。它是一种转换器,根据参考电压将二进制数字量形式的离散信号转换为模拟量。
设计原则:
本设计采用串行数模转换器芯片TLC5620。TLC5620为四路输出的数模转换器,时钟频率最多可达1MHz。TLC5620芯片的接口如下:
该芯片主要具有以下特点:四通道8位电压输出DA转换器,5V单电源,串行接口,高阻抗基准输入,可编程1或2输出范围,设备同步更新,内部上电复位,低功耗,半缓冲输出。该芯片主要用于可编程电源、数控放大器/误差检测器、移动通信、自动测试设备、R&D过程检测与控制和信号合成等。
变换公式:V = REF*(CODE/256)* (1+RNG)
v:实际电压;参考电压;代码:输入8位数据;RNG:范围。
TLC5620的接口时序如下图所示:
图1负荷控制更新(LDAC低)
图2 LDAC控制更新(LDAC低)
图3负载控制更新(使用8位串行数据,负载低)
图4 LDAC控制更新(使用8位串行数据)
如图1所示,当LOAD为高电平时,数据在CLK下降沿锁存为数据,只要所有数据都锁存,LOAD就会拉低,将数据从串行输入寄存器传输到选定的数模转换器。
如图2所示,在串行编程期间,LDAC为高,当负载为低时,数据被锁存,当LDAC为低时,数据被传输到数模转换器输出。如图3和图4所示,输入数据的最高有效位(MSB)首先出现,数据传输使用两个8时钟周期。
在本设计中,使用了图1的工作顺序:
数据通道选择:
RNG:控制数模转换器的输出范围。当RNG低时,输出范围在参考电压和GND之间。当RNG为高电平时,输出范围是参考电压和GND的两倍。
设计架构图:
本设计驱动TLC5620将输入的数字量转换成实际的模拟量(电压),并通过四个按钮控制四个输出的电压变化。每次按下按钮,电压值都会上升,相应的值(A1,A0,RNG,输入数据)会依次显示在数码管上。本次设计使用的开发板参考电压为2.5V,设计架构图如下:
key_test模块通过组合四个按键输入的值输出两个数据,11位wr_data是TLC_DA模块解码所需的数据。20位out_data是seg_num模块数码管显示所需的数据。
设计代码:
key_test模块代码如下:
0模块key_test( //按键控制模块
1 //端口信号:模块的输入输出接口
2输入clk,//50MHZ
3输入rst_n,//低电平复位
4输入[3:0]键,//四键组合信号
五
6输出[10:0] wr_data,//输出一帧数据,是DA模块的输入数字量
7输出[19:0] out_data //输出数码管显示数据
8 );
九
10 //分频计数器时钟
11 reg[30:0]CNT;
12 reg clk _ r;//分频时钟:在消除抖动的时钟频率下执行按键检测
13总是@ (posedgclk或negerst _ n)//按键去抖,一次测试时间为0.2s
14 if(!rst_n)
15开始
16 cnt <。= 0;
17 clk_r <。= 0;
18结束
19 else if(cnt <。30'd1000_0000)
20 cnt <。= CNT+1 ' B1;
其他21个
22开始
23 cnt <。= 0;
24 clk_r <。= ~ clk _ r;
25结束
26
27 //键低电平有效。当检测到相应的键时,相应的值增加1并显示相应的频道
28 reg [7:0]数据;//按键输入数据
29 reg [1:0]通道;//频道选择
30 reg [7:0] key1,key2,key3,key4//对应四个按钮
31始终@(posedge clk_r或negedge rst_n)
32 if(!rst_n)
33开始
34 key1 <。= 8 ' h00
35 key2 <。= 8 ' h00
36 key3 <。= 8 ' h00
37 key4 <。= 8 ' h00
38数据<。= 8 ' h00
39频道<。= 2 ' b00
40结束
41 else
42箱(钥匙)
43 4'b1110: begin //按钮1:选择频道A,在输入号码上加1
44频道<。= 2 ' b00
45 key1 <。= key 1+1 ' B1;
46数据<。= key1
47结束
48 4'b1101: begin //按钮2:选择频道B,在输入号码上加1
49频道<。= 2 ' b01
50 key2 <。= key 2+1 ' B1;
51数据<。= key2
52结束
53 4'b1011: begin //按钮3:选择频道C,并在输入号码上加1
54频道<。= 2 ' b10
55 key3 <。= key 3+1 ' B1;
56数据<。= key3
57结束
58 4'b0111: begin //键4:选择频道D,在输入号码上加1
59频道<。= 2 ' b11
60 key4 <。= key 4+1 ' B1;
61数据<。= key4
62结束
63默认值:;
64端箱
65
66 //将所需数据与赋值语句结合起来。在本例中,RNG默认为1
67 assign wr_data = {channel,1'b1,data };assignout_data={{3'b000,channel[1]},3'b000,channel[0],4'p,data };
六十八
69端模块
TLC_DA模块代码如下:
0模块TLC_DA( //将数字量输入到模拟量模块,本实验采用TLC5620
1 //端口信号:模块的输入输出接口
2输入clk,//系统时钟50MHz
3输入rst_n,//低电平复位
4输入[10:0] data_in,//输入一帧数据
5输出da_data,//串行数据接口
6输出da _ clk//串行时钟接口
7输出reg da_ldac,//更新控制信号
8输出寄存器da_load //串行负载控制接口
9 );
10
11 //计数器时钟分频:根据芯片内部时序要求分频
12 reg[30:0]CNT;
13线da _ clk _ r;//TLC 5620内部时钟信号
14始终@ (posedgclk或negerst _ n)//满足协议中的时钟要求,TLC 5620中的时钟要求不超过1MHZ。
15 if(!rst_n)
16 cnt <。= 6 ' d0
17其他
18 cnt <。= CNT+1 ' B1;
19
20分配da _ clk _ r = CNT[5];
21
22 //接收定时状态机
23 reg [2:0]状态;
24 reg[3:0]CNT _ da;
25 reg da _ data _ r;
26 reg da _ data _ en//定义da _ data和da _ clk的有效区域
27始终@(posedge da_clk_r或negedge rst_n)
28 if(!rst_n)
29开始
30州<。= 0;
31 cnt _ da & lt= 0;
32 da _ load & lt= 1;
33 da _ ldac & lt= 0;
34 da _ data _ r & lt= 1 ' b1
35 da _ data _ en & lt= 0;
36端
37 else
38起案件(州)
39 0:状态<。= 1;
40 1:开始
41 da _ load & lt= 1;
42 da _ data _ en & lt= 1;
43 if(CNT _ da & lt;= 10)
44开始
45 cnt _ da & lt= CNT _ da+1 ' B1;
46箱(cnt_da)
47 0:da _ data _ r & lt;= data _ in[10];
48 1:da _ data _ r & lt;= data _ in[9];
49 2:da _ data _ r & lt;= data _ in[8];
50 3:da _ data _ r & lt;= data _ in[7];
51 4:da _ data _ r & lt;= data _ in[6];
52 5:da _ data _ r & lt;= data _ in[5];
53 6:da _ data _ r & lt;= data _ in[4];
54 7:da _ data _ r & lt;= data _ in[3];
55 8:da _ data _ r & lt;= data _ in[2];
56 9:da _ data _ r & lt;= data _ in[1];
57 10:da _ data _ r & lt;= data _ in[0];
58默认值:;
59端箱
60州<。= 1;
61结束
62 else
63开始
64 cnt _ da & lt= 0;
65州<。= 2;
66 da _ data _ en & lt= 0;
67结束
68端
69 2:开始
70 da _ load & lt= 0;
71州<。= 3;
72结束
73 3:开始
74 da _ load & lt= 1;
75州<。= 0;
76端
77默认值:state <。= 0;
78端箱
79
80赋值da_data = (da_data_en)?da _ data _ r:1 ' B1;
81赋值da_clk = (da_data_en)?da _ clk _ r:1 ' B0;
82
83端模块
Seg_num模块代码如下:
0模块seg_num( //数码管显示模块:选择数码管0-4显示{A1,A0,RNG,DATA}。
1 //端口信号:模块的输入输出接口
2输入clk,//系统时钟50MHz
3输入rst_n,//低电平复位
4输入[19:0] data_in,//20位输入数据
五
6输出寄存器[7:0] seg,//数字管段选择
7输出寄存器[2:0] sel //数字电子管位选择
8 );
九
10 //通过查找表,对应位的数码管与对应的数据位一一对应
11 reg[3:0]num;
12总是@(*)
13箱(sel)
14 4:num = data _ in[3:0];//第五个数码管显示低四位数据[3: 0]
15 3:num = data _ in[7:4];//第四个数码管显示低四位数据[7: 4]
16 ^ 2:num = data _ in[11:8];//第三个数码管显示低四位数据[11:8]
17 1:num = data _ in[15:12];//第二个数码管显示低四位数据[15:12]
18 0:num = data _ in[19:16];//第一个数码管显示低四位数据[19:16]
19默认值:;
20端箱
21
22 //借助查表,数据一一对应数码管的显示方式。
23总是@(*)
24箱(数量)
25 0: seg <。= 8 ' hC0//8'b1100_0000
26 1: seg <。= 8 ' hF9//8'b1111_1001
27 2: seg <。= 8 ' hA4//8'b1010_0100
28 3: seg <。= 8 ' hB0//8'b1011_0000
29 4: seg <。= 8 ' h99//8'b1001_1001
30 5: seg <。= 8 ' h92//8'b1001_0010
31 6: seg <。= 8 ' h82//8'b1000_0010
32 7: seg <。= 8 ' hF8//8'b1111_1000
33 8: seg <。= 8 ' h80//8'b1000_0000
34 9: seg <。= 8 ' h90//8'b1001_0000
35默认值:seg <。= 8 ' hFF//8'b1111_1111
36端箱
37
38 //计数器时钟分频:cnt位10的变化用作分频时钟
39 reg[23:0]CNT;
40始终@(posedge clk或negedge rst_n)
41 if(!rst_n)
42 cnt <。= 4 ' d0
43 else
44 cnt <。= CNT+1 ' B1;
45 //在分频时钟下,数码管的0-5位依次循环
46的分频时钟总是@ (posedgcnt [10]或negerst _ n)//是2 ^ 10/50m
47 if(!rst_n)
48 sel <。= 0;
49 else if(sel & lt;4)
50 sel <。= sel+1 ' B1;
51 else
52 sel <。= 0;
53
54端模块
顶部模块代码如下:
0模块顶部(//顶部模块:组合各种模块
1 //外部接口
2输入clk,//系统时钟50MHz
3输入rst_n,//低电平复位
4输入[3:0]键,//由四个键组成的键信号,低电平有效
五
6输出da_data,//DA串行接口数据
7输出da_clk,//DA串行接口时钟
8输出da_ldac,//DA更新信号
9输出da_load,//DA串行接口负载控制信号
10输出[7:0] seg,//数字管段选择
11输出[2:0] sel //数字电子管位选择
12 );
13 //内部信号:模块的内部接口信号,如模块TLC_DA的输出信号data_in,通过内部信号r_data与模块key_test的输入信号wr_data相连
14线[10:0]wr _ data;
15线[19:0]out _ data;//数字管的数据输入
16
17 //模块实例化
18 TLC_DA TLC_DA_inst( //将数字量输入模拟量模块)
19 .clk(clk),
20 .rst_n(rst_n),
21 .da_clk(da_clk),
22 .da_data(da_data),
23 .da_ldac(da_ldac),
24 .da_load(da_load),
25 .data_in(wr_data)
26 );
27
28 key_test key_test_inst( //按键控制模块)
29 .clk(clk),
30 .rst_n(rst_n),
31 .键(key),
32 .wr_data(wr_data),
33 .out_data(out_data)
34 );
35
36 seg_num seg_num_inst( //数码管显示模块)
37 .clk(clk),
38 .rst_n(rst_n),
39 .data_in(out_data),
40 .seg(seg),
41 .sel(sel)
42 );
43
44端模块
测试顶部模块测试代码:
0 '时间刻度1 ns/ 1 ns //将模拟时间单位和精度分别设置为1 ns/ 1 ns
1 //如果设置为`时标1ns/1ps (# 200表示延迟200 ns1ps是模拟的精度)
2模块测试;//测试模块:主要是给激励信号赋值,模拟后观察波形,验证是否与实际功能相同
三
4 //端口信号定义,激励信号为reg类型
5 reg clk
6 reg rst _ n;
7 reg [3:0]键;
8线[7:0]seg;
9线[2:0]sel;
10
11 //模块实例化
12顶顶(
13 .clk(clk),
14 .rst_n(rst_n),
15 .键(key),
16 .seg(seg),
17 .sel(sel)
18 );
19
20 //初始化激励,并为相应的激励赋值
21首字母
22开始
23 clk = 0;rst _ n = 0;key = 4 ' b1111//在复位阶段,将激励设置为初始值
24
25 # 200 rst _ n = 1;//延迟200ns后,将复位信号设置为1
26
27 //实现按键1打开和关闭
28 # 500000 key = 4 ' b1110
29 # 500000 key = 4 ' b1111
30
31结束
32
33始终# 10 clk = ~ clk//时钟的表示,即每10ns,一个周期的时间为20ns,时钟为1/20ns = 50MHZ
34
35端模块
模拟图:
由于模拟时间的原因,这里只测试按下按钮1时数码管的显示,显示为00100,表示频道A,RNG为1,输入数字为00。实际板卡验证后,也可以用万用表测量输入数字量对应的电压值。
1.《数模转换 【FPGA学习】一文教你轻松实现数模转换的设计》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。
2.《数模转换 【FPGA学习】一文教你轻松实现数模转换的设计》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。
3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/junshi/938718.html