47.简易电压表的设计与验证(2)

(1)Verilog 代码:

module adc_collect(
    input                   clk         ,
    input                   reset_n     ,
    input   [7:0]           adc_data    ,
    
    output                  clk_adc     
    
);
    wire                clk_adc_a       ;
    wire                clk_adc_turn    ;
    wire                locked          ;
    wire    [31:0]      n_volt          ;
    wire    [31:0]      p_volt          ;
    wire    [31:0]      data_n          ;
    wire    [31:0]      data_p          ;
    
    reg     [10:0]      ad_cnt          ;
    reg     [19:0]      sum_ad          ;
    reg     [27:0]      adc_mid         ;
    reg     [31:0]      volt_n          ;
    reg     [31:0]      volt_p          ;
    
 assign clk_adc = clk_adc_a  ; 

pll_20M         pll_20M_inst
(
    .clk_adc(clk_adc_a),                  // output clk_adc
    .clk_adc_turn(clk_adc_turn),        // output clk_adc_turn
    .resetn(reset_n),                    // input resetn
    .locked(locked),                    // output locked
    .clk(clk)                           // input clk
);      

ila_volt        ila_volt_inst
(
	.clk(clk),                       // input wire clk
	.probe0(n_volt),                // input wire [31:0]  probe0  
	.probe1(p_volt)                 // input wire [31:0]  probe1
);

//adc累加计数器
always@(posedge clk_adc_turn or negedge locked)
    if(!locked)    
        ad_cnt  <= 11'd0;
    else if(ad_cnt == 11'd1025)
        ad_cnt  <= 11'd1025;
    else 
        ad_cnt  <= ad_cnt + 11'd1;

//adc前1024个数据累加       
always@(posedge clk_adc_turn or negedge locked)
    if(!locked)
        sum_ad <= 20'd0;
    else if(ad_cnt <= 11'd1024)
        sum_ad <= sum_ad + adc_data;
    else    
        sum_ad <= sum_ad;

//adc中值计算     
always@(posedge clk_adc_turn or negedge locked)
    if(!locked)
        adc_mid <= 28'd0;
    else if(ad_cnt == 11'd1024)
        adc_mid <= sum_ad >> 10;
    else if(ad_cnt == 11'd1025)
        adc_mid <= adc_mid;
    else 
        adc_mid <= 28'd0;
        
//精度定义   显示数据为4位数,其中第一位为个位,后三位为十分位,百分位,千分位。     40960_000 = 5* 2^13 * 1000
    assign data_n = (ad_cnt == 11'd1025)? 40960_000/(adc_mid + 1) : 0;
    assign data_p = (ad_cnt == 11'd1025)? 40960_000/(256 - adc_mid) : 0;    
        
//电压计算
always@(posedge clk_adc_turn or negedge locked)
    if(!locked)
        volt_n <= 32'd0;
    else if((ad_cnt == 11'd1025) && (adc_data < adc_mid))
        volt_n <= (data_n * (adc_mid - adc_data)) >> 13;
    else    
        volt_n <= 32'd0;
        
always@(posedge clk_adc_turn or negedge locked)
    if(!locked)
        volt_p <= 32'd0;
    else if((ad_cnt == 11'd1025) && (adc_data >= adc_mid))
        volt_p <= (data_n * (adc_data - adc_mid)) >> 13;
    else    
        volt_p <= 32'd0;   

//传入ILA
    assign n_volt = volt_n;
    assign p_volt = volt_p;
        
endmodule

(2)仿真文件:

`timescale 1ns / 1ps

module adc_collect_tb;

reg         clk         ;
reg         clk_sample  ;
reg         reset_n     ;
reg   [7:0] adc_data    ;
reg   [7:0] data_reg    ;
reg         data_en     ;

wire        clk_adc     ;

initial clk = 1'd1;
always #10 clk = ~clk;

initial clk_sample = 1'd1;
always #25 clk_sample = ~clk_sample;

initial begin
    reset_n <= 1'd0;
    #25;
    reset_n <= 1'd1;
    #200; 
    data_en <= 1'd0;
    #2000000;
    data_en <= 1'd1;    
    #2000000;
    $stop;
end

    always@(posedge clk_sample or negedge reset_n)
        if(!reset_n)
            data_reg <= 8'd0;
        else if(data_en)
            data_reg <= data_reg + 8'd1;
        else 
            data_reg <= 8'd0;
            
    always@(posedge clk_sample or negedge reset_n)
        if(!reset_n)
            adc_data <= 8'd0;
        else if(!data_en)
            adc_data <= 8'd125;
        else 
            adc_data <= data_reg ;
            
adc_collect     adc_collect_inst(
    .clk         (clk),
    .reset_n     (reset_n),
    .adc_data    (adc_data),

    .clk_adc     (clk_adc)
    
);


endmodule

(3)仿真波形(仿真前先把ILA注释掉):

  • 整体波形图:
  • PLL时钟波形图:

  • 求中值中,累加计数器和中间值的计算:

  • 后续dac数据的赋值以及精度的波形:

  • 数值波形:

(4)XDC文件:

set_property IOSTANDARD LVCMOS33 [get_ports {adc_data[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {adc_data[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports clk_adc]
set_property IOSTANDARD LVCMOS33 [get_ports {adc_data[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {adc_data[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {adc_data[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports reset_n]
set_property IOSTANDARD LVCMOS33 [get_ports {adc_data[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports {adc_data[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {adc_data[2]}]
set_property PACKAGE_PIN W19 [get_ports clk]
set_property PACKAGE_PIN N15 [get_ports reset_n]
set_property PACKAGE_PIN L13 [get_ports {adc_data[0]}]
set_property PACKAGE_PIN M13 [get_ports {adc_data[1]}]
set_property PACKAGE_PIN M16 [get_ports {adc_data[2]}]
set_property PACKAGE_PIN M15 [get_ports {adc_data[3]}]
set_property PACKAGE_PIN M20 [get_ports {adc_data[4]}]
set_property PACKAGE_PIN N20 [get_ports {adc_data[5]}]
set_property PACKAGE_PIN M22 [get_ports {adc_data[6]}]
set_property PACKAGE_PIN N22 [get_ports {adc_data[7]}]
set_property PACKAGE_PIN L14 [get_ports clk_adc]

(5)实验现象:

编译遇到报错:

解决方法:

未接线,0v时,ILA波形:

-2.3v时,ILA波形:

-1.5v时,ILA波形:

0.5v时,ILA波形:

2.7v时,ILA波形:

3.75v时,ILA波形:

4.85v时,ILA波形:

相关推荐
学习路上_write2 分钟前
FPGA/Verilog,Quartus环境下if-else语句和case语句RT视图对比/学习记录
单片机·嵌入式硬件·qt·学习·fpga开发·github·硬件工程
jjjxxxhhh1231 小时前
FPGA,使用场景,相比于单片机的优势
单片机·嵌入式硬件·fpga开发
诚实可靠小郎君95276 小时前
FPGA高速设计之Aurora64B/66B的应用与不足的修正
fpga开发·aurora·高速通信
百锦再6 小时前
基于Zynq FPGA对雷龙SD NAND的测试
fpga开发
∑狸猫不是猫18 小时前
HDLBIts习题(4):边沿检测、分频计数器、多位BCD计数器
fpga开发
黑旋风大李逵1 天前
FPGA使用Verilog实现CAN通信
fpga开发·can通信·sja1000t·fpga实现can通信
hi941 天前
PYNQ 框架 - 中断(INTR)驱动
嵌入式硬件·fpga开发·zynq·pynq
transfer_ICer2 天前
Vscode搭建verilog开发环境
vscode·fpga开发·编辑器
沐欣工作室_lvyiyi3 天前
汽车牌照识别系统的设计与仿真(论文+源码)
人工智能·单片机·fpga开发·汽车·单片机毕业设计·matlab车牌识别
绅士羊OuO3 天前
FPGA学习笔记#5 Vitis HLS For循环的优化(1)
c++·笔记·嵌入式硬件·学习·fpga开发