目录

一、ADC

1.1 ADC简介

1.2 ADC驱动

1.3 线性序列机结构

二、代码编写

2.1 设计文件

2.2 激励文件

2.3 仿真图

三、ADC驱动模块调用

3.1 模块调用代码

3.2 板级测试


一、ADC

1.1 ADC简介

定义:模数转换器,用于将模拟信号转换为数字信号的电子元件
常见指标参数:
分辨率: 指 ADC 能分辨的最小信号变化,以输出数字码的位数表示(如 12 位、16 位)。位数越高,可量化的信号细节越精细,例如 12 位 ADC 能将满量程信号分为 4096 个等级。
采样范围: DC 能有效转换的信号范围,分单极性(如 0~5V)和双极性(如 - 10~+10V)。输入信号超出范围会导致失真,需根据实际信号选择匹配量程。
采样速率: 单位时间内的采样次数(单位:Hz 或 SPS),需满足奈奎斯特定理(采样率≥信号最高频率 2 倍)。例如,采样 10kHz 信号需至少 20kSPS 的速率,避免信号混叠失真。

1.2 ADC驱动

单次采集时序图

ADD2,ADD1,ADD0为通道选择信号

多次采集时序图

设计思路:
计数单元,定义两个计数器(①最小时间单位计数器,②对最小时间单位进行计数),用于表示时刻0~34;
对照时刻表,在0~34时刻,驱动信号进行相应的变化

1.3 线性序列机结构

  • 计数单元,本质上就是一个不停计数的计数器,用以计时得到最小时间单位
  • 序列计数器,用来标记每一个时间点
  • 驱动部分,负责根据时刻表中各个信号的值,在对应时间点驱动信号变化

二、代码编写

2.1 设计文件

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////

// Create Date: 2025/07/04 10:44:08
// Design Name: 
// Module Name: ADC128S102_Driver

module ADC128S102_Driver(
    clk,
	reset_n,
	
	addr,
	conv_go,
	
	conv_done,
	data,
	
	ADC_SCLK,
	ADC_CS_N,
	ADC_DIN,
	ADC_DOUT
    );
	input clk;
	input reset_n;
	input [2:0] addr;
	input conv_go;
	
	output reg conv_done;
	output reg [11:0] data;
	
	output reg ADC_CS_N;
	output reg ADC_DIN;
	output reg ADC_SCLK;
	
	input ADC_DOUT;
	
	reg [29:0] div_cnt;
	reg [5:0] bit_cnt;
	reg [2:0] r_addr;
	reg [11:0] r_data;
	
	reg conv_en;
	
	parameter clk_freq = 50_000_000;
	parameter SCLK_freq = 12_500_000;
	parameter mcnt_div = clk_freq/(SCLK_freq * 2)-1; //最小时间单位为周期的一半
	parameter mcnt_bit = 34;
	
	always @(posedge clk or negedge reset_n)
    if(!reset_n)
        conv_en <= 1'b0;
    else if(conv_go)
        conv_en <= 1'b1;
    else if((bit_cnt == mcnt_bit)&&(div_cnt == mcnt_div)) 
	    conv_en <= 1'b0;
	else 
	    conv_en <= conv_en;
	
	//最小时间单元计数器
	always @(posedge clk or negedge reset_n)
	if(!reset_n)
	   div_cnt <= 30'd0;
	else if(conv_en)begin
	   if(div_cnt == mcnt_div)
	        div_cnt <= 30'd0;
	   else
	       div_cnt <= div_cnt + 1'b1;
     end
	else
	    div_cnt <= 30'd0;
		
	//对最小时间单位进行位计数
	always @(posedge clk or negedge reset_n)
	if(!reset_n)
	    bit_cnt <= 6'd0;
    else if(div_cnt == mcnt_div) begin
	   if(bit_cnt == mcnt_bit)
	       bit_cnt <= 6'd0;
	   else
	       bit_cnt <= bit_cnt +1'b1;
	end
	else 
	    bit_cnt <= bit_cnt;
		
	//防止addr在驱动过程中发生变化,进行一级寄存
	always @(posedge clk)
	if(conv_go)
	   r_addr <= addr;
	else
	   r_addr <= r_addr;
	
	//驱动信号
	always @(posedge clk or negedge reset_n)
	if(!reset_n) begin
	    ADC_CS_N <= 1'b1;
		ADC_SCLK <= 1'b1;
		ADC_DIN <= 1'b1;
		r_data <= 12'd0;
	end
	else if(div_cnt == mcnt_div) begin
	   case(bit_cnt)
	   0:begin
	        ADC_CS_N <= 1'b1;
			ADC_SCLK <= 1'b1;
	     end
	   1:ADC_CS_N <= 1'b0;
	   2:ADC_SCLK <= 1'b0;
	   3:ADC_SCLK <= 1'b1;	
	   4:ADC_SCLK <= 1'b0;
	   5:ADC_SCLK <= 1'b1;
	   6:begin 
	       ADC_SCLK <= 1'b0;
		   ADC_DIN <= r_addr[2];
		 end
	   7:ADC_SCLK <= 1'b1;
	   8:begin 
	       ADC_SCLK <= 1'b0;
		   ADC_DIN <= r_addr[1];
		 end
	   9:ADC_SCLK <= 1'b1;
	   10:begin 
	       ADC_SCLK <= 1'b0;
		   ADC_DIN <= r_addr[0];
		 end
	   11:begin 
	        ADC_SCLK <= 1'b1;
            r_data[11] <= ADC_DOUT;			
		  end
	   12:ADC_SCLK <= 1'b0;
	   13:begin 
	        ADC_SCLK <= 1'b1;
            r_data[10] <= ADC_DOUT;			
		  end	
	   14:ADC_SCLK <= 1'b0;
	   15:begin 
	        ADC_SCLK <= 1'b1;
            r_data[9] <= ADC_DOUT;			
		  end	
	   16:ADC_SCLK <= 1'b0;
	   17:begin 
	        ADC_SCLK <= 1'b1;
            r_data[8] <= ADC_DOUT;			
		  end	
	   18:ADC_SCLK <= 1'b0;
	   19:begin 
	        ADC_SCLK <= 1'b1;
            r_data[7] <= ADC_DOUT;			
		  end	 
	   20:ADC_SCLK <= 1'b0;
	   21:begin 
	        ADC_SCLK <= 1'b1;
            r_data[6] <= ADC_DOUT;			
		  end
	   22:ADC_SCLK <= 1'b0;
	   23:begin 
	        ADC_SCLK <= 1'b1;
            r_data[5] <= ADC_DOUT;			
		  end	   
	   24:ADC_SCLK <= 1'b0;
	   25:begin 
	        ADC_SCLK <= 1'b1;
            r_data[4] <= ADC_DOUT;			
		  end
	   26:ADC_SCLK <= 1'b0;
	   27:begin 
	        ADC_SCLK <= 1'b1;
            r_data[3] <= ADC_DOUT;			
		  end
	   28:ADC_SCLK <= 1'b0;
	   29:begin 
	        ADC_SCLK <= 1'b1;
            r_data[2] <= ADC_DOUT;			
		  end
	   30:ADC_SCLK <= 1'b0;
	   31:begin 
	        ADC_SCLK <= 1'b1;
            r_data[1] <= ADC_DOUT;			
		  end
	   32:ADC_SCLK <= 1'b0;
	   33:begin 
	        ADC_SCLK <= 1'b1;
            r_data[0] <= ADC_DOUT;			
		  end
	   34:ADC_CS_N <= 1'b1;
	   endcase
	end	
	
	 //为了避免数据接收的过程中,未完成的结果条件在输出端口上,使用内部存储器存储数据结枿
	 always @(posedge clk or negedge reset_n)
	 if(!reset_n)begin
	     conv_done <= 1'b0;
		 data <= 12'd0;
	 end
	 else if((bit_cnt == mcnt_bit)&&(div_cnt == mcnt_div)) begin
	     conv_done <= 1'b1;
		 data <= r_data;
	 end
	 else begin
	 	 conv_done <= 1'b0;
		 data <= data;
	 end
endmodule

2.2 激励文件

`timescale 1ns / 1ps

// Create Date: 2025/07/04 13:14:54
// Design Name: 
// Module Name: ADC128S102_Driver_tb


module ADC128S102_Driver_tb;
     reg clk;
	 reg reset_n;
	 
	 reg [2:0] addr;
	 reg conv_go;
	 
	 wire conv_done;
	 wire [11:0] data;
	 
	 wire ADC_CS_N;
	 wire ADC_DIN;
	 wire ADC_SCLK;
	 
	 reg ADC_DOUT;


   ADC128S102_Driver ADC128S102_Driver_inst(
    .clk(clk),
	.reset_n(reset_n),
	
	.addr(addr),
	.conv_go(conv_go),
	
	.conv_done(conv_done),
	.data(data),
	
	.ADC_SCLK(ADC_SCLK),
	.ADC_CS_N(ADC_CS_N),
	.ADC_DIN(ADC_DIN),
	.ADC_DOUT(ADC_DOUT)
    );
	
	initial clk = 1'b1;
	always #10 clk = ~clk;
	
	initial begin
	reset_n =1'b0; 
	addr = 3'd0;
	conv_go = 1'b0;
	#201;
	reset_n = 1'b1;
	#200;
	conv_go = 1'b1;
	addr = 3'd3;
	#20;
	conv_go = 1'b0;
	wait(!ADC_CS_N);
	//16'H0A58 0000_1010_0101_1000
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b0; //DB15
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b0; //DB14
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b0; //DB13
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b0; //DB12
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b1; //DB11
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b0; //DB10
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b1; //DB9
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b0; //DB8
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b0; //DB7
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b1; //DB6
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b0; //DB5
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b1; //DB4
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b1; //DB3
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b0; //DB2
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b0; //DB1
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b0; //DB0
    wait(ADC_CS_N);
    #20000;	
	
    conv_go = 1'b1;
	addr = 3'd7;
	#20;
	conv_go = 1'b0;
	wait(!ADC_CS_N);
	//16'H089c 0000_1000_1001_1100
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b0; //DB15
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b0; //DB14
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b0; //DB13
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b0; //DB12
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b1; //DB11
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b0; //DB10
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b0; //DB9
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b0; //DB8
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b1; //DB7
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b0; //DB6
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b0; //DB5
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b1; //DB4
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b1; //DB3
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b1; //DB2
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b0; //DB1
	@(negedge ADC_SCLK)
	ADC_DOUT = 1'b0; //DB0
    wait(ADC_CS_N);
    #20000;	
	$stop;
	   
	end
	
	
endmodule

2.3 仿真图

三、ADC驱动模块调用

3.1 模块调用代码

`timescale 1ns / 1ps
// Create Date: 2025/07/04 15:35:36
// Design Name: 
// Module Name: ADC128S102_test

module ADC128S102_test(
       clk,
	reset_n,
	key,
	addr,
	led,	
	
	HEX8_DIO,
	HEX8_SRCLK,
	HEX8_RCLK,
	
	ADC_SCLK,
	ADC_CS_N,
	ADC_DIN,
	ADC_DOUT,
	
    );
	input clk;
	input reset_n;
	input key;
	input [2:0] addr;
	output reg led;
	
	output HEX8_DIO;
	output HEX8_SRCLK;
	output HEX8_RCLK;
	
	output ADC_SCLK;
	output ADC_CS_N;
	output ADC_DIN;
	input ADC_DOUT;
	
	wire [31:0] disp_data;

	wire conv_go;
	wire conv_done;
	wire [11:0] data;
	
	wire key_p_flag;
	
	assign disp_data={20'd0,data};
	//数码管驱动模块调用,将采集到的数据显示在数码管上
    hex8_hc595(
          .clk(clk),
	  .reset_n(reset_n),
	  .disp_data(disp_data),
	  .DIO(HEX8_DIO),
	  .SRCLK(HEX8_SRCLK),
          .RCLK(HEX8_RCLK)
    );
	
	//ADC模块调用
   ADC128S102_Driver ADC128S102_Driver_inst(
         .clk(clk),
	 .reset_n(reset_n),
	
	 .addr(addr),
   	 .conv_go(conv_go),
	
	 .conv_done(conv_done),
	 .data(data),
	
	 .ADC_SCLK(ADC_SCLK),
	 .ADC_CS_N(ADC_CS_N),
	 .ADC_DIN(ADC_DIN),
	 .ADC_DOUT(ADC_DOUT)
    );
	
	//按键消抖模块调用,使用按键指示conv_go开始采集信号
	key_filter(
	 .clk(clk),
 	 .reset_n(reset_n),
	 .key(key),
 	 .key_p_flag(key_p_flag),
 	 .key_r_flag(),
	 .key_state()
	);
	
	assign conv_go =key_p_flag;
	
	//LED指示模块
	always @(posedge clk or negedge reset_n)
	if(!reset_n)
	   led <= 1'b0;
	else if(conv_done)
	   led <=~led;
	else  
	   led <= led;
endmodule

3.2 板级测试

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐