我是靠谱客的博主 沉静路灯,最近开发中收集的这篇文章主要介绍FPGA学习之数模转换(TLC5620)(通过4个按键输入,输出数模转换需要的数据和数码管显示需要的数据),觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
1.数模转换器即DAC,一般情况下由四个部分组成,权电阻网络,运算放大器,基准电源和模拟开关。是一种以二进制显示的数字量转换成以参考电压为基准的模拟量转换器。
2.设计原理:
TLC5620是一个拥有4路输出的数模转换器,时钟频率最高可以达到1MHZ,在本实例中它可以将输入的数字量转换为实际的模拟量(电压),并通过4个按键控制4路输出电压,每按一次,电压随之上升,同时数码管上依次显示相应的值:A1,A0,RNG,以及输入的数字量,采用开发板的基准电压2.5v。
芯片端口图:
点击此处添加图片说明文字
实际的电压公式是:V = REF*(CODE/256)*(1+RNG)
REF为基准电压,CODE为输入的8位数据,RNG为输入范围
3.key_test模块:按键控制通道选择
module key_test(
input clk,
input rst_n,
input [3:0] key, //4个按键组合信号
output [10:0] wr_data, //输出一帧数据
output [19:0] out_data //输出数码管的显示数据
);
reg [30:0] cnt; //计数器分频
reg clk_r; //分频时钟:在消抖的时钟频率下进行按键检测
reg [7:0] data; //按键输入的数据
reg [1:0] channel; //通道选择
reg [7:0] key1,key2,key3,key4; //4个按键
always @(posedge clk or negedge rst_n) //按键消抖,每0.2s进行一次检测
begin
if(!rst_n)
begin
cnt <= 0;
clk_r <= 0;
end
else if(cnt < 30'd1000_0000) //系统时钟5M,要0.2检测一次,就用50000000/(1/0.2)
cnt <= cnt + 1;
else
begin
cnt <= 0;
clk_r <= ~clk_r;
end
end
always @(posedge clk_r or negedge rst_n) //按键低电平有效,当检测到相应的按键按下时,
//相应数值加一,并显示相应的通道
begin
if(!rst_n)
begin
data <= 0;
channel <= 0;
key1 <= 0;
key2 <= 0;
key3 <= 0;
key4 <= 0;
end
else
case(key)
4'b1110:begin //按键1:选择通道A,输入数字量加一
channel <= 2'b00;
key1 <= key1 + 1'b1;
data <= key1;
end
4'b1101:begin //选择通道B,输入数字量加一
channel <= 2'b01;
key2 <= key2 + 1'b1;
data <= key2;
end
4'b1011:begin //选择通道C,输入数字量加一
channel <= 2'b10;
key3 <= key3 + 1'b1;
data <= key3;
end
4'b0111:begin //选择通道D,输入数字量加一
channel <= 2'b11;
key4 <= key4 + 1'b1;
data <= key4;
end
default : ;
endcase
end
//用赋值语句将需要的数据组合起来,在此例中RNG默认为1
assign wr_data = {channel,1'b1,data};
assign out_data = {3'b000,channel[1],3'b000,channel[0],4'h1,data};
endmodule
4.TLC_DA模块:数模转换芯片的驱动程序
点击此处添加图片说明文字
点击此处添加图片说明文字
module TLC_DA(
input clk,
input rst_n,
input [10:0] data_in, //输入一帧数据
output da_data, //串行数据接口
output da_clk, //串行时钟接口
output reg da_ladc, //更新控制信号
output reg da_load //串行加载控制接口
);
reg [30:0] cnt;
wire da_clk_r; //TLC5620内部的时钟信号
//计时器时钟分频:根据芯片内部的时序要求进行分频
always @(posedge clk or negedge rst_n) //频率不大于1MHZ
begin
if(!rst_n)
cnt <= 6'd0;
else
cnt <= cnt + 1'b1;
end
assign da_clk_r = cnt[5];
//接受时序的序列机
reg [2:0] state;
reg [3:0] cnt_da;
reg da_data_r;
reg da_data_en; //限定da_data和da_clk的有效区域
always @(posedge da_clk_r or negedge rst_n)
begin
if(!rst_n)
begin
state <= 0;
cnt_da <= 0;
da_data_r <= 1'b1;
da_data_en <= 0;
da_load <= 1;
da_ladc <= 0;
end
else
case(state)
0:state <= 1;
1:begin
da_data_en <= 1;
da_load <= 1;
if(cnt_da <= 10)
begin
cnt_da <= cnt_da + 1'b1;
case(cnt_da)
0:da_data_r <= data_in[10];
1:da_data_r <= data_in[9];
2:da_data_r <= data_in[8];
3:da_data_r <= data_in[7];
4:da_data_r <= data_in[6];
5:da_data_r <= data_in[5];
6:da_data_r <= data_in[4];
7:da_data_r <= data_in[3];
8:da_data_r <= data_in[2];
9:da_data_r <= data_in[1];
10:da_data_r <= data_in[0];
endcase
state <= 1;
end
else
begin
cnt_da <= 0;
state <= 2;
da_data_en <= 0;
end
end
2:begin
da_load <= 0;
state <= 3;
end
3:begin
da_load <= 1;
state <= 0;
end
default : state <= 0;
endcase
end
assign da_data = (da_data_en) ? da_data_r:1'b1;
assign da_clk = (da_data_en) ? da_clk_r:1'b0;
endmodule
5.seg_sum模块:数码管显示
处添加图片说明文字
点击此处添加图片说明文字
module seg_sum(
input clk,
input rst_n,
input [19:0] data_in, //20位输入数据
output reg [7:0] seg,
output reg [2:0] sel
);
reg [3:0] num; //数码管的位数
always@(*)
case(sel)
4:num = data_in[3:0]; //第5个数码管显示数据的低四位
3:num = data_in[7:4];
2:num = data_in[11:8];
1:num = data_in[15:12];
0:num = data_in[19:16];
default:;
endcase
always @(*)
case(num)
0:seg <= 8'hC0;
1:seg <= 8'hF9;
2:seg <= 8'hA4;
3:seg <= 8'hB0;
4:seg <= 8'h99;
5:seg <= 8'h92;
6:seg <= 8'h82;
7:seg <= 8'hF8;
0:seg <= 8'h80;
0:seg <= 8'h90;
default:seg <= 8'hFF;
endcase
//计数器分频:用cnt在第10位的变化作为分频时钟
reg [23:0] cnt;
always @(posedge clk or negedge rst_n)
if(!rst_n)
cnt <= 4'b0;
else
cnt <= cnt + 1'b1;
//在分频时钟下,数码管的0~4位依次循环
always @(posedge cnt[10] or negedge rst_n) //分频时钟为2的10次方除以50M
if(!rst_n)
sel <= 0;
else if(sel < 4)
sel <= sel + 1'b1;
else
sel <= 0;
endmodule
6.顶层文件:
module top(
input clk,
input rst_n,
input [3:0] key,
output da_data, //串行数据接口
output da_clk, //串行时钟接口
output da_ladc, //更新控制信号
output da_load, //串行加载控制接口
output [7:0] seg,
output [2:0] sel
);
//内部信号
wire [10:0] wr_data; //输出一帧数据
wire [19:0] out_data; //输出数码管的显示数据
//实例化
TLC_DA TLC_DA(
.clk(clk),
.rst_n(rst_n),
.da_data(da_data),
.da_clk(da_clk),
.da_ladc(da_ladc),
.da_load(da_load),
.data_in(wr_data)
);
key_test key_test(
.clk(clk),
.rst_n(rst_n),
.key(key),
.out_data(out_data),
.wr_data(wr_data)
);
seg_sum seg_sum(
.clk(clk),
.rst_n(rst_n),
.data_in(out_data),
.sel(sel),
.seg(seg)
);
endmodule
7.仿真测试文件
点击此处添加图片说明文字
`timescale 1 ns/ 1 ps
module TLC_DA_tb();
parameter T = 20;
/********************系统输入**********************/
reg clk;
reg rst_n;
reg [3:0] key;
/*********************系统输出*****************/
wire da_data;
wire da_clk;
wire da_ladc;
wire da_load;
initial
begin
clk = 1'b0;
rst_n = 1'b0;
key = 4'b1111;
#1000.1 rst_n = 1'b1;
#100 key = 4'b1110;
$stop;
end
always #(T/2) clk = ~clk;
TLC_DA TLC_DA(
.clk(clk),
.rst_n(rst_n),
.da_data(da_data),
.da_clk(da_clk),
.da_ladc(da_ladc),
.da_load(da_load),
.data_in(wr_data)
);
key_test key_test(
.clk(clk),
.rst_n(rst_n),
.key(key),
.out_data(out_data),
.wr_data(wr_data)
);
seg_sum seg_sum(
.clk(clk),
.rst_n(rst_n),
.data_in(out_data),
.sel(sel),
.seg(seg)
);
endmodule
8.RTL图
点击此处添加图片说明文字
工程文件上传至qq群:868412045
最后
以上就是沉静路灯为你收集整理的FPGA学习之数模转换(TLC5620)(通过4个按键输入,输出数模转换需要的数据和数码管显示需要的数据)的全部内容,希望文章能够帮你解决FPGA学习之数模转换(TLC5620)(通过4个按键输入,输出数模转换需要的数据和数码管显示需要的数据)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复