module AD_TLC549
#(parameter T_conv=12'd850,//轉換時間50M*17us=850parameter T_su=8'd70,//準備時間50M*1.4us=70usparameter AD_CLK_nop=4'd8,//定義8個AD_CLKparameter AD_CLK_circle_time=6'd46,//0.92usparameter AD_CLK_circle_time_half=6'd23 //23*50=0.46us
)
(
input sys_clk,
input RST_N,
input AD_DATA,
//-------------------
output AD_CLK,
output CS_N,output reg [AD_CLK_nop-1:0] AD_out_DATA //串行的AD_DATA轉并行的8位寄存器);wire AD_CLK_edg;
reg AD_out_reg_finish;//串行轉并行完成標志
reg [11:0] T_conv_cnt=0;//轉換時間的計數器
reg [7:0] T_su_cnt=0;//準備時間的計數器
reg [3:0] AD_CLK_cnt=0;//AD_CLK個數計數器
reg [5:0] AD_CLK_circle_time_cnt=0;//一個AD_CLK的高/低電平時間計數器
reg AD_CLK_reg_reg;//用于緩存一拍AD_CLK,實現下降沿檢測//設置輸出寄存器
reg AD_CLK_reg=0;
reg CS_N_reg;reg [AD_CLK_nop-1:0] AD_out_reg;//采用三段式狀態機
/*有限狀態機,三段式建模風格*/
/*三個過程*/
//狀態編碼
localparam transition_state = 3'b001,//數據轉換狀態ready_1_4_state = 3'b010,//準備采樣狀態Acess_sample_state = 3'b100;//采樣狀態
//這里可以把數據轉換狀態視作初始狀態,1沒有時鐘,2 CS_N為高,也無效。
reg [2:0] now_state=transition_state;
reg [2:0] next_state=transition_state;//1.實現狀態轉換:實現當前狀態now_state到next_state的轉換
always @ (posedge sys_clk)
beginif(!RST_N)now_state<=transition_state;elsenow_state<=next_state;
end
//2.設置狀態切換條件,產生下一個狀態
always@(*)
begincase(now_state)transition_state:if(T_conv_cnt==T_conv) //如果轉換時間36next_state=ready_1_4_state;elsenext_state=transition_state;ready_1_4_state:if(T_su_cnt==T_su)next_state=Acess_sample_state;elsenext_state=ready_1_4_state; Acess_sample_state:if(AD_CLK_cnt<AD_CLK_nop)next_state=Acess_sample_state;elsenext_state=transition_state; default:;endcaseend//3.產生每個狀態機的條件輸出值
always @ (posedge sys_clk)
begincase(next_state)transition_state:beginT_conv_cnt<=T_conv_cnt+1;T_su_cnt<=0;AD_CLK_cnt<=0;endready_1_4_state:beginT_su_cnt<=T_su_cnt+1;T_conv_cnt<=0;endAcess_sample_state:beginif (AD_CLK_edg)AD_CLK_cnt <= AD_CLK_cnt + 1'b1;elseAD_CLK_cnt <= AD_CLK_cnt;endendcaseend
//4.設置每個輸出值
//1.CS_N的輸出值
always@(posedge sys_clk)
beginif(!RST_N)beginCS_N_reg<=1; //end else if(now_state==transition_state)beginCS_N_reg<=1; //endelse beginCS_N_reg<=0; //CS_N低電平有效end
end
assign CS_N=CS_N_reg;//2.AD_CLK的輸出值
always@(posedge sys_clk)
beginif(!RST_N)AD_CLK_circle_time_cnt<=0;else if(now_state==Acess_sample_state)AD_CLK_circle_time_cnt<=(AD_CLK_circle_time_cnt<AD_CLK_circle_time-1)?(AD_CLK_circle_time_cnt+1'b1):0;elseAD_CLK_circle_time_cnt<=0;
endalways@ (posedge sys_clk)
beginif(!RST_N)AD_CLK_reg<=0;else if(now_state==Acess_sample_state)AD_CLK_reg <= (AD_CLK_circle_time_cnt <=AD_CLK_circle_time_half-1) ? 1'b1 : 1'b0;elseAD_CLK_reg<=0;
end
//3.AD_CLK_nop_edg控制
always @ (posedge sys_clk)
beginAD_CLK_reg_reg<=AD_CLK_reg; //寄存一拍
endassign AD_CLK_edg = AD_CLK_reg_reg&(~AD_CLK_reg);//判斷下降沿assign AD_CLK=AD_CLK_reg;//4.AD_DATA_reg控制讀取........控制在什么時候,把串行AD_DATA的數據寫入多位的寄存器AD_DATA_reg之中,時機不對,自然寫入的數肯定就不對
always @ (posedge sys_clk)
beginif((now_state==ready_1_4_state)&(next_state==Acess_sample_state))AD_out_reg[AD_CLK_nop-1]<=AD_DATA;else if(AD_CLK_edg&(AD_CLK_cnt<=AD_CLK_nop-1))AD_out_reg[AD_CLK_nop-1-1:0]<={AD_out_reg[AD_CLK_nop-1-1-1:0],AD_DATA};//移位循環實現串行轉并行else if(AD_CLK_cnt==AD_CLK_nop)//在第8個時鐘下降沿的時候,代表了AD_DATA_reg已經移位完成,之所以沒有剛好設置第7個下降沿,是擔心第7個下降沿還在讀取。AD_out_reg_finish<=1;elsebeginAD_out_reg<=AD_out_reg;AD_out_reg_finish<=0; endendalways @ (posedge sys_clk)
beginif(AD_out_reg_finish==1) //只有在讀取8位完畢后,再將這8位數更新AD_out_DATA<=AD_out_reg;elseAD_out_DATA<=AD_out_DATA;
endendmodule
// Copyright (C) 1991-2013 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.// *****************************************************************************
// This file contains a Verilog test bench template that is freely editable to
// suit user's needs .Comments are provided in each section to help the user
// fill out necessary details.
// *****************************************************************************
// Generated on "11/08/2018 16:19:41"// Verilog Test Bench template for design : AD_TLC549
//
// Simulation tool : ModelSim (Verilog)
// `timescale 1 ns/ 1 ps
module AD_TLC549_vlg_tst();
// constants
// general purpose registers
reg eachvec;
// test vector input registers
reg AD_DATA;
reg RST_N;
reg sys_clk;
// wires
wire AD_CLK;
wire [7:0] AD_out_DATA;
wire CS_N;// assign statements (if any)
AD_TLC549 i1 (
// port map - connection between master ports and signals/registers .AD_CLK(AD_CLK),.AD_DATA(AD_DATA),.AD_out_DATA(AD_out_DATA),.CS_N(CS_N),.RST_N(RST_N),.sys_clk(sys_clk)
);
initial
begin
$display("Running testbench");
#0 sys_clk=0;
#0 RST_N=0;
#40 RST_N=1;
#0 AD_DATA=1;end
//------------------------------------------
always
begin #10 sys_clk=~sys_clk; end
endmodule