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波形:

相关推荐
IM_DALLA10 小时前
【Verilog学习日常】—牛客网刷题—Verilog快速入门—VL21
学习·fpga开发
皇华ameya14 小时前
AMEYA360:村田电子更适合薄型设计应用场景的3.3V输入、12A输出的DCDC转换IC
fpga开发
千穹凌帝17 小时前
SpinalHDL之结构(二)
开发语言·前端·fpga开发
一口一口吃成大V1 天前
FPGA随记——FPGA时序优化小经验
fpga开发
贾saisai1 天前
Xilinx系FPGA学习笔记(九)DDR3学习
笔记·学习·fpga开发
redcocal1 天前
地平线秋招
python·嵌入式硬件·算法·fpga开发·求职招聘
思尔芯S2C2 天前
高密原型验证系统解决方案(下篇)
fpga开发·soc设计·debugging·fpga原型验证·prototyping·深度调试·多fpga 调试
坚持每天写程序2 天前
xilinx vivado PULLMODE 设置思路
fpga开发
redcocal2 天前
地平线内推码 kbrfck
c++·嵌入式硬件·mcu·算法·fpga开发·求职招聘
邹莉斯4 天前
FPGA基本结构和简单原理
fpga开发·硬件工程