挂在Avalon总线上的AD7656芯片驱动verilog程序实现

ops/2024/9/23 14:31:31/

        AD7656是一款16位同步采样双极ADC转换器,本文中用状态机方式实现了AD7656芯片的Verilog驱动,并且将驱动直接挂在了altera芯片的Avalon总线上,使其altera芯片能够通过总线直接控制ADC芯片,其代码如下:

module AD7656_drive(clk,rst_n,slave_rd_n,slave_cs_n,slave_address,slave_rddata,ad_cs_n,sclking,sclk,CONVST,DOUTA,DOUTB); 
//-------------------------------------------- 
    input clk;
    input rst_n;
     input sclking; 
     wire  sclk;    
//-----------------------------------------
//Avalon--MM interface
    input  slave_rd_n;
    input  slave_cs_n;  
    output[31:0] slave_rddata;
    input [1:0]slave_address;
    
    reg  [31:0] slave_rddata;
//------------------------------------------
//AD7656 interface
    reg[31:0]data_in_A/* synthesis noprune */;
    reg[31:0]data_in_B/* synthesis noprune */;
    
    output reg   CONVST;///
    output       sclk; ///
    output reg   ad_cs_n;
    input        DOUTA;//
    input        DOUTB;
//------------------------------------------------    
    
     reg [5:0] bitnum; ///
     
     reg [3:0]  delay_200ns; //
     reg [8:0]  delay_4_us;

     reg [2:0] cstate;//
     reg [2:0] nstate;//
     parameter empty=0,start=1,delay_4us=2,data_transfer=3,stop=4,transfer_interval=5;
//----------------------------------------------------------------------------------------------------
assign  sclk=sclking;    ///the deg is 0 compared with the primitive input clk
//-----------------------------------------------------------------------------------------------------
//reset  module-----we apply the asynchronous reset and release the reset  signal synchronously
reg rst_nr1,rst_nr2;
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)   rst_nr1<=0;
    else              rst_nr1<=1;
end

always @(posedge clk  or negedge rst_n)begin
    if(!rst_n)       rst_nr2<=0;
    else                  rst_nr2<=rst_nr1;
end
//-------------------------------------------------------------------------------------------------------
//pulse-generation technique---refer to Recommend Design Practices (9-7) in Quartus II Help for details 
reg pulse1,pulse2;
wire sclk_neg;  //check the  negedge edge of sclk
always @(posedge clk or  negedge  rst_nr2)begin
    if(!rst_nr2)begin
        pulse1<=1;
        pulse2<=1;    
    end
    else  begin
        pulse1<=sclk;
        pulse2<=pulse1;                
    end
end

assign  sclk_neg=(~pulse1)&&pulse2;
//------------------------------------------------------------------------------------------------------------
reg pulse3,pulse4;
wire sclk_pos;  //check the  posedge edge of sclk
always @(posedge clk or  negedge  rst_nr2)begin
    if(!rst_nr2)begin
        pulse3<=0;
        pulse4<=0;    
    end
    else  begin
        pulse3<=sclk;
        pulse4<=pulse3;                
    end
end
assign  sclk_pos=pulse3&&(~pulse4);
//---------------------------------------------------------------------------------------------------------
//assign ad_cs_n=~(nstate==data_transfer|nstate==start);
//----------------------------------------------------------------------------------------------------
always @(posedge clk or negedge rst_nr2)
begin
    if(!rst_nr2)                 bitnum<=6'd0; 
    else if(nstate==start)    bitnum<=6'd31;
    else if((nstate==data_transfer)&& sclk_neg)   bitnum<=bitnum-1;
    else if(nstate==stop)    bitnum<=0;
end
//-----------------------------------------------------------------------------------------------------
//delay  module-----------delay  4us to save conversion's time
always@(posedge clk or negedge rst_nr2)//develop  latch??
    if(!rst_nr2)                                      delay_4_us<=0;
    else if((nstate==delay_4us)&&sclk_pos)  delay_4_us<= delay_4_us+1'd1;//why nstate??
    else if(nstate==empty)                        delay_4_us<=0;    
   wire flag_4us=(delay_4_us==4);//the mark of counter's arrival 
//---------------------------------------------------------------------------------------------------
//delay  module-----------delay  200ns to indicate transfer interval
always@(posedge clk or negedge rst_nr2)//develop  latch
    if(!rst_nr2)                                      delay_200ns<=0;
    else if((nstate==transfer_interval)&&sclk_neg)    delay_200ns<= delay_200ns+1'd1;
    else if(nstate==empty)                        delay_200ns<=0;    
   wire flag_200ns=(delay_200ns==1); //the mark of counter's arrival     
//----------------------------------------------------------------------------------------------------
always @(posedge clk or negedge rst_nr2)    
begin
     if(!rst_nr2) cstate<=empty;
     else begin
            cstate <= nstate;
         end
end
//----------------------------------------------------------------------------------------------------
always @(cstate or sclk_neg or bitnum or flag_4us or flag_200ns)  //this is a combinational logic
        begin
                case (cstate)
                empty:  nstate <= delay_4us;                                 
                delay_4us: begin   ///
                    if (flag_4us&&sclk_neg)
                        nstate = start;                                                 
                    else
                        nstate = delay_4us;
                end
                start: begin
                    if (sclk_neg)
                    begin
                        nstate = data_transfer;
                    end
                    else
                        nstate = start;
                end
                data_transfer: begin
                    if (sclk_neg&&(bitnum==6'd0))
                        nstate = stop;
                    else
                        nstate = data_transfer;
                end
                stop: begin   //question 
                    if (sclk_neg)
                        nstate = transfer_interval;
                    else
                        nstate = stop;
                end
                transfer_interval: begin //cun zai wen  ti 
                    if (flag_200ns&&sclk_neg)
                        nstate = empty;
                    else
                        nstate = transfer_interval;
                end
               default:  begin 
                          nstate  = 'hx; 
                     end        
            endcase
            end
//---------------------------------------------------------------------------------------------------
//3rd always block,the sequential FSM output
always @(posedge clk or negedge rst_nr2)    
     if(!rst_nr2) begin
             CONVST<=0;
                ad_cs_n<=1; 
                end
     else begin
                begin
                CONVST<=0;
                ad_cs_n<=1; 
                end
            case(cstate)
            empty:          begin 
                        CONVST<=0;
                        ad_cs_n<=1; 
                            end
            delay_4us:  begin 
                        CONVST<=1;
                            ad_cs_n<=1; 
                            end
            start:          begin 
                            CONVST<=1; 
                            ad_cs_n<=0; 
                            end
            data_transfer:begin 
                            if(bitnum==16&&(sclk ==1))
                              begin
                                CONVST<=1;
                                ad_cs_n<=1; 
                              end
                            else
                              begin
                               CONVST<=1;
                                ad_cs_n<=0; 
                              end
                            end
            stop:            begin 
                            CONVST<=1;
                            ad_cs_n<=1; 
                            end
            transfer_interval:begin
                        CONVST<=0;
                            ad_cs_n<=1; 
                            end
         endcase
         end
//-------------------------------------------------------------------------------------------------------
//Avalon--MM interface
wire slave_rdcs_n=slave_rd_n|slave_cs_n;

always@(posedge clk or negedge rst_nr2)
begin 
        if(!rst_nr2)     slave_rddata[31:0]<=0;
        else if(slave_rdcs_n && slave_address==2'h0)  
        slave_rddata[31:0]<=data_in_A;
        else if(slave_rdcs_n && slave_address==2'h1)  
        slave_rddata[31:0]<=data_in_B;
        else
        slave_rddata[31:0]<=slave_rddata[31:0];        
end
//----------------------------------------------------------------------------------------------------
always @(posedge clk or negedge rst_nr2)
    if(!rst_nr2)begin            
        data_in_A[31:0]<=0;
        data_in_B[31:0]<=0;
        end
    else if((nstate==data_transfer)&&sclk_neg)begin   
       data_in_A[bitnum]<=DOUTA; 
        data_in_B[bitnum]<=DOUTB;
        end
        
//------------------------------------------------------------------------------------------------------
endmodule 


http://www.ppmy.cn/ops/11822.html

相关文章

给rwkv_pytorch配了个流式服务和请求demo

项目地址 rwkv_pytorch 服务端 import json import uuid import timeimport torch from src.model import RWKV_RNN from src.sampler import sample_logits from src.rwkv_tokenizer import RWKV_TOKENIZER from flask import Flask, request, jsonify, Responseapp Flask…

学习笔记-数据结构-线性表(2024-04-16)

设计一个算法判断单链表中元素是否是递增的。 设计思想&#xff1a;双指针操作 变量说明&#xff1a; head表示链表头指针 p和q表示两个用来遍历链表的指针节点&#xff0c;且q始终在p之后 bool IsIncrease(LinkList *head) {// 代码优先判空&#xff0c;若为空链表&#xff…

linux的一些实用操作

快捷键 强制停止 ctrlc强制停止或退出命令的输入 退出登出 ctrld强制退出用户登录或退出某些程序的专属页面&#xff08;如py&#xff09; ps&#xff1a;不能退出vi/vim 历史命令搜索 history可以查看历史命令&#xff0c;用来复制粘贴 在使用history之后&#xff0c;…

Midjourney 中文文档

快速使用 学习如何在Discord上使用Midjourney Bot从简单的文本提示中创建自定义图像。 行为准则 不要表现出不良行为。不要使用我们的工具制作可能引起煽动&#xff0c;不安或引起争议的图像。这包括血腥和成人内容。尊重其他人和团队。 1&#xff1a;加入Discord 访问Midj…

C#开发UdpClient无法在局域网中发送UDP广播包,但能接收的解决办法

# 记得开发好的软件原来可以使用的&#xff0c;今天突然不正常了&#xff0c;还以为哪里修改过了。 在网上看到了一个网友的文章&#xff1a;https://www.cnblogs.com/kissazi2/archive/2012/12/07/2806533.html 我虽然没有安装虚拟机&#xff0c;没有VMware的虚拟网卡&#…

西瓜书学习——对数几率回归

对数几率回归&#xff08;Logistic Regression&#xff09;是一种广泛应用于分类问题的统计方法&#xff0c;特别是用于二分类问题。尽管它的名字中包含“回归”&#xff0c;但它实际上是一种分类算法&#xff0c;用于估计一个样本属于某个类别的概率。 对数几率回归的核心是使…

C++ day1

const char *p; 可以改变p的值&#xff0c;不可以改变p指向的字符的值。 const (char *) p; 语法错误 char *const p; 可以改变p指向的字符值 不可以改变p的值 const char* const p; 都不可以改变 char const *p; 可以改变p的值 不可以改变 p指向的字符的值 …

CUDA 以及MPI并行矩阵乘连接服务器运算vscode配置

一、CUDA Vscode配置 &#xff08;一&#xff09;扩展安装 本地安装 服务器端安装 &#xff08;二&#xff09; CUDA 配置 .vscode c_cpp_properties.json {"configurations": [{"name": "Linux","includePath": ["${workspa…