点击此处添加图片说明文字
TLC549是模数转换芯片,只需要对外接时钟(clk),芯片选择(cs)和输入模拟信号(ANIN)进行控制,当cs被拉低时,ADC前一次转换数据的最高位立即出现在数据线DAT上,之后的数据在时钟下降沿来时改变
因为ADC的位宽为8bits,所以采样电压为v=(D*V(ref))/256
(D为ADC转换后读取的8位二进制数,V(ref)为参考电压)
1.TLC549芯片的驱动模块:
点击此处添加图片说明文字
module tcl549_Driver(
input clk,
input rst_n,
input en, //ADC转换使能,高电平有效
input ADC_in, //输入ADC的串行数据
output reg ADC_clk, //输出ADC的时钟
output reg ADC_cs, //输出ADC的片选信号
output reg Get_Flag, //新数据采集完成标志位
output reg [7:0] data //ADC转换以后的电压值
);
reg [10:0] cnt; //系统时钟计数器
reg [7:0] data_temp; //数据寄存器
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt <= 11'd0;
else if(!en)
cnt <= 11'd0;
else if(cnt == 1310)
cnt <= 11'd0;
else
cnt <= cnt + 1;
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
ADC_clk <= 0;
ADC_cs <= 1;
Get_Flag <= 0;
data <= 8'd0;
data_temp <= 8'd0;
end
else if(en)
begin
case(cnt)
1:ADC_cs <= 0; //1~71,因为内部电路在测得CS下降沿后,
//再等待两个内部时钟上升沿和一个下降沿后,然后确认这一变化,
//最后自动将前一次转换结果的最高位(D7)位输出到DATAOUT端上。
71:begin
ADC_clk <= 1;
data_temp[7] <= ADC_in;
end
96:ADC_clk <= 0;
121:begin
ADC_clk <= 1;
data_temp[6] <= ADC_in;
end
146:ADC_clk <= 0;
171:begin
ADC_clk <= 1;
data_temp[5] <= ADC_in;
end
196:ADC_clk <= 0;
221:begin
ADC_clk <= 1;
data_temp[4] <= ADC_in;
end
246:ADC_clk <= 0;
271:begin
ADC_clk <= 1;
data_temp[3] <= ADC_in;
end
296:ADC_clk <= 0;
321:begin
ADC_clk <= 1;
data_temp[2] <= ADC_in;
end
346:ADC_clk <= 0;
371:begin
ADC_clk <= 1;
data_temp[1] <= ADC_in;
end
396:ADC_clk <= 0;
421:begin
ADC_clk <= 1;
data_temp[0] <= ADC_in;
end
446:begin
ADC_clk <= 0;
ADC_cs <= 1;
Get_Flag <= 1;
end
447:begin
Get_Flag <= 0;
data <= data_temp;
end
1310:;
default : ;
endcase
end
else
begin
ADC_clk <= 0;
ADC_cs <= 1;
end
end
endmodule
2.数据控制模块
点击此处添加图片说明文字
module control(
input clk,
input rst_n,
input Get_Flag, //新数据采集完成标志位
input [7:0] ADC_data, //输入ADC采集数据
output reg [23:0] seg_data //数码管待显示的数据
);
reg [3:0] qianwei; //千位
reg [3:0] baiwei;
reg [3:0] shiwei;
reg [3:0] gewei;
reg [15:0] tenvalue; //采样的电压值
//采集电压值计算
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
tenvalue <= 0;
else
tenvalue <= (ADC_data*100*25)/256; //模数转换
end
//二进制转BCD码
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
qianwei <= 0;
baiwei <= 0;
shiwei <= 0;
gewei <= 0;
end
else
begin
qianwei <= tenvalue/1000;
baiwei <= (tenvalue/100)%10;
shiwei <= (tenvalue/10)%10;
gewei <= tenvalue%10;
end
end
//数码管显示数值
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
seg_data <= 0;
else
seg_data <= {qianwei,baiwei,shiwei,gewei,8'hFF}; //显示值
end
endmodule
3.数码管显示模块
点击此处添加图片说明文字
module dig_led_drive(
input clk,
input rst_n,
input [23:0] data, //待显示数据
output [7:0] dig_led_seg, //段选信号
output [7:0] dig_led_sel //位选信号
);
parameter system_clk = 50_000_000;
localparam cnt_max = 24; //在仿真时使用
//localparam localparam cnt_max = system_clk/1000/2 - 1; //在板级验证时使用
reg [14:0] cnt1; //分频计数器
reg clk_1k; //扫描时钟
reg [2:0] sel_r; //数码管的位选信号
reg [2:0] seg_r;
reg [3:0] disp_data; //显示数据缓存
//1khz的时钟分频计数器
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt1 <= 0;
else if(cnt1 == cnt_max)
cnt1 <= 0;
else
cnt1 <= cnt1 + 1;
end
//得到1khz的时钟
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
clk_1k <= 0;
else if(cnt1 == cnt_max)
clk_1k <= ~clk_1k;
end
//位选信号控制
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
sel_r <= 0;
else if(sel_r == 3)
sel_r <= 0;
else
sel_r <= sel_r + 1'b1;
end
//选择不同的待显示数据
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
disp_data <= 4'd0;
else
begin
case(sel_r)
3'd0:disp_data = data[23:20];
3'd1:disp_data = data[19:16];
3'd2:disp_data = data[15:12];
3'd3:disp_data = data[11:8];
3'd4:disp_data = data[7:4];
3'd5:disp_data = data[3:0];
endcase
end
end
always @(*)
begin
if(!rst_n)
seg_r <= 8'hff;
else
begin
case(disp_data)
4'd0:seg_r = 8'hc0;
4'd1:seg_r = 8'hf9;
4'd2:seg_r = 8'ha4;
4'd3:seg_r = 8'hb0;
4'd4:seg_r = 8'h99;
4'd5:seg_r = 8'h92;
4'd6:seg_r = 8'h82;
4'd7:seg_r = 8'hf8;
4'd8:seg_r = 8'h80;
4'd9:seg_r = 8'h90;
4'd10:seg_r = 8'h88;
4'd11:seg_r = 8'h83;
4'd12:seg_r = 8'hc6;
4'd13:seg_r = 8'ha1;
4'd14:seg_r = 8'h86;
4'd15:seg_r = 8'h8e;
default : seg_r <= 8'hff;
endcase
end
end
assign dig_led_seg = seg_r;
assign dig_led_sel = sel_r;
endmodule
4.顶层文件
点击
module AD_TLC549(
input clk,
input rst_n,
input ADC_in, //输入ADC的串行数据
output ADC_clk, //输出ADC的时钟
output ADC_cs, //输出ADC的片选信号
output [7:0] dig_led_seg, //段选信号
output [7:0] dig_led_sel //位选信号
);
wire Get_Flag;
wire ADC_data;
wire seg_data;
tcl549_Driver tcl549_Driver(
.clk(clk),
.rst_n(rst_n),
.en(1'b1),
.ADC_in(ADC_in),
.ADC_clk(ADC_clk),
.ADC_cs(ADC_cs),
.data(ADC_data),
.Get_Flag(Get_Flag)
);
control control(
.clk(clk),
.rst_n(rst_n),
.ADC_data(ADC_data),
.seg_data(seg_data),
.Get_Flag(Get_Flag)
);
dig_led_drive dig_led_drive(
.clk(clk),
.rst_n(rst_n),
.dig_led_seg(dig_led_seg),
.dig_led_sel(dig_led_sel),
.data(seg_data),
);
endmodule
此处添加图片说明文字
5.RTL图
点击此处添加图片说明文字
工程文件上传至qq群:868412045