|
AD9833的控制可以分为以下几步:
1、写控制寄存器。复位等。
2、写频率寄存器低位。
3、写频率寄存器高位。
4、写相位寄存器。
5、写输出使能。
6、延时后输出有效。
百度了以下,控制字可以分别写入:0X2100,0X4A7C,0X4000,0XC000,0X0000。可以使芯片输出100HZ正弦波。如果需要调整频率,调整第二个和第三个控制字即可。
所以,在编写verilog程序时候,考虑分:IDLE,START,WR_CTR,WR_F_L,WR_F_M,WR_PHASE,WR_EN,DEALY,OVER,这几个状态,依次为“空闲、开始、写控制寄存器、写频率低位、写频率高位、写相位、写输出是能控制字、延时、结束”。然后再用一个计数器,在每个状态开始的时候,由0计数到17,对应的在0-15,或者1-16的时候写数据。特别要注意每次状态转换时候要清零。
程序如下:
module dds_ad9833(clk,rst_n,start_config,fsync,spi_data,spi_clk,out_cnt2,out_state,out_cnt1,state_flag,fsync_reg_r);
input clk,
rst_n,
start_config;
output fsync,
spi_data,
spi_clk;
output wire[4:0] out_cnt2;
output wire[9:0] out_state;
output wire[4:0] out_cnt1;
assign out_state = cstate;///////////////
assign out_cnt1 = cnt1;
parameter IDLE = 10'b00_0000_0001,//--1
START = 10'b00_0000_0010,//2
WR_CTR = 10'b00_0000_0100,//4
WR_F_L = 10'b00_0000_1000,//8
WR_F_M = 10'b00_0001_0000,//16
WR_PHASE = 10'b00_0010_0000,//32
WR_EN = 10'b00_0100_0000,//64
DELAY = 10'b00_1000_0000,//128
OVER = 10'b01_0000_0000;//
//------------------产生分频信号------------------------
reg[4:0]cnt1;
reg spi_clk_r;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt1 <= 5'd0;
else if(fsync_reg_r==1)///////////++
cnt1 <= 5'd0;
else
cnt1 <= cnt1 + 1'b1;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
spi_clk_r <= 1'b0;
else if(cstate==OVER)
spi_clk_r <= 1'bz;
else if(((cnt2==5'd16)||(cnt2==5'd17))&&(cstate!=WR_CTR))
spi_clk_r <= 1'b0;
/*else if((cnt2==5'd15)&&(cnt1==5'd16))
spi_clk_r <= 1'b0;*/
else
begin
case(cnt1)
5'd0,5'd1,5'd2,5'd3,
5'd4,5'd5,5'd6,5'd7,
5'd8,5'd9,5'd10,5'd11,
5'd12,5'd13,5'd14,5'd15: spi_clk_r <= 1'b0;
5'd16,5'd17,5'd18,5'd19,
5'd20,5'd21,5'd22,5'd23,
5'd24,5'd25,5'd26,5'd27,
5'd28,5'd29,5'd30,5'd31: spi_clk_r <= 1'b1;
default: spi_clk_r <= 1'b0;
endcase
end
end
assign spi_clk = spi_clk_r;
//----------------------------------------------
reg[15:0]ctr_reg;
reg[15:0]fsl_reg;
reg[15:0]fsm_reg;
reg[15:0]phase_reg;
reg[15:0]en_reg;
reg[9:0]cstate,
nstate;
reg[4:0]cnt2;
reg spi_data_reg;
reg fsync_reg;
reg state_finish;
//----------------------------------
output wire fsync_reg_r;
reg fsync_reg_n;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
fsync_reg_n <= 1'b1;
else
fsync_reg_n <= fsync_reg;
end
assign fsync_reg_r = ((~fsync_reg_n)&&(fsync_reg));//
//-----------------------------------
output wire state_flag;
assign state_flag = state_finish;
always@(posedge clk or negedge rst_n)//对分频的时钟上升沿计数,计满17次清零
begin
if(!rst_n)
cnt2 <= 5'd0;
else if((fsync_reg_r==1'b1)&&(cnt1==5'd16))//
cnt2 <= 5'd0;
else if((cnt2==5'd17)&&(cnt1==5'd16))//++
cnt2 <= 5'd0;//
else if(cnt1==5'd16)
cnt2 <= cnt2 + 1'b1;
end
assign out_cnt2 = cnt2;
always@(posedge clk or negedge rst_n)//操作状态机
begin
if(!rst_n)
cstate <= IDLE;
else
cstate <= nstate;
end
always@(cstate or start_config or cnt2)
begin
case(cstate)
IDLE:
begin
//state_finish = 1'b0
fsync_reg = 1'b1;
if(start_config==1'b1)
begin
nstate = START;
end
else
begin
nstate = IDLE;
end
end
START:
begin
/*if(start_config==1'b1)//
begin
nstate = WR_CTR;
end
else
nstate = IDLE;*/
nstate = WR_CTR;
end
WR_CTR:
begin
case(cnt2)
5'd0:
begin
if(cnt1==5'd16)
begin
//state_finish = 1'b0;
fsync_reg = 1'b0;
spi_data_reg = 1'b0;
end
else
begin
fsync_reg = 1'b1;
spi_data_reg = 1'b0;
end
end/*
begin
//state_finish = 1'b0;
fsync_reg = 1'b0;
spi_data_reg = 1'b0;
end*/
5'd1:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd2:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd3:
begin
fsync_reg = 0;
spi_data_reg = 1'b1;
end
5'd4:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd5:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd6:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd7:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd8:
begin
fsync_reg = 0;
spi_data_reg = 1'b1;
end
5'd9:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd10:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd11:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd12:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd13:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd14:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd15:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd16:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd17:
begin
if(cnt1==5'd16)
begin
nstate = WR_F_L;
fsync_reg = 1'b1;
//state_finish = 1'b1;
spi_data_reg = 1'bz;
end
else
begin
nstate = WR_CTR;
fsync_reg = 1'b1;
spi_data_reg = 1'bz;
end
end
default:
begin
spi_data_reg = 1'bz;
nstate = WR_CTR;
end
endcase
end
WR_F_L: ////8state
begin
case(cnt2)
5'd0:
/*begin
if(cnt1==5'd16)
begin
//state_finish = 1'b0;
fsync_reg = 1'b0;
spi_data_reg = 1'b0;
end
else
begin
fsync_reg = 1'b1;
spi_data_reg = 1'b0;
end
end*/
begin
//state_finish = 1'b0;
fsync_reg = 0;
spi_data_reg = 1'b0;
nstate = WR_F_L;
end
5'd1:
begin
fsync_reg = 0;
spi_data_reg = 1'b1;
nstate = WR_F_L;
end
5'd2:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
nstate = WR_F_L;
end
5'd3:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
nstate = WR_F_L;
end
5'd4:
begin
fsync_reg = 0;
spi_data_reg = 1'b1;
nstate = WR_F_L;
end
5'd5:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
nstate = WR_F_L;
end
5'd6:
begin
fsync_reg = 0;
spi_data_reg = 1'b1;
nstate = WR_F_L;
end
5'd7:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
nstate = WR_F_L;
end
5'd8:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
nstate = WR_F_L;
end
5'd9:
begin
fsync_reg = 0;
spi_data_reg = 1'b1;
nstate = WR_F_L;
end
5'd10:
begin
fsync_reg = 0;
spi_data_reg = 1'b1;
nstate = WR_F_L;
end
5'd11:
begin
fsync_reg = 0;
spi_data_reg = 1'b1;
nstate = WR_F_L;
end
5'd12:
begin
fsync_reg = 0;
spi_data_reg = 1'b1;
nstate = WR_F_L;
end
5'd13:
begin
fsync_reg = 0;
spi_data_reg = 1'b1;
nstate = WR_F_L;
end
5'd14:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
nstate = WR_F_L;
end
5'd15:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
nstate = WR_F_L;
end
5'd16:
begin
if(cnt1==5'd16)
begin
nstate = WR_F_M;
fsync_reg = 1'b1;
spi_data_reg = 1'bz;
//state_finish = 1'b1;
end
else
begin//+
nstate = WR_F_L;
fsync_reg = 1'b1;
spi_data_reg = 1'bz;
end
end
default:
begin
spi_data_reg = 1'bz;
nstate = WR_F_L;
fsync_reg = 1'b1;//++
end
endcase
end
WR_F_M:
begin
case(cnt2)
5'd0:
/*begin
if(cnt1==5'd16)
begin
//state_finish = 1'b0;
fsync_reg = 1'b0;
spi_data_reg = 1'b0;
end
else
begin
fsync_reg = 1'b1;
spi_data_reg = 1'b0;
end
end*/
begin
//state_finish = 1'b0;
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd1:
begin
fsync_reg = 0;
spi_data_reg = 1'b1;
end
5'd2:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd3:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd4:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd5:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd6:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd7:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd8:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd9:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd10:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd11:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd12:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd13:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd14:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd15:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd16:
begin
if(cnt1==5'd16)
begin
nstate = WR_PHASE;
fsync_reg = 1'b1;
spi_data_reg = 1'bz;
//state_finish = 1'b1;
end
else
begin
nstate = WR_F_M;
fsync_reg = 1'b1;
spi_data_reg = 1'bz;
end
end
default:
begin
spi_data_reg = 1'bz;
nstate = WR_F_M;
fsync_reg = 1'b1;//++
end
endcase
end
WR_PHASE:
begin
case(cnt2)
5'd0:
/*begin
if(cnt1==5'd16)
begin
//state_finish = 1'b0;
fsync_reg = 1'b0;
spi_data_reg = 1'b1;
end
else
begin
fsync_reg = 1'b1;
spi_data_reg = 1'b1;
end
end*/
begin
//state_finish = 1'b0;
fsync_reg = 0;
spi_data_reg = 1'b1;
end
5'd1:
begin
fsync_reg = 0;
spi_data_reg = 1'b1;
end
5'd2:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd3:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd4:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd5:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd6:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd7:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd8:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd9:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd10:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd11:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd12:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd13:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd14:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd15:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd16:
begin
if(cnt1==5'd16)
begin
nstate = WR_EN;
fsync_reg = 1'b1;
spi_data_reg = 1'bz;
//state_finish = 1'b1;
end
else
begin
nstate = WR_PHASE;
fsync_reg = 1'b1;
spi_data_reg = 1'bz;
end
end
default:
begin
spi_data_reg = 1'bz;
nstate = WR_PHASE;
fsync_reg = 1'b1;//++
end
endcase
end
WR_EN:
begin
case(cnt2)
5'd0:
/*begin
if(cnt1==5'd16)
begin
//state_finish = 1'b0;
fsync_reg = 1'b0;
spi_data_reg = 1'b0;
end
else
begin
fsync_reg = 1'b1;
spi_data_reg = 1'b0;
end
end*/
begin
//state_finish = 1'b0;
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd1:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd2:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd3:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd4:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd5:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd6:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd7:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd8:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd9:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd10:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd11:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd12:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd13:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd14:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd15:
begin
fsync_reg = 0;
spi_data_reg = 1'b0;
end
5'd16:
begin
if(cnt1==5'd16)
begin
nstate = DELAY;
fsync_reg = 1'b1;
spi_data_reg = 1'bz;
//state_finish = 1'b1;
end
else
begin
nstate = WR_EN;
fsync_reg = 1'b1;
spi_data_reg = 1'bz;
end
end
default:
begin
spi_data_reg = 1'bz;
nstate = WR_EN;
fsync_reg = 1'b1;//++
end
endcase
end
DELAY:
begin
fsync_reg = 1'b1;
spi_data_reg = 1'bz;
if(cnt2==5'd16)
nstate = OVER;
else
nstate = DELAY;
end
OVER:
begin
spi_data_reg = 1'bz;
fsync_reg = 1'b1;
nstate = OVER;
end
default: nstate = IDLE;//
endcase
end
assign spi_data = spi_data_reg;
assign fsync = fsync_reg;
endmodule
注意的几个问题:
1、状态的划分要清晰
2、控制标志何时清零、清零信号的选择要注意
3、CASE语句中,每个case中对变量赋的值不会保持,综合出来是一个触发器,下一个case就会丢失,如果想让改变量保持住,在 每个case中都需要赋值。
4、时序仿真时,不知道为什么WR_F_L状态不稳定,故在每个case中加上了赋为本身状态的语句,再次仿真则稳定了。
5、控制信号都是相互关联的,牵一发而动全身,修改的时候要注意。往往改着改着自己都忘记这个是什么功能了。
6、检测信号上升沿可以用该信号下一个状态值与上当前状态值的非,检测信号下降沿,可以用该信号下一个状态值的非与上当前值。检测出来的信号可作为触发信号控制其他变量。
7、组合逻辑,只有触发变量发生变化时,下面的程序才会执行,时序逻辑在每个时钟内都执行一次,在编写控制电路的时候要注意 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。
|