糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > FPGA 30 综合数字ADC /DAC 信号发送采集系统设计(综合项目设计)

FPGA 30 综合数字ADC /DAC 信号发送采集系统设计(综合项目设计)

时间:2024-06-29 14:20:52

相关推荐

FPGA 30 综合数字ADC /DAC 信号发送采集系统设计(综合项目设计)

FPGA 30 综合数字ADC /DAC 信号发送采集系统设计(综合项目设计)

模块名称 : 综合数字ADC /DAC 信号发送采集系统设计

主要功能 :本实验设计了一个信号发送和采集系统的设计,在整个系统中,基于原先学习的key_filter 按键滤波模块,adc_12s022 模数转换驱动模块,dac_tlv5618 数模转换驱动模块,DAC_rom_siganl 信号rom存储器控制器模块,FIFO模块、FIFO_send_ctrl FIFO发送控制模块和uart_tx 串口发送模块构成了整个综合的实验系统。

输入信号有 : Key_in 、 Clk 、 Rst_n、 ADC_DOUT

输出信号有 :Rs232_Tx 、 ( ADC_CS_N 、ADC_DIN、ADC_SCLK) ( DAC_SCLK、DAC_DIN、DAC_CS_N)。

实现功能(设计思想/流程)是: 通过按键Key_in 按下,按键滤波以后,通过接收按键标志信号(key_flag) 和 按键状态信号(key_state) 输出给 按键控制采样模块,该模块通过判断FIFO数据是否已满、AD转换是否已经完成整这个3个信号来输出Ad_En_Conv 信号,即判断是否启动ADC 驱动模块开始电压(信号),并且内部该模块实现连续的100次采集,采集100次的数据信号,存储在中间的FIFO中,同时,本次使用的FIFO是一个单时钟,输入输出位宽相同的FIFO,在fifo_send_ctrl 模块,通过FIFO模块的FIFO_almost_empty 和 empty 信号输入给fifo_send_ctrl 模块,并且将器转换为标准的8bit发送的串口格式数据发送给uart_byte_tx 模块。此外,我们的信号也是通过fpga的rom资源来存储信号,并设计控制模块,驱动设计的dac_tlv5618 数模转换模块,并在外部的模拟信号连接到adc_128s022 的我们设定的采样通道。配合上半部分的电路连接,进而完成整个系统的设计。

1、首先实现整个系统设计图的下半部分

即:DAC信号存储控制模块的设计 DAC_rom_signal.v

module DAC_rom_signal(Clk,Rst_n,DAC_State,DAC_DATA,Data_Start);input Clk ;input Rst_n;input DAC_State;output [15:0]DAC_DATA;output reg Data_Start;reg [11:0]address;wire clock ;wire [11:0]q;DAC_romDAC_rom0(.address(address),.clock(clock),.q(q));reg [31:0]timer_cnt ;reg timer_full_flag ; parameter Timer_Cnt_Full = 5_000_000 ; // 0.01s 循环定时 // 1S 循环计时 50_000_000 3s 150_000_000 clk div parameterreg r_Data_Start ; // 信号延时一个时钟// 定时器脉冲信号always@(posedge Clk or negedge Rst_n)if(!Rst_n)timer_cnt <= 32'd0;else if(timer_cnt == (Timer_Cnt_Full - 1'b1))timer_cnt <= 32'd0 ; //定时计数器清零elsetimer_cnt <= timer_cnt + 1'b1 ;// timer_full_flagalways@(posedge Clk or negedge Rst_n)if(!Rst_n)timer_full_flag <= 1'd0;else if(timer_cnt == (Timer_Cnt_Full - 1'b1))timer_full_flag <= 1'd1;elsetimer_full_flag <= 1'd0;assign clock = timer_full_flag ;// reg [3:0]address ; always@(posedge Clk or negedge Rst_n)if(!Rst_n)address <= 4'd0 ;else if(timer_full_flag)address <= address +1'b1; // address 到 4095后会自动清零,相当于循环elseaddress <= address ;// Data_Start DAC_DATA <= 1'b0;// 启动信号延时一个时钟周期 reg r_Data_Start ;always@(posedge Clk or negedge Rst_n)if(!Rst_n)r_Data_Start <= 1'b0 ;else if(timer_full_flag && DAC_State)r_Data_Start <= 1'b1 ;elser_Data_Start <= 1'b0 ;// 延时一个时钟节拍,保证信号可以跟新当前的DA数据always@(posedge Clk or negedge Rst_n)if(!Rst_n)Data_Start <= 1'b0 ;elseData_Start <= r_Data_Start ;assign DAC_DATA = {4'b0100,q} ; // 4'b0100 ,给通道1 发送信号endmodule

第2步 、dac_tlv5618.v dac芯片驱动设计

module dac_tlv5618(Clk,Rst_n,DAC_DATA,Start,Set_Done,DAC_CS_N,DAC_DIN,DAC_SCLK,DAC_State);input Clk;input Rst_n;input [15:0]DAC_DATA;input Start;output reg Set_Done;output reg DAC_CS_N;output reg DAC_DIN;output reg DAC_SCLK;output DAC_State;assign DAC_State = DAC_CS_N;reg en;parameter DIV_PARAM = 2 ; // clk div parameterreg [3:0]DIV_CNT;reg SCLK2X;reg [5:0]SCLK_GEN_CNT ; // 状态机半周期计数个数wire trans_done ;// clk_div// reg [15:0]r_DAC_DATA ;always@(posedge Clk or negedge Rst_n)if(!Rst_n)r_DAC_DATA <= 16'd0;else if(Start)r_DAC_DATA <= DAC_DATA;elser_DAC_DATA <= r_DAC_DATA;// en singal handlealways@(posedge Clk or negedge Rst_n)if(!Rst_n)en <= 1'b0;else if(Start)en <= 1'b1 ;else if(trans_done)en <= 1'b0;elseen <= en ;// div_clk --> 12.5Mhz// reg [3:0]DIV_CNT;always@(posedge Clk or negedge Rst_n)if(!Rst_n)DIV_CNT <= 4'd0;else if(en)beginif(DIV_CNT == DIV_PARAM -1'b1)DIV_CNT <= 4'd0;elseDIV_CNT <= DIV_CNT + 1'd1;endelseDIV_CNT <= 4'd0;//生成2倍SCLK使能脉冲,时钟计数器 //reg SCLK2X;always@(posedge Clk or negedge Rst_n)if(!Rst_n)SCLK2X <= 1'b0 ;else if(en && (DIV_CNT == (DIV_PARAM -1'b1) )) // must add en singal SCLK2X <= 1'b1;else SCLK2X <= 1'b0;// 状态机半周期计数// reg [5:0]SCLK_GEN_CNT ;always@(posedge Clk or negedge Rst_n)if(!Rst_n)SCLK_GEN_CNT <= 6'd0;else if(SCLK2X && en)beginif(SCLK_GEN_CNT == 6'd33)SCLK_GEN_CNT <= 6'd0;elseSCLK_GEN_CNT <= SCLK_GEN_CNT +1'b1 ;endelseSCLK_GEN_CNT <= SCLK_GEN_CNT ;// state machine handle// DAC_CS_N; DAC_DIN; DAC_SCLK;always@(posedge Clk or negedge Rst_n)if(!Rst_n)beginDAC_CS_N <= 1'd1;DAC_DIN <= 1'd0;DAC_SCLK <= 1'd1;endelse if(SCLK2X && (!Set_Done)) begincase(SCLK_GEN_CNT)0 : begin DAC_CS_N <= 1'b0 ; DAC_SCLK <= 1'b1 ; DAC_DIN <= r_DAC_DATA[15]; end2 : begin DAC_SCLK <= 1'b1 ; DAC_DIN <= r_DAC_DATA[14]; end4 : begin DAC_SCLK <= 1'b1 ; DAC_DIN <= r_DAC_DATA[13]; end6 : begin DAC_SCLK <= 1'b1 ; DAC_DIN <= r_DAC_DATA[12]; end8 : begin DAC_SCLK <= 1'b1 ; DAC_DIN <= r_DAC_DATA[11]; end10 : begin DAC_SCLK <= 1'b1 ; DAC_DIN <= r_DAC_DATA[10]; end12 : begin DAC_SCLK <= 1'b1 ; DAC_DIN <= r_DAC_DATA[9]; end14 : begin DAC_SCLK <= 1'b1 ; DAC_DIN <= r_DAC_DATA[8]; end16 : begin DAC_SCLK <= 1'b1 ; DAC_DIN <= r_DAC_DATA[7]; end18 : begin DAC_SCLK <= 1'b1 ; DAC_DIN <= r_DAC_DATA[6]; end20 : begin DAC_SCLK <= 1'b1 ; DAC_DIN <= r_DAC_DATA[5]; end22 : begin DAC_SCLK <= 1'b1 ; DAC_DIN <= r_DAC_DATA[4]; end24 : begin DAC_SCLK <= 1'b1 ; DAC_DIN <= r_DAC_DATA[3]; end26 : begin DAC_SCLK <= 1'b1 ; DAC_DIN <= r_DAC_DATA[2]; end28 : begin DAC_SCLK <= 1'b1 ; DAC_DIN <= r_DAC_DATA[1]; end30 : begin DAC_SCLK <= 1'b1 ; DAC_DIN <= r_DAC_DATA[0]; end32:begin DAC_SCLK <= 1'b1 ; end33 : begin DAC_CS_N <= 1'b1 ; end1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31: begin DAC_SCLK <= 1'b0 ; enddefault: ;endcaseendassign trans_done = (SCLK_GEN_CNT == 33) && SCLK2X ;// Set_Done handlealways@(posedge Clk or negedge Rst_n)if(!Rst_n)Set_Done <= 1'b0;else if(trans_done)Set_Done <= 1'b1;elseSet_Done <= 1'b0;endmodule

通过1、2步骤,可以实现连续信号发生器的设计。

第3部分 按键滤波模块 key_filter.v

//定义按键函数端口module key_filter(Clk ,Rst_n ,key_in ,key_flag, //检测按键成功信号key_state //实时的信号);input Clk ;input Rst_n ;input key_in ;output reg key_flag ;output reg key_state ;//定义状态机localparamIDEL = 4'b0001 ,FILTER0= 4'b0010 ,DOWN = 4'b0100 ,FILTER1= 4'b1000 ;//定义使用到的寄存器reg [3:0]state ;reg key_tmp0 , key_tmp1 ; // key_in 的状态寄存器wire pedge , nedge ;reg en_cnt_20ms ;reg [19:0]cnt_20ms ;reg cnt_20ms_full ;//对外部输入的异步信号key_in进行同步处理reg key_in_sa,key_in_sb;always@(posedge Clk or negedge Rst_n)if(!Rst_n)beginkey_in_sa <= 1'b0;key_in_sb <= 1'b0;endelse beginkey_in_sa <= key_in;key_in_sb <= key_in_sa;end//获取上一个周期的 按键电平 和当前 按键电平//目的: 获取 按键状态判断是否是下降沿还是上升沿到来always@(posedge Clk or negedge Rst_n)if(Rst_n == 1'b0) beginkey_tmp0 <= 1'b0 ;key_tmp1 <= 1'b0 ;endelse begin //每次时钟上升沿到来,两个寄存器读取上一次的数据的值key_tmp0 <= key_in_sb;key_tmp1 <= key_tmp0;end// 下降沿和上升沿到来标志位信号assign nedge = ((~key_tmp0 ) & ( key_tmp1)) ; //判断下降沿是否到来? //分析:: 下降沿到来的清况是高电平-->低电平的变换过程,也就是说://key_tmp1 存的前1个时刻的电平,// key_tmp0 存的是当前时刻的电平,// 要满足该条件,也就是说, key_tmp0 <= 0 且 key_tmp1 <= 1; 此时得到 nedge = 1 ;assign pedge = key_tmp0 & (!key_tmp1) ; //判断上升沿是否到来?//状态机判断always@(posedge Clk or negedge Rst_n)if(!Rst_n) //复位状态下,状态机处于空闲状态 beginstate <= IDEL ; //复位状态下,状态机处于空闲模式下en_cnt_20ms <= 1'b0 ; //消抖计数器关闭key_flag <= 1'b0 ; //按键成功标志位清零key_state <= 1'b1 ; //默认输入按键状态高电平endelse begincase(state)IDEL :beginkey_flag <= 1'b0 ;//空闲状态下,按键成功标志位永远为0if(nedge == 1'b1) begin//按键检测到下降沿到来state <= FILTER0 ;//进入下一个案件滤波状态en_cnt_20ms <= 1 ;//开启使能计数20msendelsestate <= IDEL ;//未检测到下降沿到来,信号状态保持不变endFILTER0:if(cnt_20ms_full == 1'b1) begin //看消除抖动20ms后,且20ms内没有检测到上升沿到来 = 20mskey_flag <= 1'b1;//表示按键已经成功按下key_state<= 1'b0;//此时输入按键按下输出状态为低电平state <= DOWN ;//进入下一状态en_cnt_20ms <= 0 ;//20ms计数器关闭endelse if(pedge == 1'b1) begin//没有满20ms 以内,有上升沿的到来,表明此时是抖动信号,非按键按下信号state <= IDEL ;en_cnt_20ms <= 0 ;//计数器关闭endelse//上述两者情况均为出现,则状态机保持不变state <= FILTER0 ;DOWN:begin key_flag <= 1'b0; //检测到有按键按下,发送一个脉冲信号,由上一个状态的高电平变为低电平if(pedge == 1'b1) begin //上一个状态时间超过20ms,此时需要一直等待上升沿的到来(做为按键松开的标志)state <= FILTER1 ;//进入到下一状态en_cnt_20ms <= 1'b1 ;//开启下一次20ms 延时计数endelse //没有,则保持该状态state <= DOWN ;endFILTER1:if(cnt_20ms_full == 1'b1) begin//表示 20ms计数又一次到来,此时按键稳定key_flag <= 1'b1;//表示上升沿的信号稳定的信号,随后到 IDEL又会设置为低电平,产生一个脉冲信号key_state<= 1'b1; //此时输入按键按下状态为低电平en_cnt_20ms <= 1'b0 ; //关闭20ms定时器state <=IDEL ;endelse if(nedge)begin// 20ms内又出现了下降沿,表示这是一次抖动en_cnt_20ms <= 1'b0 ;state <= DOWN ;endelse//20ms内状态保持不变state <=FILTER1 ;default:beginstate <= IDEL ; key_flag <= 1'b0;key_state<= 1'b1;//默认状态时 1 高电平en_cnt_20ms <= 1'b0 ; //默认状态时 0 低电平endendcaseend//定时器启动 always块always@(posedge Clk or negedge Rst_n)if(!Rst_n)cnt_20ms <= 20'd0;else if(en_cnt_20ms)cnt_20ms <= cnt_20ms + 1'b1;else // 关闭时,计时器清零cnt_20ms <= 20'd0;//定时器20ms always块 50Mhz 20ms = cnt_20ms : 1_000_000always@(posedge Clk or negedge Rst_n)if(Rst_n == 1'b0)cnt_20ms_full <= 0 ;else if(cnt_20ms == 20'd999_999)cnt_20ms_full <= 1'b1 ; //计数值计满标志位elsecnt_20ms_full <= 1'b0 ;// 未挤满,输出0endmodule

第4部分: ctrl_sample 通过按键按下滤波后的信号,控制ADC 驱动,完成连续的100次信号采集

// 模块功能,每次按键按下,使用控制AD 100次信号采样// 采样的信号 存放到fifo中。module ctrl_sample(Clk,Rst_n,key_flag ,key_state ,Ad_Conv_Done,Fifo_almost_full,Ad_En_Conv);input Clk;input Rst_n;input key_flag ;input key_state ;input Ad_Conv_Done;input Fifo_almost_full;output reg Ad_En_Conv;parameter SAMPLE_TIMES = 100 ; //每次采样次数reg [6:0]sample_cnt ;// key_state key_flag// Ad_En_Conv ;reg en_flag ;always@(posedge Clk or negedge Rst_n)if(!Rst_n)en_flag <= 1'b0 ;else if(key_flag && (!key_state))beginif(Fifo_almost_full)en_flag <= 1'b0;elseen_flag <= 1'b1;endelse if(Fifo_almost_full || (sample_cnt== (SAMPLE_TIMES-1)) )en_flag <= 1'b0;elseen_flag <= en_flag ;// Ad_En_Conv handlealways@(posedge Clk or negedge Rst_n)if(!Rst_n)Ad_En_Conv <= 1'b0 ;else if(key_flag && (!key_state))beginif(Fifo_almost_full)Ad_En_Conv <= 1'b0;elseAd_En_Conv <= 1'b1;endelse if(en_flag && Ad_Conv_Done)Ad_En_Conv <= 1'b1;elseAd_En_Conv <= 1'b0;// Ad_Conv_Done// Ad_En_Conv// sample_cntalways@(posedge Clk or negedge Rst_n)if(!Rst_n)sample_cnt <= 7'b0 ;else if(Ad_Conv_Done)beginif(sample_cnt == (SAMPLE_TIMES-1) )sample_cnt <=7'd0;elsesample_cnt <= sample_cnt +1'b1;endelsesample_cnt <= sample_cnt ;endmodule

第5部分: ad128s022.v 芯片驱动模块,可以设置采样通道、采样频率等基本输入参数,即可驱动信号。

module ad128s022(Clk,Rst_n,Channel,Data,En_Conv,Conv_Done,ADC_State,DIV_PARAM,ADC_SCLK,ADC_DOUT,ADC_DIN,ADC_CS_N);input Clk;input Rst_n;input [2:0]Channel;output reg [11:0]Data;input En_Conv;output reg Conv_Done;output ADC_State;input [7:0]DIV_PARAM;output reg ADC_SCLK;input ADC_DOUT;output reg ADC_DIN;output reg ADC_CS_N;reg en ;reg [2:0]r_Channel;reg [7:0]DIV_CNT ;reg SCLK2X ;reg [5:0]SCLK_GEN_CNT;reg [11:0]r_Data;// en handle always@(posedge Clk or negedge Rst_n)if(!Rst_n)en <= 1'b0;else if(En_Conv)en <= 1'b1;else if(Conv_Done)en <= 1'b0 ;elseen <= en ;// r_Channel we set En_Conv is a plus signal always@(posedge Clk or negedge Rst_n)if(!Rst_n)r_Channel <= 3'd0;else if(En_Conv)r_Channel <= Channel;elser_Channel <= r_Channel;// 时钟分频脉冲计数// reg [7:0]DIV_CNT ;always@(posedge Clk or negedge Rst_n)if(!Rst_n)DIV_CNT <= 8'd0 ;else if(en)beginif(DIV_CNT == (DIV_PARAM -1) )DIV_CNT <= 8'd0 ;elseDIV_CNT <= DIV_CNT + 1'd1 ;endelseDIV_CNT <= 8'd0 ;// SCLK2X plus// reg SCLK2Xalways@(posedge Clk or negedge Rst_n)if(!Rst_n)SCLK2X <= 1'b0;else if(DIV_CNT == (DIV_PARAM -1) )SCLK2X <= 1'b1 ;elseSCLK2X <= 1'b0;// reg [5:0]SCLK_GEN_CNT always@(posedge Clk or negedge Rst_n)if(!Rst_n)SCLK_GEN_CNT <= 6'd0 ;else if(en && SCLK2X)beginif(SCLK_GEN_CNT == 6'd33)SCLK_GEN_CNT <=6'd0;elseSCLK_GEN_CNT <= SCLK_GEN_CNT + 1'b1 ;endelseSCLK_GEN_CNT <= SCLK_GEN_CNT ;///*output ADC_SCLKinput ADC_DOUT;output ADC_DIN;output reg ADC_CS_N;reg [11:0]r_Data;*/always@(posedge Clk or negedge Rst_n)if(!Rst_n)beginADC_SCLK <= 1'b1;ADC_DIN <= 1'b0;ADC_CS_N <= 1'b1;endelse if(en && SCLK2X)begincase(SCLK_GEN_CNT)0: begin ADC_CS_N <= 1'b0; ADC_SCLK <= 1'b1; ADC_DIN <= 1'b0; end1,3: begin ADC_SCLK <= 1'b0; end2,4,6,8: begin ADC_SCLK <= 1'b1 ; end5: begin ADC_SCLK <= 1'b0; ADC_DIN <= r_Channel[2]; end7: begin ADC_SCLK <= 1'b0; ADC_DIN <= r_Channel[1]; end9: begin ADC_SCLK <= 1'b0; ADC_DIN <= r_Channel[0]; end10: begin ADC_SCLK <= 1'b1; r_Data[11] <= ADC_DOUT ; end12: begin ADC_SCLK <= 1'b1; r_Data[10] <= ADC_DOUT ; end14: begin ADC_SCLK <= 1'b1; r_Data[9] <= ADC_DOUT ; end16: begin ADC_SCLK <= 1'b1; r_Data[8] <= ADC_DOUT ; end18: begin ADC_SCLK <= 1'b1; r_Data[7] <= ADC_DOUT ; end20: begin ADC_SCLK <= 1'b1; r_Data[6] <= ADC_DOUT ; end22: begin ADC_SCLK <= 1'b1; r_Data[5] <= ADC_DOUT ; end24: begin ADC_SCLK <= 1'b1; r_Data[4] <= ADC_DOUT ; end26: begin ADC_SCLK <= 1'b1; r_Data[3] <= ADC_DOUT ; end28: begin ADC_SCLK <= 1'b1; r_Data[2] <= ADC_DOUT ; end30: begin ADC_SCLK <= 1'b1; r_Data[1] <= ADC_DOUT ; end32: begin ADC_SCLK <= 1'b1; r_Data[0] <= ADC_DOUT ; end11,13,15,17,19,21,23,25,27,29,31: begin ADC_SCLK <= 1'b0; end33: begin ADC_CS_N <= 1'b1; enddefault: ;endcaseend// output [11:0]Data always@(posedge Clk or negedge Rst_n)if(!Rst_n)Data <= 12'd0 ;else if(en && SCLK2X && (SCLK_GEN_CNT == 6'd33))Data <= r_Data ;elseData <= Data ;// conv_Done signalalways@(posedge Clk or negedge Rst_n)if(!Rst_n)Conv_Done <= 1'd0 ;else if(en && SCLK2X && (SCLK_GEN_CNT == 6'd33))Conv_Done <= 1'd1 ;elseConv_Done <= 1'd0 ;//产生ADC工作状态指示信号,保持和CS片选信号同步即可assign ADC_State = ADC_CS_N ; endmodule

第6部分、FIFO模块,注:这个一般来说,是调用内部IP 核来实现的,主要是看FIFO的配置,可以看一下 FPGA22 FIFO 的实现

// megafunction wizard: %FIFO%// GENERATION: STANDARD// VERSION: WM1.0// MODULE: scfifo // ============================================================// File Name: AD_fifo.v// Megafunction Name(s):// scfifo//// Simulation Library Files(s):// // ============================================================// ************************************************************// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!//// 13.0.0 Build 156 04/24/ SJ Full Version// ************************************************************//Copyright (C) 1991- Altera Corporation//Your use of Altera Corporation's design tools, logic functions //and other software and tools, and its AMPP partner logic //functions, and any output files from any of the foregoing //(including device programming or simulation files), and any //associated documentation or information are expressly subject //to the terms and conditions of the Altera Program License //Subscription Agreement, Altera MegaCore Function License //Agreement, or other applicable license agreement, including, //without limitation, that your use is for the sole purpose of //programming logic devices manufactured by Altera and sold by //Altera or its authorized distributors. Please refer to the //applicable agreement for further details.// synopsys translate_off`timescale 1 ps / 1 ps// synopsys translate_onmodule AD_fifo (clock,data,rdreq,sclr,wrreq,almost_empty,almost_full,empty,full,q,usedw);input clock;input[11:0] data;input rdreq;input sclr;input wrreq;output almost_empty;output almost_full;output empty;output full;output[11:0] q;output[9:0] usedw;wire [9:0] sub_wire0;wire sub_wire1;wire sub_wire2;wire [11:0] sub_wire3;wire sub_wire4;wire sub_wire5;wire [9:0] usedw = sub_wire0[9:0];wire empty = sub_wire1;wire full = sub_wire2;wire [11:0] q = sub_wire3[11:0];wire almost_empty = sub_wire4;wire almost_full = sub_wire5;scfifoscfifo_component (.clock (clock),.sclr (sclr),.wrreq (wrreq),.data (data),.rdreq (rdreq),.usedw (sub_wire0),.empty (sub_wire1),.full (sub_wire2),.q (sub_wire3),.almost_empty (sub_wire4),.almost_full (sub_wire5),.aclr ());defparamscfifo_component.add_ram_output_register = "OFF",scfifo_component.almost_empty_value = 1,scfifo_component.almost_full_value = 1023,scfifo_component.intended_device_family = "Cyclone IV E",scfifo_component.lpm_numwords = 1024,scfifo_component.lpm_showahead = "OFF",scfifo_component.lpm_type = "scfifo",scfifo_component.lpm_width = 12,scfifo_component.lpm_widthu = 10,scfifo_component.overflow_checking = "ON",scfifo_component.underflow_checking = "ON",scfifo_component.use_eab = "ON";endmodule

第7 部分 fifo_send_ctrl.v文件,主要实现的是将fifo 的存放数据【12位】设置一个转换【8位】输出,输出串口标准的发送信号.

module fifo_send_ctrl(Clk,Rst_n,Tx_done ,Fifo_empty ,Fifo_q,Tx_Send_en,Tx_Data,Fifo_rdreq);input Clk ;input Rst_n ;input Tx_done ;input Fifo_empty ;input [11:0]Fifo_q ;output reg Tx_Send_en ;output reg [7:0]Tx_Data ;output reg Fifo_rdreq ;//localparamSTATE_S0= 5'b0_0001,STATE_S1 = 5'b0_0010,STATE_S2= 5'b0_0100,STATE_S3= 5'b0_1000,STATE_S4= 5'b1_0000;reg[4:0]state;always@(posedge Clk or negedge Rst_n)if(!Rst_n)beginstate <= STATE_S0;endelse begincase(state)STATE_S0:if(Fifo_empty == 1'b0) begin // fifo 有dataFifo_rdreq <= 1'b1 ; //发送读信号state <= STATE_S1;endelsestate <= STATE_S0;STATE_S1:beginFifo_rdreq <= 1'b0 ;state <= STATE_S2;endSTATE_S2:beginTx_Send_en <= 1'b1;Tx_Data <= {4'b0000,Fifo_q[11:8]} ; // 先发送高8位state <= STATE_S3;endSTATE_S3:if(Tx_done == 1'b1)beginTx_Send_en <= 1'b1;Tx_Data <= Fifo_q[7:0] ; //再发送低8位state <= STATE_S4;endelsebeginTx_Send_en <= 1'b0;state <= STATE_S3;endSTATE_S4:if(Tx_done == 1'b1)state <= STATE_S0;else if(Tx_done == 1'b0)beginTx_Send_en <= 1'b0;state <= STATE_S4;enddefault:state <= STATE_S1;endcaseendendmodule

第8部分: uart_byte_tx .v 串口发送模块

module uart_byte_tx(Clk,Rst_n,data_byte,send_en,baud_set,Rs232_Tx,Tx_Done,uart_state);input Clk;input Rst_n;input [7:0]data_byte;input send_en;input [2:0]baud_set;output reg Rs232_Tx;output reg Tx_Done;output reg uart_state;reg bps_clk;//波特率时钟reg [15:0]div_cnt;//分频计数器reg [15:0]bps_DR;//分频计数最大值reg [3:0]bps_cnt;//波特率时钟计数器reg [7:0]r_data_byte;localparam START_BIT = 1'b0;localparam STOP_BIT = 1'b1;always@(posedge Clk or negedge Rst_n)if(!Rst_n)uart_state <= 1'b0;else if(send_en)uart_state <= 1'b1;else if(bps_cnt == 4'd11)uart_state <= 1'b0;elseuart_state <= uart_state;always@(posedge Clk or negedge Rst_n)if(!Rst_n)r_data_byte <= 8'd0;else if(send_en)r_data_byte <= data_byte;elser_data_byte <= r_data_byte;always@(posedge Clk or negedge Rst_n)if(!Rst_n)bps_DR <= 16'd5207;else begincase(baud_set)0:bps_DR <= 16'd5207;1:bps_DR <= 16'd2603;2:bps_DR <= 16'd1301;3:bps_DR <= 16'd867;4:bps_DR <= 16'd433;default:bps_DR <= 16'd5207;endcaseend//counteralways@(posedge Clk or negedge Rst_n)if(!Rst_n)div_cnt <= 16'd0;else if(uart_state)beginif(div_cnt == bps_DR)div_cnt <= 16'd0;elsediv_cnt <= div_cnt + 1'b1;endelsediv_cnt <= 16'd0;// bps_clk genalways@(posedge Clk or negedge Rst_n)if(!Rst_n)bps_clk <= 1'b0;else if(div_cnt == 16'd1)bps_clk <= 1'b1;elsebps_clk <= 1'b0;//bps counteralways@(posedge Clk or negedge Rst_n)if(!Rst_n)bps_cnt <= 4'd0;else if(bps_cnt == 4'd11)bps_cnt <= 4'd0;else if(bps_clk)bps_cnt <= bps_cnt + 1'b1;elsebps_cnt <= bps_cnt;always@(posedge Clk or negedge Rst_n)if(!Rst_n)Tx_Done <= 1'b0;else if(bps_cnt == 4'd11)Tx_Done <= 1'b1;elseTx_Done <= 1'b0;always@(posedge Clk or negedge Rst_n)if(!Rst_n)Rs232_Tx <= 1'b1;else begincase(bps_cnt)0:Rs232_Tx <= 1'b1;1:Rs232_Tx <= START_BIT;2:Rs232_Tx <= r_data_byte[0];3:Rs232_Tx <= r_data_byte[1];4:Rs232_Tx <= r_data_byte[2];5:Rs232_Tx <= r_data_byte[3];6:Rs232_Tx <= r_data_byte[4];7:Rs232_Tx <= r_data_byte[5];8:Rs232_Tx <= r_data_byte[6];9:Rs232_Tx <= r_data_byte[7];10:Rs232_Tx <= STOP_BIT;default:Rs232_Tx <= 1'b1;endcaseendendmodule

第九部分: 顶层设计文件,就是模块核模块之间的连接

// 实验内容:// ① 通过按键控制AD采集模块// ② 按键按下,ad 进行采样100 次,操作// ③ ad 采样的数据存取到fifo 中// ④ 读取fifo中的数据,将数据通过串口模块发送,直到fifo 的数据全部读取完毕为止// ⑤ 读取的数据是12位,串口模块发送需要先变成标准的2个8位数据发送,通过电脑上的串口调试助手显示发送的数据// 信号发生器模块: 【内部有一个 DA_rom 数据模块】 ,每次间隔0.01S,发送一次模拟数据到,模拟信号发送通道1,发送出去// 信号采样时间现在本工程暂时无法控制,下一个工程【27_ADC_DAC_system】将会完善改功能module AD_DA_Top(Clk ,Rst_n ,key_in ,ADC_DOUT ,ADC_SCLK ,ADC_DIN ,ADC_CS_N ,Rs232_Tx ,DAC_CS_N ,DAC_DIN ,DAC_SCLK);input Clk ;input Rst_n ;input key_in ;input ADC_DOUT ;output ADC_SCLK;output ADC_DIN;output ADC_CS_N;output Rs232_Tx;// 信号源output DAC_CS_N;output DAC_DIN;output DAC_SCLK;wire key_flag ;wire key_state ;wire Ad_En_Conv;wire Conv_Done;wire Fifo_empty;wire Fifo_almost_full;wire Tx_Done;wire Tx_Send_en;wire [7:0]Tx_Data;wire [11:0]fifo_dtae;wire [11:0]Fifo_q;wire Fifo_rdreq;wire [15:0]DAC_DATA ;wire Start ;wire DAC_State;key_filterkey_filter_0(.Clk(Clk) ,.Rst_n(Rst_n) ,.key_in(key_in) ,.key_flag(key_flag), //检测按键成功信号.key_state(key_state) //实时的信号);ctrl_sample ctrl_sample0( .Clk(Clk),.Rst_n(Rst_n),.key_flag(key_flag) ,.key_state(key_state) ,.Ad_Conv_Done(Conv_Done),.Fifo_almost_full(Fifo_almost_full),.Ad_En_Conv(Ad_En_Conv));ad128s022 ad128s022_0(.Clk(Clk),.Rst_n(Rst_n),.Channel(3'd5),.Data(fifo_dtae),.En_Conv(Ad_En_Conv),.Conv_Done(Conv_Done),.ADC_State(), // 和 ADC_CS_N 状态保持一致.DIV_PARAM(8'd13),.ADC_SCLK(ADC_SCLK),.ADC_DOUT(ADC_DOUT),.ADC_DIN(ADC_DIN),.ADC_CS_N(ADC_CS_N));AD_fifoAD_fifo_0 (.clock(Clk),.data(fifo_dtae),.rdreq(Fifo_rdreq),.sclr(!Rst_n), .wrreq(Conv_Done),.almost_empty(),.almost_full(Fifo_almost_full),.empty(Fifo_empty),.full(),.q(Fifo_q),.usedw());fifo_send_ctrlfifo_send_ctrl_0(.Clk(Clk),.Rst_n(Rst_n),.Tx_done(Tx_Done) ,.Fifo_empty(Fifo_empty) ,.Fifo_q(Fifo_q),.Tx_Send_en(Tx_Send_en),.Tx_Data(Tx_Data),.Fifo_rdreq(Fifo_rdreq));uart_byte_txuart_byte_tx_0(.Clk(Clk),.Rst_n(Rst_n),.data_byte(Tx_Data),.send_en(Tx_Send_en),.baud_set(3'd4), // 115200bps.Rs232_Tx(Rs232_Tx),.Tx_Done(Tx_Done),.uart_state());DAC_rom_signal DAC_rom_signal_0(.Clk(Clk),.Rst_n(Rst_n),.DAC_State(DAC_State),.DAC_DATA(DAC_DATA),.Data_Start(Start));dac_tlv5618 dac_tlv5618_0(.Clk(Clk),.Rst_n(Rst_n),.DAC_DATA(DAC_DATA),.Start(Start),.Set_Done(),.DAC_CS_N(DAC_CS_N),.DAC_DIN(DAC_DIN),.DAC_SCLK(DAC_SCLK),.DAC_State(DAC_State));endmodule

注: 本次作为一个综合实验,主要是对原先学习的知识做一个系统的设计,将现阶段所学的内容整合在一块,同时也需要知道真正在做fpga项目的时候,基本上都是先做系统模块化数字电路设计,后面模块再去写模块代码,做模块验证,最后根据顶层文件直接连接,最后综合和测试即可。

如果觉得《FPGA 30 综合数字ADC /DAC 信号发送采集系统设计(综合项目设计)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。