基于verilog及DA9709的DDS设计
DDS(Direct Digtal Synthesizer) 直接数字合成器
相位累加器、LUT、DAC
top.v, dds_ctrl.v, dds_wave.v, DA.v。
dds_wave.v cfg_mode=0,1,2控制三种波形,0-sin,1-斜坡,2-方波
dds_ctrl.v cfg_add控制波形频率 cfg_repeat控制波形重复几个周期 输出为每x个周期内的采样点数,即cfg_add
三个计数器完成x+x+x个周期的波形,循环……
assign add_cnt0=1;
assign end_cnt0= (add_cnt0)&&(cnt0==cfg_time-1);//波形单个周期=cfg_time个Tclk
assign add_cnt1=end_cnt0;
assign end_cnt1= (add_cnt1)&&(cnt1==x-1);//波形重复x个周期,每x个周期内可通过cfg_add设置频率
assign add_cnt2=end_cnt1;
assign end_cnt2= (add_cnt2)&&(cnt2==3-1);///// x个周期再x个周期再x个周期,然后循环
always @(*)begin
if(cnt2==0) begin
x = cfg_repeat0;
y = cfg_add0 ;
end
else if(cnt2==1)begin
x = cfg_repeat1;
y = cfg_add1 ;
end
else begin///2
x = cfg_repeat2;
y = cfg_add2 ;
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
dout <= 0;
end
else if(cfg_en) begin
dout <= y ;
end
else begin
dout <= 0;
end
end
dds_wave.v 接收上个模块的采样点数,输出波形对应的采样值wave_dout
parameter C_W=16;
reg [C_W-1 :0] addr;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
addr <= 0;
end
else if(din_vld) begin
addr <= addr + din_add ;//din_add即dds_ctrl的dout
end
end
组合逻辑输出sin_data (addr高8位128种情况下对应的sin值)
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
wave_dout <= 0;
end
else if(cfg_mode==0) begin
wave_dout <= sin_data;
end
else if(cfg_mode==1)begin
wave_dout <= addr[C_W-1 -:8];//从C_W-1往下数8位//输出递增地址即斜坡
end
else if(cfg_mode==2)begin
wave_dout <= 8'b11110000;//方波
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
dout_vld <= 0;
end
else begin
dout_vld <= dout_rdy;//dout_rdy由AD.v的din_ready得到
end
end
AD.v 最终输出dac_da就是wave_out延迟一拍(在din_vld高期间)
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
dac_da<=0;
end
else if (din_vld) begin
dac_da<=din;
end
end
always @ (*) begin
if (flag_add_tmp)
din_ready=0;
else
din_ready=1;
end
always @ (*) begin
if (din_vld) begin
flag_add_tmp=1;
end
else if (end_cnt0) begin
flag_add_tmp=0;
end
else begin
flag_add_tmp=flag_add;// 即 flag_add_tmp上一拍
end
end
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
flag_add<=0;
end
else begin
flag_add<=flag_add_tmp;
end
end
assign add_cnt0=flag_add;
assign end_cnt0=(add_cnt0)&&(cnt0==2-1);
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
dac_clka<=0;
end
else if (add_cnt0 && cnt0==1-1) begin //0期间高
dac_clka<=1;
end
else if (end_cnt0) begin// 1期间低
dac_clka<=0;
end
斜坡 128 128 128
sin 64 128 256
串口
添加串口,由串口控制dds_ctrl的输入
其中uart_cfg由4个module构成
1.1 uart_rx
cnt0计数BPS
cnt1计9个BPS
//2个计数器共计9个 长度为BPS的
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt0 <= 0;
end
else if(add_cnt0)begin
if(end_cnt0)
cnt0 <= 0;
else
cnt0 <= cnt0 + 1;
end
end
assign add_cnt0 = flag_add;
assign end_cnt0 = add_cnt0 && cnt0==BPS-1 ;
//cnt1计9个cnt0
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt1 <= 0;
end
else if(add_cnt1)begin
if(end_cnt1)
cnt1 <= 0;
else
cnt1 <= cnt1 + 1;
end
end
assign add_cnt1 = end_cnt0;
assign end_cnt1 = add_cnt1 && cnt1==9-1 ;
其中flag_add:rx刚拉低的后一个T flag_add拉高,cnt0计数,直到end_cnt1再拉低。
也就是说重复9个BPS之后,cnt0就不再计数了
assign rx_en = rx2 & ~rx1; //rx1为rx打一拍,rx2为rx打2拍
//rx刚拉低的后一个T flag_add拉高,cnt0计数,直到end_cnt1再拉低
always @ (posedge clk or negedge rst_n)begin
if(!rst_n) begin
flag_add <= 1'b0;
end
else if(rx_en) begin
flag_add <= 1'b1;
end
else if(end_cnt1) begin
flag_add <= 1'b0;
end
//否则不变
end
8位的rx_dout 是 1位rx 的串转并,在后面8个BPS一半处转
//9个BPS周期中 每个周期(除去第一个周期)的一半处 rx_dout的0-7位<=rx2(串转并)
always @ (posedge clk or negedge rst_n)begin
if(!rst_n) begin
rx_dout <= 8'd0;
end
else if(add_cnt0 && cnt0==BPS/2-1 && cnt1!=0) begin//cnt1=1-8
rx_dout[cnt1-1]<= rx2 ;//分别为rx_dout的0-7位 对应 cnt1=1-8时的中间处
end
end
rx_dout_vld是end_cnt1打一拍,9个BPS结束处打一拍
always @ (posedge clk or negedge rst_n)begin
if(!rst_n) begin
rx_dout_vld <= 1'b0;
end
else if(end_cnt1) begin
rx_dout_vld <= 1'b1;
end
else begin
rx_dout_vld <= 1'b0;
end
end
1.2 uart_cfg_s2p 有些奇怪
parameter D_W=128;
output [ D_W-1:0] s2p_dout ;
在top_uart.v文件中 .cfg_head (16’hd5d5) ,
//计6个(9个BPS) 0-5 //接着串 uart_rt.v 的cnt1 (flag_head为1时)
always @(posedge clk or negedge rst_n) begin
if (rst_n==0) begin
s2p_cnt0 <= 0;
end
else if(add_cnt0) begin
if(end_cnt0)
s2p_cnt0 <= 0;
else
s2p_cnt0 <= s2p_cnt0+1 ;
end
end
assign add_cnt0 = flag_head;
assign end_cnt0 = add_cnt0 && s2p_cnt0 == 6-1 ;