FPGA学习之模数转换(TLC549)(调节电位器改变ADC的模拟输入量,读取采样值后,数码管显示,并比较两个值)

点击此处添加图片说明文字

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

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值