OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 8500|回复: 7

[ALTERA] FPGA实现ad7606八同步采集,并行输出

[复制链接]

24

主题

57

帖子

0

精华

高级会员

Rank: 4

积分
800
金钱
800
注册时间
2016-11-25
在线时间
93 小时
发表于 2019-12-9 21:12:51 | 显示全部楼层 |阅读模式
//=============================================================
// Module   : ad7606_driver.v
// Function : ADC7606驱动模块,8通道输入,并行模式输出16bit
// Author        : snjshping
// Date             : 20191208
// Version    : 1.0
//=============================================================
module ad7606_driver
    (
    input                                Clock                    ,
    input                                Rst_n                    ,
   
    input                                iAd_start_en    ,
    input                                iAd_frstdata    ,
    input                                iAd_busy            ,
    input             [15:0]        iAd_data            ,
   
    output       [2:0]        oAd_os                ,
    output reg                    oAd_cs_n            ,
    output reg                    oAd_rd_n            ,
    output reg                    oAd_reset_p        ,
    output reg                    oAd_convest_ab,
    output reg [15:0]        oAd_ch1_vaule    ,
    output reg [15:0]        oAd_ch2_vaule    ,
    output reg [15:0]        oAd_ch3_vaule    ,
    output reg [15:0]        oAd_ch4_vaule    ,
    output reg [15:0]        oAd_ch5_vaule    ,
    output reg [15:0]        oAd_ch6_vaule    ,
    output reg [15:0]        oAd_ch7_vaule    ,
    output reg [15:0]        oAd_ch8_vaule    ,
   
    output                            beep                    ,   
    output reg                     oAd_conv_done
    );
//=============================================================
// parameter define
//=============================================================
localparam ST_IDLE             = 12'b0000_0000_0001;
localparam ST_AD_CONV     = 12'b0000_0000_0010;
localparam ST_WAIT_BUSY = 12'b0000_0000_0100;
localparam ST_RD_CH1         = 12'b0000_0000_1000;
localparam ST_RD_CH2         = 12'b0000_0001_0000;
localparam ST_RD_CH3         = 12'b0000_0010_0000;
localparam ST_RD_CH4         = 12'b0000_0100_0000;
localparam ST_RD_CH5         = 12'b0000_1000_0000;
localparam ST_RD_CH6         = 12'b0001_0000_0000;
localparam ST_RD_CH7         = 12'b0010_0000_0000;
localparam ST_RD_CH8         = 12'b0100_0000_0000;
localparam ST_RD_END         = 12'b1000_0000_0000;



//=============================================================
// wire define
//=============================================================

//=============================================================
// reg define
//=============================================================
reg [11:0]        rCurr_state    ;
reg [11:0]        rNext_state    ;
reg                        rSkip_en        ;

reg [15:0]      rRst_cnt        ;
reg [5:0]            rClk_cnt        ;


//-------------------------------------------------------------
// don't use oversampling with os[2:0] = 3'b000
//-------------------------------------------------------------        
assign oAd_os[2:0] = 3'b000;
assign beep = 1'b1;



//-------------------------------------------------------------
// generating reset signal to reset ad7606 with high level
//-------------------------------------------------------------   
always@(posedge Clock or negedge Rst_n)
begin
    if(Rst_n == 1'b0)
    begin
        rRst_cnt[15:0] <= 16'd0;
    end
    else
    begin
        rRst_cnt[15:0] <= (rRst_cnt[15:0] == 16'hffff) ? rRst_cnt[15:0] : (rRst_cnt[15:0] + 16'd1);
    end
end
always@(posedge Clock or negedge Rst_n)
begin
    if(Rst_n == 1'b0)
    begin
        oAd_reset_p <= 1'b0;
    end
    else
    begin
        oAd_reset_p <= (rRst_cnt[15:0] < 16'hffff) ? 1'b1 : 1'b0;
    end
end


//-------------------------------------------------------------
// Temporal logic describes state transitions
//-------------------------------------------------------------   
always @ ( posedge Clock or negedge Rst_n )
begin
    rCurr_state[11:0] <= (Rst_n == 1'b0) ? ST_IDLE : rNext_state[11:0];
end


//-------------------------------------------------------------
// combination logic describes state transitions
//-------------------------------------------------------------   
always @ ( * )
begin   
    case(rCurr_state[11:0])
        ST_IDLE             : rNext_state[11:0] = (rSkip_en == 1'b1) ? ST_AD_CONV : ST_IDLE;
        ST_AD_CONV          : rNext_state[11:0] = (rSkip_en == 1'b1) ? ST_WAIT_BUSY : ST_AD_CONV;
        ST_WAIT_BUSY     : rNext_state[11:0] = (rSkip_en == 1'b1) ? ST_RD_CH1 : ST_WAIT_BUSY;
        ST_RD_CH1         : rNext_state[11:0] = (rSkip_en == 1'b1) ? ST_RD_CH2 : ST_RD_CH1;
        ST_RD_CH2         : rNext_state[11:0] = (rSkip_en == 1'b1) ? ST_RD_CH3 : ST_RD_CH2;
        ST_RD_CH3         : rNext_state[11:0] = (rSkip_en == 1'b1) ? ST_RD_CH4 : ST_RD_CH3;
        ST_RD_CH4         : rNext_state[11:0] = (rSkip_en == 1'b1) ? ST_RD_CH5 : ST_RD_CH4;
        ST_RD_CH5         : rNext_state[11:0] = (rSkip_en == 1'b1) ? ST_RD_CH6 : ST_RD_CH5;
        ST_RD_CH6         : rNext_state[11:0] = (rSkip_en == 1'b1) ? ST_RD_CH7 : ST_RD_CH6;
        ST_RD_CH7         : rNext_state[11:0] = (rSkip_en == 1'b1) ? ST_RD_CH8 : ST_RD_CH7;
        ST_RD_CH8         : rNext_state[11:0] = (rSkip_en == 1'b1) ? ST_RD_END : ST_RD_CH8;
        ST_RD_END         : rNext_state[11:0] = (rSkip_en == 1'b1) ? ST_IDLE : ST_RD_END;
        default                : rNext_state[11:0] = ST_IDLE;
    endcase
end


//-------------------------------------------------------------
// Temporal logic describes output
//-------------------------------------------------------------   
always @ ( posedge Clock )
begin
    if(oAd_reset_p == 1'b1)
    begin
        rSkip_en                        <= 1'b0;
        rClk_cnt[5:0]                <= 6'd0;
        oAd_cs_n                        <= 1'b1;
        oAd_rd_n                        <= 1'b1;
        oAd_convest_ab            <= 1'b1;            
        oAd_ch1_vaule[15:0] <= 16'd0;
        oAd_ch2_vaule[15:0] <= 16'd0;
        oAd_ch3_vaule[15:0]    <= 16'd0;
        oAd_ch4_vaule[15:0]    <= 16'd0;
        oAd_ch5_vaule[15:0]    <= 16'd0;
        oAd_ch6_vaule[15:0]    <= 16'd0;
        oAd_ch7_vaule[15:0]    <= 16'd0;
        oAd_ch8_vaule[15:0]    <= 16'd0;   
    oAd_conv_done             <= 1'b0;            
    end
    else
    begin
        case(rCurr_state[11:0])
            ST_IDLE             : begin                                                                                            
                                                oAd_cs_n             <= 1'b1;
                                                oAd_rd_n             <= 1'b1;
                                                oAd_convest_ab <= 1'b1;
                                                oAd_conv_done  <= 1'b0;
                                                rClk_cnt[5:0]  <= 6'd0;
                                                rSkip_en              <= ((iAd_start_en == 1'b1) && (rNext_state[11:0] == ST_IDLE)) ? 1'b1 : 1'b0;
                                                // 注意:若只写rSkip_en <= (iAd_start_en == 1'b1) ? 1'b1 : 1'b0;
                                                // 则产生两个时钟周期的rSkip_en信号,导致下一个状态逻辑错误
                                            end
            ST_AD_CONV          : begin
                                                rClk_cnt[5:0]      <= (rClk_cnt[5:0] == 6'd9) ? 6'd0 : (rClk_cnt[5:0] + 6'd1);
                                                oAd_convest_ab    <= (rClk_cnt[5:0] <= 6'd1) ? 1'b0 : 1'b1;
                                                rSkip_en                 <= (rClk_cnt[5:0] == 6'd8) ? 1'b1 : 1'b0;
                                            end
            ST_WAIT_BUSY     : begin
                                                rClk_cnt[5:0]      <= 6'd0;
                                                rSkip_en                 <= ((iAd_busy == 1'b0) && (rNext_state[11:0] == ST_WAIT_BUSY)) ? 1'b1 : 1'b0;
                                            end
            ST_RD_CH1         : begin                                                
                                                oAd_cs_n                      <= 1'b0;
                                                rClk_cnt[5:0]              <= (rClk_cnt[5:0] == 6'd3) ? 6'd0 : (rClk_cnt[5:0] + 6'd1);
                                                oAd_rd_n                       <= (rClk_cnt[5:0] == 6'd0) ? 1'b1 : 1'b0;
                                                rSkip_en                         <= (rClk_cnt[5:0] == 6'd2) ? 1'b1 : 1'b0;
                                                oAd_ch1_vaule[15:0] <= (rClk_cnt[5:0] == 6'd3) ? iAd_data[15:0] : oAd_ch1_vaule[15:0];
                                            end
            ST_RD_CH2         : begin                                                                                                
                                                oAd_cs_n                      <= 1'b0;
                                                rClk_cnt[5:0]              <= (rClk_cnt[5:0] == 6'd3) ? 6'd0 : (rClk_cnt[5:0] + 6'd1);
                                                oAd_rd_n                       <= (rClk_cnt[5:0] == 6'd0) ? 1'b1 : 1'b0;
                                                rSkip_en                         <= (rClk_cnt[5:0] == 6'd2) ? 1'b1 : 1'b0;
                                                oAd_ch2_vaule[15:0] <= (rClk_cnt[5:0] == 6'd3) ? iAd_data[15:0] : oAd_ch2_vaule[15:0];
                                            end
            ST_RD_CH3         : begin                                                                                                
                                                oAd_cs_n                      <= 1'b0;
                                                rClk_cnt[5:0]              <= (rClk_cnt[5:0] == 6'd3) ? 6'd0 : (rClk_cnt[5:0] + 6'd1);
                                                oAd_rd_n                       <= (rClk_cnt[5:0] == 6'd0) ? 1'b1 : 1'b0;
                                                rSkip_en                         <= (rClk_cnt[5:0] == 6'd2) ? 1'b1 : 1'b0;
                                                oAd_ch3_vaule[15:0] <= (rClk_cnt[5:0] == 6'd3) ? iAd_data[15:0] : oAd_ch3_vaule[15:0];
                                            end
            ST_RD_CH4         : begin                                                                                       
                                                oAd_cs_n                      <= 1'b0;
                                                rClk_cnt[5:0]              <= (rClk_cnt[5:0] == 6'd3) ? 6'd0 : (rClk_cnt[5:0] + 6'd1);
                                                oAd_rd_n                       <= (rClk_cnt[5:0] == 6'd0) ? 1'b1 : 1'b0;
                                                rSkip_en                         <= (rClk_cnt[5:0] == 6'd2) ? 1'b1 : 1'b0;
                                                oAd_ch4_vaule[15:0] <= (rClk_cnt[5:0] == 6'd3) ? iAd_data[15:0] : oAd_ch4_vaule[15:0];
                                            end
            ST_RD_CH5         : begin                                                                                                
                                                oAd_cs_n                      <= 1'b0;
                                                rClk_cnt[5:0]              <= (rClk_cnt[5:0] == 6'd3) ? 6'd0 : (rClk_cnt[5:0] + 6'd1);
                                                oAd_rd_n                       <= (rClk_cnt[5:0] == 6'd0) ? 1'b1 : 1'b0;
                                                rSkip_en                         <= (rClk_cnt[5:0] == 6'd2) ? 1'b1 : 1'b0;
                                                oAd_ch5_vaule[15:0] <= (rClk_cnt[5:0] == 6'd3) ? iAd_data[15:0] : oAd_ch5_vaule[15:0];
                                            end
            ST_RD_CH6         : begin                                                                                            
                                                oAd_cs_n                      <= 1'b0;
                                                rClk_cnt[5:0]              <= (rClk_cnt[5:0] == 6'd3) ? 6'd0 : (rClk_cnt[5:0] + 6'd1);
                                                oAd_rd_n                       <= (rClk_cnt[5:0] == 6'd0) ? 1'b1 : 1'b0;
                                                rSkip_en                         <= (rClk_cnt[5:0] == 6'd2) ? 1'b1 : 1'b0;
                                                oAd_ch6_vaule[15:0] <= (rClk_cnt[5:0] == 6'd3) ? iAd_data[15:0] : oAd_ch6_vaule[15:0];
                                            end
            ST_RD_CH7         : begin                                                                                            
                                                oAd_cs_n                      <= 1'b0;
                                                rClk_cnt[5:0]              <= (rClk_cnt[5:0] == 6'd3) ? 6'd0 : (rClk_cnt[5:0] + 6'd1);
                                                oAd_rd_n                       <= (rClk_cnt[5:0] == 6'd0) ? 1'b1 : 1'b0;
                                                rSkip_en                         <= (rClk_cnt[5:0] == 6'd2) ? 1'b1 : 1'b0;
                                                oAd_ch7_vaule[15:0] <= (rClk_cnt[5:0] == 6'd3) ? iAd_data[15:0] : oAd_ch7_vaule[15:0];
                                            end
            ST_RD_CH8         : begin                                                                                            
                                                oAd_cs_n                      <= 1'b0;
                                                rClk_cnt[5:0]              <= (rClk_cnt[5:0] == 6'd3) ? 6'd0 : (rClk_cnt[5:0] + 6'd1);
                                                oAd_rd_n                       <= (rClk_cnt[5:0] == 6'd0) ? 1'b1 : 1'b0;
                                                rSkip_en                         <= (rClk_cnt[5:0] == 6'd2) ? 1'b1 : 1'b0;
                                                oAd_ch8_vaule[15:0] <= (rClk_cnt[5:0] == 6'd3) ? iAd_data[15:0] : oAd_ch8_vaule[15:0];
                                            end
            ST_RD_END         : begin                                                
                                                oAd_rd_n             <= 1'b1;
                                                rClk_cnt[5:0]     <= (rClk_cnt[5:0] == 6'd1) ? 6'd0 : (rClk_cnt[5:0] + 6'd1);
                                                oAd_cs_n              <= (rClk_cnt[5:0] == 6'd1) ? 1'b1 : 1'b0;
                                                rSkip_en              <= (rClk_cnt[5:0] == 6'd0) ? 1'b1 : 1'b0;
                                                oAd_conv_done  <= ((rClk_cnt[5:0] == 6'd0) && (rNext_state[11:0] == ST_RD_END)) ? 1'b1 : 1'b0;
                                            end
            default                : ;
        endcase
    end
end


endmodule
/************************************************
ad7606_driver  inst_ad7606_driver (
    .Clock             (Clock),
    .Rst_n             (Rst_n),
    .iAd_start_en      (iAd_start_en),
    .iAd_frstdata      (iAd_frstdata),
    .iAd_busy          (iAd_busy),
    .iAd_data          (iAd_data),
    .oAd_reset_p       (oAd_reset_p),
    .oAd_os            (oAd_os),
    .oAd_convest_ab    (oAd_convest_ab),
    .oAd_cs_n          (oAd_cs_n),
    .oAd_rd_n          (oAd_rd_n),
    .oAd_ch1_vaule     (oAd_ch1_vaule),
    .oAd_ch2_vaule     (oAd_ch2_vaule),
    .oAd_ch3_vaule     (oAd_ch3_vaule),
    .oAd_ch4_vaule     (oAd_ch4_vaule),
    .oAd_ch5_vaule     (oAd_ch5_vaule),
    .oAd_ch6_vaule     (oAd_ch6_vaule),
    .oAd_ch7_vaule     (oAd_ch7_vaule),
    .oAd_ch8_vaule     (oAd_ch8_vaule),
    .oAd_conv_done     (oAd_conv_done)
);
*************************************************/
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

5

主题

424

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1020
金钱
1020
注册时间
2014-9-4
在线时间
199 小时
发表于 2019-12-10 16:36:19 | 显示全部楼层
https://github.com/WZTENG
回复 支持 反对

使用道具 举报

5

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
143
金钱
143
注册时间
2019-8-18
在线时间
61 小时
发表于 2019-12-10 22:46:17 来自手机 | 显示全部楼层
厉害哦,楼主有没有考虑过将数据传输并存储呢?
回复 支持 反对

使用道具 举报

24

主题

57

帖子

0

精华

高级会员

Rank: 4

积分
800
金钱
800
注册时间
2016-11-25
在线时间
93 小时
 楼主| 发表于 2019-12-25 16:55:13 | 显示全部楼层
lanya001jia 发表于 2019-12-10 22:46
厉害哦,楼主有没有考虑过将数据传输并存储呢?

这个得看实际需求了
回复 支持 反对

使用道具 举报

1

主题

12

帖子

0

精华

新手上路

积分
22
金钱
22
注册时间
2019-6-19
在线时间
2 小时
发表于 2020-4-24 15:56:18 | 显示全部楼层
很强大,支持
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
14
金钱
14
注册时间
2020-2-15
在线时间
6 小时
发表于 2020-9-23 17:35:53 | 显示全部楼层
请问楼主用的FPGA的型号是?
回复 支持 反对

使用道具 举报

24

主题

57

帖子

0

精华

高级会员

Rank: 4

积分
800
金钱
800
注册时间
2016-11-25
在线时间
93 小时
 楼主| 发表于 2020-9-25 10:04:46 | 显示全部楼层
STMxiaocai 发表于 2020-9-23 17:35
请问楼主用的FPGA的型号是?

ALTERA的EP4CEF23C8
回复 支持 反对

使用道具 举报

7

主题

88

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
273
金钱
273
注册时间
2015-1-10
在线时间
69 小时
发表于 2021-3-18 15:02:44 | 显示全部楼层
这个厉害了,赞一个
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-10-3 18:16

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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