目錄
?一、功能定義
二、設計輸入?
1、主模塊
2、DDS模塊
3、 按鍵消抖模塊
三、功能仿真?
四、綜合優(yōu)化
五、布局布線
六、時序仿真
七、板級調試?
代碼規(guī)范:Verilog 代碼規(guī)范_verilog代碼編寫規(guī)范-CSDN博客
開發(fā)流程:FPGA基礎知識----第二章 FPGA 開發(fā)流程_fpga 一個項目的整個流程-CSDN博客?
源碼下載:GitHub - Redamancy785/FPGA-Learning-Record: 項目博客:https://blog.csdn.net/weixin_51460407
?一、功能定義
二、設計輸入?
1、主模塊
這段代碼是一個Verilog模塊,名為
dds_ad9767
,它實現(xiàn)了一個雙通道的直接數(shù)字頻率合成器(DDS)系統(tǒng)。DDS是一種用于生成模擬波形(如正弦波、方波等)的電子技術,廣泛應用于信號發(fā)生器、通信系統(tǒng)等領域。這個模塊特別為與AD9767這類數(shù)字信號處理器(DSP)芯片協(xié)同工作而設計。
/*
Tips:
1、可分別于A、B通道同時輸出兩路波形
2、每次按下 f_switch_button_a_i , 通道A輸出頻率在預設的四種情況切換;通道B同理。
3、每次按下 p_switch_button_a_i , 通道A輸出相位在預設的兩種情況切換;通道B同理。
*/
module dds_ad9767(
reset_n_i,
clk_i,
mode_switch_button_a_i,
f_switch_button_a_i,
p_switch_button_a_i,
mode_switch_button_b_i,
f_switch_button_b_i,
p_switch_button_b_i,
data_a_o,
data_b_o
);
input reset_n_i,clk_i;
input [1:0]mode_switch_button_a_i,mode_switch_button_b_i;
input f_switch_button_a_i,p_switch_button_a_i,f_switch_button_b_i,p_switch_button_b_i;
output [13:0] data_a_o;
output [13:0] data_b_o;
// A通道dds例化
reg [31:0] u_f_word_a;
reg [11:0] u_p_word_a;
dds U_dds_a(
.reset_n_i(reset_n_i),
.clk_i(clk_i),
.f_word_i(u_f_word_a),
.p_word_i(u_p_word_a),
.mode_i(mode_switch_button_a_i),
.data_o(data_a_o)
);
// A通道頻率切換
wire f_switch_button_a_press_key_flag;
key_filter U_f_switch_button_a_i(
.clk_i(clk_i),
.reset_n_i(reset_n_i),
.key_i(f_switch_button_a_i),
.press_key_flag_o(f_switch_button_a_press_key_flag)
);
reg [1:0] f_switch_cnt_a;
always@(posedge clk_i or negedge reset_n_i)
if(!reset_n_i)
f_switch_cnt_a <= 0;
else if(f_switch_button_a_press_key_flag == 1)
f_switch_cnt_a <= f_switch_cnt_a + 1;
always@(*)
case(f_switch_cnt_a)
0 : u_f_word_a <= 65536;
1 : u_f_word_a <= 65536*2;
2 : u_f_word_a <= 65536*3;
3 : u_f_word_a <= 65536*4;
endcase
// A通道相位切換
wire p_switch_button_a_press_key_flag;
key_filter U_p_switch_button_a_i(
.clk_i(clk_i),
.reset_n_i(reset_n_i),
.key_i(p_switch_button_a_i),
.press_key_flag_o(p_switch_button_a_press_key_flag)
);
reg p_switch_cnt_a;
always@(posedge clk_i or negedge reset_n_i)
if(!reset_n_i)
p_switch_cnt_a <= 0;
else if(p_switch_button_a_press_key_flag == 1)
p_switch_cnt_a <= p_switch_cnt_a + 1;
always@(*)
case(p_switch_cnt_a)
0 : u_p_word_a <= 0;
1 : u_p_word_a <= 1024;
endcase
// B通道dds例化
reg [31:0] u_f_word_b;
reg [11:0] u_p_word_b;
dds U_dds_b(
.reset_n_i(reset_n_i),
.clk_i(clk_i),
.f_word_i(u_f_word_b),
.p_word_i(u_p_word_b),
.mode_i(mode_switch_button_b_i),
.data_o(data_b_o)
);
// B通道頻率切換
wire f_switch_button_b_press_key_flag;
key_filter U_f_switch_button_b_i(
.clk_i(clk_i),
.reset_n_i(reset_n_i),
.key_i(f_switch_button_b_i),
.press_key_flag_o(f_switch_button_b_press_key_flag)
);
reg [1:0] f_switch_cnt_b;
always@(posedge clk_i or negedge reset_n_i)
if(!reset_n_i)
f_switch_cnt_b <= 0;
else if(f_switch_button_b_press_key_flag == 1)
f_switch_cnt_b <= f_switch_cnt_b + 1;
always@(*)
case(f_switch_cnt_b)
0 : u_f_word_b <= 65536;
1 : u_f_word_b <= 65536*2;
2 : u_f_word_b <= 65536*3;
3 : u_f_word_b <= 65536*4;
endcase
// B通道相位切換
wire p_switch_button_b_press_key_flag;
key_filter U_p_switch_button_b_i(
.clk_i(clk_i),
.reset_n_i(reset_n_i),
.key_i(p_switch_button_b_i),
.press_key_flag_o(p_switch_button_b_press_key_flag)
);
reg p_switch_cnt_b;
always@(posedge clk_i or negedge reset_n_i)
if(!reset_n_i)
p_switch_cnt_b <= 0;
else if(p_switch_button_b_press_key_flag == 1)
p_switch_cnt_b <= p_switch_cnt_b + 1;
always@(*)
case(p_switch_cnt_b)
0 : u_p_word_b <= 0;
1 : u_p_word_b <= 1024;
endcase
endmodule
?2、DDS模塊
1、IP設置
?
?
?2、初始文件生成設置
3、代碼部分
這段代碼是一個Verilog模塊,名為
dds
,它實現(xiàn)了一個直接數(shù)字頻率合成器(DDS)的功能。DDS是一種電子系統(tǒng),能夠通過數(shù)字技術生成模擬波形,如正弦波、方波和三角波等。這個模塊通過接收頻率字(f_word_i
)和相位字(p_word_i
)輸入,以及模式選擇信號(mode_i
),來輸出相應的波形數(shù)據(jù)。
/*
Tips:
1、修改 mode_i 可以切換三種不同的輸出波形
2、f_word_i 頻率字輸入,當?shù)扔诘湫椭?^16=65536時,dds輸出的波形頻率在738Hz左右
3、p_word_i 相位字輸入,當?shù)扔诘湫椭?024時,dds輸出的波形起始相位為90°
*/
module dds(
reset_n_i,
clk_i,
f_word_i,
p_word_i,
mode_i,
data_o
);
input [1:0] mode_i;
input reset_n_i,clk_i;
input [31:0]f_word_i;
input [11:0]p_word_i;
output reg [13:0] data_o;
// 頻率字輸入寄存器 r_f_word_i
reg [31:0] r_f_word_i;
always@(posedge clk_i)
r_f_word_i <= f_word_i;
// 相位字輸入寄存器 r_f_word_i
reg [11:0] r_p_word_i;
always@(posedge clk_i)
r_p_word_i <= p_word_i;
// 相位累加器 phase_accumulator
reg [31:0] phase_accumulator;
always@(posedge clk_i or negedge reset_n_i)
if(!reset_n_i)
phase_accumulator <= 0;
else
phase_accumulator <= phase_accumulator + r_f_word_i;
// 波形數(shù)據(jù)表地址 rom_addr
reg [11:0] rom_addr;
always@(posedge clk_i or negedge reset_n_i)
if(!reset_n_i)
rom_addr <= 0;
else
rom_addr <= r_p_word_i + phase_accumulator[31:20];
// sine波形
wire [13:0] sine_data_o;
sine_rom U_sine_rom (
.clka(clk_i), // input wire clka
.addra(rom_addr), // input wire [11 : 0] addra
.douta(sine_data_o) // output wire [13 : 0] douta
);
// square波形
wire [13:0] square_data_o;
square_rom U_square_rom (
.clka(clk_i), // input wire clka
.addra(rom_addr), // input wire [11 : 0] addra
.douta(square_data_o) // output wire [13 : 0] douta
);
// triangular波形
wire [13:0] triangular_data_o;
triangular_rom U_triangular_rom (
.clka(clk_i), // input wire clka
.addra(rom_addr), // input wire [11 : 0] addra
.douta(triangular_data_o) // output wire [13 : 0] douta
);
// 模式選擇
always@(*)
case(mode_i)
0 : data_o = sine_data_o;
1 : data_o = square_data_o;
2 : data_o = triangular_data_o;
3 : data_o = 8192;
endcase
endmodule
3、 按鍵消抖模塊
這段代碼是一個Verilog模塊,名為
key_filter
,它實現(xiàn)了一個按鍵濾波器的功能。該模塊用于檢測按鍵的按下和釋放,并確保按鍵動作至少持續(xù)20毫秒。模塊提供了按鍵按下和釋放的輸出標志,以及當前按鍵的狀態(tài)。
/*
Tips:
1、檢測到按鍵按下,會產生一個周期的 press_key_flag_o 提示信號
2、按鍵按下時間需要持續(xù)20ms
*/
module key_filter(
clk_i,
reset_n_i,
key_i,
press_key_flag_o,
release_key_flag_o,
key_state_o
);
input clk_i,reset_n_i,key_i;
output press_key_flag_o,release_key_flag_o,key_state_o;
reg press_key_flag_o,release_key_flag_o;
reg [1:0] state;
wire time_20ms_reached;
reg key_state_o;
localparam IDLE = 0;
localparam PRESS_FILTER = 1;
localparam WAIT = 2;
localparam RELEASE_FILTER = 3;
// 輸入 key_i 同步處理 消除亞穩(wěn)態(tài)
reg r_key_i,sync_d_0_key_i,sync_d_1_key_i;
wire nedge_key,pedge_key;
always@(posedge clk_i)
sync_d_0_key_i <= key_i;
always@(posedge clk_i)
sync_d_1_key_i <= sync_d_0_key_i;
always@(posedge clk_i)
r_key_i <= sync_d_1_key_i;
assign nedge_key = r_key_i & (~sync_d_1_key_i);
assign pedge_key = ~r_key_i & sync_d_1_key_i;
// 狀態(tài)機
always@(posedge clk_i or negedge reset_n_i)
if(!reset_n_i) begin
release_key_flag_o <= 0;
press_key_flag_o <= 0;
state <= IDLE;
key_state_o <= 1;
end
else begin
case(state)
IDLE :
begin
release_key_flag_o <= 0;
if(nedge_key)
state <= PRESS_FILTER;
else
state <= IDLE;
end
PRESS_FILTER :
if(time_20ms_reached) begin
state <= WAIT;
press_key_flag_o <= 1;
key_state_o <= 0;
end
else if(pedge_key)
state <= IDLE;
else
state <= PRESS_FILTER;
WAIT :
begin
press_key_flag_o <= 0;
if(pedge_key)
state <= RELEASE_FILTER;
else
state <= WAIT;
end
RELEASE_FILTER :
if(time_20ms_reached) begin
state <= IDLE;
release_key_flag_o <= 1;
key_state_o <= 1;
end
else if(nedge_key)
state <= WAIT;
else
state <= RELEASE_FILTER;
endcase
end
// time_20ms_reached
parameter MCNT = 1000_000;
reg [29:0] counter;
always@(posedge clk_i or negedge reset_n_i)
if(!reset_n_i)
counter <= 0;
else if(state == RELEASE_FILTER || state == PRESS_FILTER)
counter <= counter + 1;
else
counter <= 0;
assign time_20ms_reached = ( counter >= (MCNT - 1) );
endmodule
三、功能仿真?
這段代碼是一個Verilog測試平臺(testbench),名為
dds_ad9767_tb
,用于模擬和測試dds_ad9767
模塊的行為。測試平臺沒有物理硬件,它通過模擬輸入信號來驗證dds_ad9767
模塊的功能是否符合預期。
?文章來源:http://www.zghlxwxcb.cn/news/detail-841122.html
`timescale 1ns / 1ps
module dds_ad9767_tb();
reg u_reset_n_i,u_clk_i;
reg [1:0] u_mode_switch_button_a_i,u_mode_switch_button_b_i;
reg u_f_switch_button_a_i,u_p_switch_button_a_i,u_f_switch_button_b_i,u_p_switch_button_b_i;
wire [13:0] u_data_a_o;
wire [13:0] u_data_b_o;
dds_ad9767 U_dds_ad9767(
.reset_n_i(u_reset_n_i),
.clk_i(u_clk_i),
.mode_switch_button_a_i(u_mode_switch_button_a_i),
.f_switch_button_a_i(u_f_switch_button_a_i),
.p_switch_button_a_i(u_p_switch_button_a_i),
.mode_switch_button_b_i(u_mode_switch_button_b_i),
.f_switch_button_b_i(u_f_switch_button_b_i),
.p_switch_button_b_i(u_p_switch_button_b_i),
.data_a_o(u_data_a_o),
.data_b_o(u_data_b_o)
);
initial u_clk_i = 1;
always #10 u_clk_i = ~u_clk_i; // 50MHz
initial begin
u_reset_n_i = 0;
u_f_switch_button_a_i = 1;
u_f_switch_button_b_i = 1;
u_p_switch_button_a_i = 1;
u_p_switch_button_b_i = 1;
// 通道 波形類型 頻率倍數(shù) 相位
// a sine x1 0 \ b square x1 0
u_mode_switch_button_a_i = 0;
u_mode_switch_button_b_i = 1;
#201;
u_reset_n_i = 1;
#10_000_000;
// a square x1 0 \ b square x1 0
u_mode_switch_button_a_i = 1;
// a square x2 0 \ b square x1 0
u_f_switch_button_a_i = 0;
#20_000_000;
u_f_switch_button_a_i = 1;
#10_000_000;
// a square x2 90 \ b square x1 0
u_p_switch_button_a_i = 0;
#20_000_000;
u_p_switch_button_a_i = 1;
#10_000_000;
// a square x2 90 \ b square x1 90
u_p_switch_button_b_i = 0;
#20_000_000;
u_p_switch_button_b_i = 1;
#10_000_000;
// a square x2 90 \ b triangular x1 90
u_mode_switch_button_b_i = 2;
// a square x2 90 \ b triangular x2 90
u_f_switch_button_a_i = 0;
#20_000_000;
u_f_switch_button_a_i = 1;
#10_000_000;
$stop;
end
endmodule
文章來源地址http://www.zghlxwxcb.cn/news/detail-841122.html
四、綜合優(yōu)化
五、布局布線
六、時序仿真
七、板級調試?
到了這里,關于基于vivado+Verilog FPGA開發(fā) — 基于AD9767高速DAC的DDS信號發(fā)生器的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!