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;文章来源:https://www.toymoban.com/news/detail-858848.html
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 文章来源地址https://www.toymoban.com/news/detail-858848.html
到了这里,关于挂在Avalon总线上的AD7656芯片驱动verilog程序实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!