集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 1675|回复: 3

AD采样的FPGA程序书写参考 Verilog代码

[复制链接]
fpga_feixiang 发表于 2020-3-2 12:39:07 | 显示全部楼层 |阅读模式
提供一段AD采样的FPGA程序
程序如下

Verilog源程序如下:
//---------------------------------------------------------------------------
//--        文件名                :        Ad_Module.v
//--        作者                :        ZIRCON
//--        描述                :        AD模块
//---------------------------------------------------------------------------

`define AD_CLK_TIME                        10'd49        //1.1M, 909ns,909 / (1 / 50M) = 45 =0x2D
`define AD_CLK_TIME_HALF        10'd24        //909ns / 2 = 454.5ns 45 / 2 = 22        

module Ad_Module
(        
        //Input
        CLK_50M,RST_N,
        //Output
        AD_CS,AD_CLK,AD_DATA,data_out
);
        
//---------------------------------------------------------------------------
//--        外部端口声明
//---------------------------------------------------------------------------
input                                        CLK_50M;                                //时钟的端口,开发板用的50M晶振
input                                        RST_N;                                //复位的端口,低电平复位
input                                        AD_DATA;                                //AD数据端口
output                                AD_CS;                                //AD片选端口
output                                AD_CLK;                                //AD时钟端口,最大不超过1.1MHz
output        [ 7:0]        data_out;                        //AD模数转换完成的数据输出


//---------------------------------------------------------------------------
//--        内部端口声明
//---------------------------------------------------------------------------
reg                                        AD_CS;                                //AD片选信号端口
reg                                        AD_CS_N;                                //AD_CS的下一个状态
reg                                        AD_CLK;                                //AD时钟,最大不超过1.1MHz
reg                                        AD_CLK_N;                        //AD_CLK的下一个状态

reg                [ 2:0]        ad_fsm_cs;                        //状态机的当前状态
reg                [ 2:0]        ad_fsm_ns;                        //状态机的下一个状态

reg                [ 5:0]        time_cnt;                        //用于记录一个时钟所用时间的定时器
reg                [ 5:0]        time_cnt_n;                        //time_cnt的下一个状态
reg                [ 5:0]        bit_cnt;                                //用来记录时钟周期个数的计数器
reg                [ 5:0]        bit_cnt_n;                        //bit_cnt的下一个状态

reg                [ 7:0]        data_out;                        //用来保存稳定的AD数据
reg                [ 7:0]        data_out_n;                        //data_out的下一个状态
reg                [ 7:0]        ad_data_reg;                //用于保存数据的移位寄存器
reg                [ 7:0]        ad_data_reg_n;                //ad_data_reg_n的下一个状态

parameter        FSM_IDLE                        = 3'h0;        //状态机的初始状态;
parameter        FSM_READY                = 3'h1;        //满足CS有效时的第一个1.4us的延时状态
parameter        FSM_DATA                        = 3'h2;        //读取8个数据状态
parameter        FSM_WAIT_CONV        = 3'h3;        //等待转换状态,等待17us;
parameter        FSM_END                        = 3'h4;        //结束的状态

//---------------------------------------------------------------------------
//--        逻辑功能实现        
//---------------------------------------------------------------------------
//时序电路,用来给ad_fsm_cs寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
        if(!RST_N)                                                                //判断复位
                ad_fsm_cs <= 1'b0;                                //初始化ad_fsm_cs值
        else
                ad_fsm_cs <= ad_fsm_ns;                        //用来给ad_fsm_ns赋值
end

//组合电路,用来实现状态机
always @ (*)
begin
        case(ad_fsm_cs)                                                //判断状态机的当前状态
                FSM_IDLE:
                                                                                                //3 x 0.909us = 2.727us用于初始化延时
                        if((bit_cnt == 6'd2 ) && (time_cnt == `AD_CLK_TIME))
                                ad_fsm_ns = FSM_READY;        //如果空闲状态完成就进入延时状态
                        else
                                ad_fsm_ns = ad_fsm_cs;        //否则保持原状态不变
                FSM_READY:
                                                                                                //2 x 0.909us = 1.818us用于延迟1.4us
                        if((bit_cnt == 6'd2 ) && (time_cnt == `AD_CLK_TIME))
                                ad_fsm_ns = FSM_DATA;        //如果延时状态完成就进入读取数据状态
                        else
                                ad_fsm_ns = ad_fsm_cs;  //否则保持原状态不变
                FSM_DATA:
                                                                                                //读取数据8位,1~8个时钟脉冲
                        if((bit_cnt == 6'd8 ) && (time_cnt == `AD_CLK_TIME))
                                ad_fsm_ns = FSM_WAIT_CONV;//如果读取数据状态完成就进入等待状态
                        else
                                ad_fsm_ns = ad_fsm_cs;        //否则保持原状态不变               
                FSM_WAIT_CONV:
                                                                                                //19 x 0.909us = 17.271us用于延迟17us
                        if((bit_cnt == 6'd10) && (time_cnt == `AD_CLK_TIME))
                                ad_fsm_ns = FSM_END;                //如果等待状态完成就进入读取状态
                        else
                                ad_fsm_ns = ad_fsm_cs;        //否则保持原状态不变  
                FSM_END:                                                               
                        ad_fsm_ns = FSM_READY;                //完成一次数据转换,进入下一次转换
                default:ad_fsm_ns = FSM_IDLE;                                
        endcase
end

//时序电路,用来给time_cnt寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
        if(!RST_N)                                                                //判断复位
                time_cnt <= 6'h0;                                        //初始化time_cnt值
        else
                time_cnt <= time_cnt_n;                        //用来给time_cnt赋值
end

//组合电路,实现0.909us的定时计数器
always @ (*)
begin
        if(time_cnt == `AD_CLK_TIME)                //判断0.909us时间
                time_cnt_n = 6'h0;                                //如果到达0.909us,定时器清零
        else
                time_cnt_n = time_cnt + 6'h1;        //如果未到0.909us,定时器继续加1
end

//时序电路,用来给bit_cnt寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
        if(!RST_N)                                                                //判断复位
                bit_cnt <= 6'h0;                                        //初始化bit_cnt值
        else
                bit_cnt <= bit_cnt_n;                        //用来给bit_cnt赋值
end

//组合电路,用来记录时钟周期个数的计数器
always @ (*)
begin
        if(ad_fsm_cs != ad_fsm_ns)                        //判断状态机的当前状态
                bit_cnt_n = 6'h0;                                        //如果当前的状态不等于下一个状态,计时器就清零
        else if(time_cnt == `AD_CLK_TIME_HALF)//判断0.4545us时间
                bit_cnt_n = bit_cnt + 6'h1;        //如果到达0.4545us,计数器就加1
        else
                bit_cnt_n = bit_cnt;                                //否则计数器保持不变
end

//时序电路,用来给AD_CLK寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
        if(!RST_N)                                                                //判断复位
                AD_CLK <= 1'h0;                                        //初始化AD_CLK值
        else
                AD_CLK <= AD_CLK_N;                                //用来给AD_CLK赋值
end

//组合电路,用来生成AD的时钟波形
always @ (*)
begin
        if(ad_fsm_cs != FSM_DATA)                        //判断状态机的当前状态
                AD_CLK_N = 1'h0;                                        //如果当前的状态不等于读取数据状态,AD_CLK_N就置0
        else if(time_cnt == `AD_CLK_TIME_HALF)//判断0.4545us时间
                AD_CLK_N = 1'h1;                                        //如果到达0.4545us,ADC_CLK_N就置1
        else if(time_cnt == `AD_CLK_TIME)//判断0.909us时间
                AD_CLK_N = 1'h0;                                        //如果到达0.909us,AD_CLK_N就置0
        else
                AD_CLK_N = AD_CLK;                                //否则保持不变
end

//时序电路,用来给AD_CS寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
        if(!RST_N)                                                                //判断复位
                AD_CS <= 1'h0;                                                //初始化AD_CS值
        else
                AD_CS <= AD_CS_N;                                        //用来给AD_CS赋值
end

//组合电路,用来生成AD的片选波形
always @ (*)
begin
        if((ad_fsm_cs == FSM_DATA) || (ad_fsm_cs == FSM_READY))//判断状态机的当前状态
                AD_CS_N = 1'h0;//如果当前的状态等于读取数据状态或等于延时1.4us状态,AD_CS_N就置0
        else
                AD_CS_N = 1'h1;//如果当前的状态不等于读取数据状态或不等于延时1.4us状态,AD_CS_N就置1
end

//时序电路,用来给ad_data_reg寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
        if(!RST_N)                                                                //判断复位
                ad_data_reg <= 8'h0;                                //初始化ad_data_reg值
        else
                ad_data_reg <= ad_data_reg_n;        //用来给ad_data_reg赋值
end

//组合电路,将AD线上的数据保存到移位寄存器中
always @(*)
begin
        if((ad_fsm_cs == FSM_DATA) && (!AD_CLK) && (AD_CLK_N))//判断每一个时钟的上升沿
                ad_data_reg_n = {ad_data_reg[6:0],AD_DATA};//将数据存入移位寄存器中,高位优先
        else
                ad_data_reg_n = ad_data_reg;        //否则保持不变
end

//时序电路,用来给data_out寄存器赋值
always @ (posedge CLK_50M or negedge RST_N)
begin
        if(!RST_N)                                                                //判断复位
                data_out <= 8'h0;                                        //初始化data_out值
        else
                data_out <= data_out_n;                        //用来给data_out赋值
end

//组合电路,将移位寄存器中的数据存入data_out中,可用于输出
always @ (*)
begin
        if(ad_fsm_cs == FSM_END)                        //判断复位
                data_out_n = ad_data_reg;                //初始化data_out值
        else
                data_out_n = data_out;                        //用来给data_out赋值
end

endmodule
大鹏 发表于 2022-5-8 08:54:08 | 显示全部楼层
AD采样的FPGA程序书写参考 Verilog代码
zxopenhl 发表于 2023-12-18 14:36:01 | 显示全部楼层
AD采样的FPGA程序书写参考 Verilog代码
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|集成电路技术分享 ( 京ICP备20003123号-1 )

GMT+8, 2024-5-19 10:37 , Processed in 0.082514 second(s), 22 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表