FPGA學習筆記——簡易的DDS信號發生器

目錄

一、任務

二、分析

三、ROM IP核配置

四、Visio圖

五、代碼

(1).v代碼

(2)仿真代碼

六、仿真

七、實驗現象



一、任務

用串口模塊,用上位機發送指令,FPGA接收,然后輸出對應的波形;其中指令用FE+波形+類型+頻率+相位+幅度+EE。

波形:選擇哪個波形

類型:頻率縮小還是放大


二、分析

首先要有串口模塊rx和tx,還要有四個單端口ROM模塊,分別存儲四種不同的波形,然后還要對指令處理的模塊,將處理后的指令給各個模塊使用。


三、ROM IP核配置


四、Visio圖

這里我就用RTL Viewer代替了。


五、代碼

(1).v代碼

top.v

module top (
input       wire            clk             ,
input       wire            rst_n           ,
input       wire            rx              ,
input       wire            key             ,
output      wire            led             ,
output      wire            tx              
);
//key
wire    key_out;
//tx
wire    [7:0]   data_tx;
wire            start  ;
wire            done_tx;
//rx
wire    [7:0]   data_rx;
wire            done_rx;
//ctrl_rom1
wire      [7:0]   data_wave1;
wire              done_wave1;//ctrl_rom2
wire      [7:0]   data_wave2;
wire              done_wave2;//ctrl_rom3
wire      [7:0]   data_wave3;
wire              done_wave3;//ctrl_rom4
wire      [7:0]   data_wave4;
wire              done_wave4;//cmd
wire     [7:0]   wave    ;
wire     [1:0]   mode    ;
wire     [7:0]   freq    ;
wire     [7:0]   phas    ;
wire     [7:0]   ampl    ;
wire             done_cmd;
//select_wave
wire     [7:0]   data_wave;
wire             done_wave;cmd cmd_u(
.    clk      (clk     )   ,
.    rst_n    (rst_n   )   ,
.    key_out  (  key_out     )   ,
.    data_rx  (data_rx )   ,//并行數據 ,其它模塊用
.    done_rx  (done_rx )   ,
.    led      (led     )   ,
.    wave     (wave    )   ,//波形
.    mode     (mode    )   ,//01:除法;10:乘法
.    freq     (freq    )   ,//頻率
.    phas     (phas    )   ,//相位
.    ampl     (ampl    )   ,//賦值
.    done_cmd (done_cmd)    //命令解析完成
);rx rx_u(
.   clk      (clk    )  ,
.   rst_n    (rst_n  )  ,
.   rx       (rx     )  ,//數據接收信號線
.   data_rx  (data_rx)  ,//并行數據 ,其它模塊用
.   done_rx  (done_rx)   //握手信號 ,接收結束信號 , 結束成功信號  
);tx tx_u(
.   clk     (clk      )  ,
.   rst_n   (rst_n    )  ,
.   data_tx (data_wave)  ,//并行輸入 --- 變化
.   start   (done_wave)  ,//數據有效信號
.   tx      (tx       )  ,  //串行輸出
.   done_tx (done_tx  )    //字節傳輸完成
);ctrl_rom1 ctrl_rom1_u(
.    clk        (clk       ) ,
.    rst_n      (rst_n     ) ,
.    wave       (wave      ) ,//波形
.    mode       (mode      ) ,//01:除法(  );10:乘法(  )
.    freq       (freq      ) ,//頻率
.    done_tx    (done_tx   ) ,
.    phas       (phas      ) ,//相位
.    ampl       (ampl      ) ,//幅值
.    done_cmd   (done_cmd  ) ,//命令解析完成
.    data_wave1 (data_wave1) ,
.    done_wave1 (done_wave1)  
);ctrl_rom2 ctrl_rom2_u(
.    clk        (clk       ) ,
.    rst_n      (rst_n     ) ,
.    wave       (wave      ) ,//波形
.    mode       (mode      ) ,//01:除法(  );10:乘法(  )
.    freq       (freq      ) ,//頻率
.    done_tx    (done_tx   ) ,
.    phas       (phas      ) ,//相位
.    ampl       (ampl      ) ,//幅值
.    done_cmd   (done_cmd  ) ,//命令解析完成
.    data_wave2 (data_wave2) ,
.    done_wave2 (done_wave2)  
);ctrl_rom3 ctrl_rom3_u(
.    clk        (clk       ) ,
.    rst_n      (rst_n     ) ,
.    wave       (wave      ) ,//波形
.    mode       (mode      ) ,//01:除法(  );10:乘法(  )
.    freq       (freq      ) ,//頻率
.    done_tx    (done_tx   ) ,
.    phas       (phas      ) ,//相位
.    ampl       (ampl      ) ,//幅值
.    done_cmd   (done_cmd  ) ,//命令解析完成
.    data_wave3 (data_wave3) ,
.    done_wave3 (done_wave3)  
);ctrl_rom4 ctrl_rom4_u(
.    clk        (clk       ) ,
.    rst_n      (rst_n     ) ,
.    wave       (wave      ) ,//波形
.    mode       (mode      ) ,//01:除法(  );10:乘法(  )
.    freq       (freq      ) ,//頻率
.    done_tx    (done_tx   ) ,
.    phas       (phas      ) ,//相位
.    ampl       (ampl      ) ,//幅值
.    done_cmd   (done_cmd  ) ,//命令解析完成
.    data_wave4 (data_wave4) ,
.    done_wave4 (done_wave4)  
);select_wave select_wave_u(
.      clk        (clk       ) ,
.      rst_n      (rst_n     ) ,
.      done_cmd   (done_cmd  ) ,//命令解析完成
.      wave       (wave      ) ,//波形
.      data_wave1 (data_wave1) ,
.      done_wave1 (done_wave1) ,
.      data_wave2 (data_wave2) ,
.      done_wave2 (done_wave2) ,
.      data_wave3 (data_wave3) ,
.      done_wave3 (done_wave3) ,
.      data_wave4 (data_wave4) ,
.      done_wave4 (done_wave4) ,
.      data_wave  (data_wave ) ,
.      done_wave  (done_wave ) 
);key key_u(
.     clk       (clk    ) ,
.     rst_n     (rst_n  ) ,
.     key       (key    ) ,
.     key_out   (key_out)
);endmodule

cmd.v

module cmd (
input       wire            clk         ,
input       wire            rst_n       ,
input       wire            key_out     ,
input       wire    [7:0]   data_rx     ,//并行數據 ,其它模塊用
input       wire            done_rx     ,
output      reg             led         ,
output      reg     [7:0]   wave        ,//波形
output      reg     [1:0]   mode        ,//01:除法;10:乘法
output      reg     [7:0]   freq        ,//頻率
output      reg     [7:0]   phas        ,//相位
output      reg     [7:0]   ampl        ,//幅值
output      reg             done_cmd     //命令解析完成
);
//指令處理localparam  IDLE  = 8'b0000_0001,START = 8'b0000_0010,WAVE  = 8'b0000_0100, MODE  = 8'b0000_1000, FREQ  = 8'b0001_0000,PHAS  = 8'b0010_0000,AMPL  = 8'b0100_0000,STOP  = 8'b1000_0000;
reg    [7:0]    cur_state ,next_state ;always @(posedge clk) beginif(!rst_n)cur_state <= IDLE;elsecur_state <= next_state;
endalways @(*) beginif(!rst_n)next_state = IDLE;elsecase (cur_state)IDLE :beginif(key_out)next_state = START;elsenext_state = cur_state;endSTART:begin   //包頭if( data_rx == 8'hFE && done_rx )next_state = WAVE;else if( data_rx != 8'hFE && done_rx )next_state = IDLE;elsenext_state = cur_state;endWAVE :begin  //波形if( done_rx )next_state = MODE;elsenext_state = cur_state;endMODE :begin  //if( done_rx )next_state = FREQ;elsenext_state = cur_state;endFREQ :begin  //if( done_rx )next_state = PHAS;elsenext_state = cur_state;endPHAS :begin  //if( done_rx )next_state = AMPL;elsenext_state = cur_state;endAMPL :begin  //if( done_rx )next_state = STOP;elsenext_state = cur_state;endSTOP : begin  //包尾if( done_rx && data_rx == 8'hEE)next_state = START;else if(done_rx && data_rx != 8'hEE)next_state = IDLE;elsenext_state = cur_state;enddefault: next_state = IDLE;endcase
endalways @(posedge clk) beginif(!rst_n) beginled      <= 0;wave     <= 0;mode     <= 0;freq     <= 0;phas     <= 0;ampl     <= 0;done_cmd <= 0;end elsecase (cur_state)IDLE :beginled      <= 1;wave     <= 0;mode     <= 0;freq     <= 0;phas     <= 0;ampl     <= 0;done_cmd <= 0;end START:beginled      <= 0;wave     <= wave    ;mode     <= mode    ;freq     <= freq    ;phas     <= phas    ;ampl     <= ampl    ;done_cmd <= 0;end WAVE :beginif(done_rx)wave <= data_rx; endMODE :beginif(done_rx)mode <= data_rx; endFREQ :beginif(done_rx)freq <= data_rx; endPHAS :beginif(done_rx)phas <= data_rx; endAMPL :beginif(done_rx)ampl <= data_rx; endSTOP : beginif(done_rx && data_rx == 8'hEE)done_cmd <= 1; elsedone_cmd <= 0; enddefault: beginled      <= 0;wave     <= 0;mode     <= 0;freq     <= 0;phas     <= 0;ampl     <= 0;done_cmd <= 0;end endcase
endendmodule

ctrl_rom1.v

module ctrl_rom1 (
input       wire             clk         ,
input       wire             rst_n       ,
input       wire     [7:0]   wave        ,//波形
input       wire     [1:0]   mode        ,//01:除法(  );10:乘法(  )
input       wire     [7:0]   freq        ,//頻率
input       wire             done_tx     ,
input       wire     [7:0]   phas        ,//相位
input       wire     [7:0]   ampl        ,//幅值
input       wire             done_cmd    ,//命令解析完成
output      reg      [7:0]   data_wave1  ,
output      reg              done_wave1   
);
//rom1
wire    [7:0]   q;
reg     [7:0]   address;
reg     [7:0]   q_reg ;//幅度計算寄存器//------------信號寄存---------//
reg    done_cmd_reg;
reg    [7:0]   wave_reg;
reg    [1:0]   mode_reg;
reg    [7:0]   freq_reg;
reg    [7:0]   phas_reg;
reg    [7:0]   ampl_reg;always @(posedge clk) beginif(!rst_n) beginwave_reg <= 0;mode_reg <= 0;freq_reg <= 0;phas_reg <= 0;ampl_reg <= 0;done_cmd_reg <= 0;endelse if ( done_cmd ) beginwave_reg <= wave;mode_reg <= mode;freq_reg <= freq;phas_reg <= phas;ampl_reg <= ampl;done_cmd_reg <=done_cmd;endelsedone_cmd_reg <= 0;
end//狀態機--------------------//
localparam  IDLE = 7'b0000001,   //等待key_outWAVE = 7'b0000010,   //波形判斷PHAS = 7'b0000100,   //相位:rom地址起始值FREQ = 7'b0001000,   //頻率:01:隔n個地址取一次數據,10:同一個地址數據取n次AMPL = 7'b0010000,   //計算幅值DATA = 7'b0100000,   //輸出波形 + doneSTOP = 7'b1000000;   //等待done_tx 構成循環
reg    [6:0]   cur_state , next_state;
reg    [3:0]    cnt;//
always @(posedge clk) beginif(!rst_n)cur_state <= IDLE;elsecur_state <= next_state;
endalways @(*) beginif(!rst_n) beginnext_state = IDLE;endelsecase (cur_state)IDLE: beginif(done_cmd_reg)next_state = WAVE;elsenext_state = cur_state;endWAVE: beginif(wave_reg == 8'h01)next_state = PHAS;else if (wave_reg != 8'h01)next_state = IDLE;elsenext_state = cur_state;endPHAS:beginif(done_cmd_reg)next_state = WAVE;elsenext_state = FREQ;endFREQ:beginif(done_cmd_reg)next_state = WAVE;else if( cnt == freq_reg - 1 && mode_reg == 2'b01 )next_state = AMPL;else if( mode_reg == 2'b10 )next_state = AMPL;elsenext_state = cur_state;endAMPL:beginif(done_cmd_reg)next_state = WAVE;elsenext_state = DATA;endDATA:beginif(done_cmd_reg)next_state = WAVE;elsenext_state = STOP;endSTOP: beginif(done_cmd_reg)next_state = WAVE;else if( done_tx )next_state = FREQ;elsenext_state = cur_state;enddefault: next_state = IDLE;endcase
endalways @(posedge clk) beginif(!rst_n) begindata_wave1 <= 0;done_wave1 <= 0;address    <= 0;cnt        <= 0;q_reg      <= 0;endelsecase (cur_state)IDLE:begindata_wave1 <= 0;done_wave1 <= 0;address    <= 0;cnt        <= 0;q_reg      <= 0;endWAVE:begindata_wave1 <= 0;done_wave1 <= 0;address    <= 0;cnt        <= 0;q_reg      <= 0;endPHAS:begin//rom起始地址address    <= phas_reg;endFREQ:begincase (mode) //頻率:01:隔n個地址取一次數據,10:同一個地址數據取n次2'b01:beginaddress <= address + 1;if( cnt == freq_reg - 1 )cnt <= 0;elsecnt <= cnt + 1;end2'b10: beginif( cnt == freq_reg - 1 ) begincnt <= 0;address <= address + 1;endelsecnt <= cnt + 1;enddefault: beginaddress    <= 0;cnt        <= 0;endendcaseendAMPL:beginq_reg      <= q/ampl_reg;endDATA:begindata_wave1 <= q_reg;done_wave1 <= 1; //短信號endSTOP: begindata_wave1 <= 0;done_wave1 <= 0;q_reg      <= 0;enddefault: begindata_wave1 <= 0;done_wave1 <= 0;address    <= 0;cnt        <= 0;q_reg      <= 0;endendcase
end//rom1
rom1	rom1_inst (.aclr     ( !rst_n     ),.address  ( address    ),.clock    ( clk        ),.q        ( q          ));endmodule

ctrl_rom2.v

module ctrl_rom2 (
input       wire             clk         ,
input       wire             rst_n       ,
input       wire     [7:0]   wave        ,//波形
input       wire     [1:0]   mode        ,//01:除法(  );10:乘法(  )
input       wire     [7:0]   freq        ,//頻率
input       wire             done_tx     ,
input       wire     [7:0]   phas        ,//相位
input       wire     [7:0]   ampl        ,//幅值
input       wire             done_cmd    ,//命令解析完成
output      reg      [7:0]   data_wave2  ,
output      reg              done_wave2   
);
//rom1
wire    [7:0]   q;
reg     [7:0]   address;
reg     [7:0]   q_reg ;//幅度計算寄存器//------------信號寄存---------//
reg    done_cmd_reg;
reg    [7:0]   wave_reg;
reg    [1:0]   mode_reg;
reg    [7:0]   freq_reg;
reg    [7:0]   phas_reg;
reg    [7:0]   ampl_reg;always @(posedge clk) beginif(!rst_n) beginwave_reg <= 0;mode_reg <= 0;freq_reg <= 0;phas_reg <= 0;ampl_reg <= 0;done_cmd_reg <= 0;endelse if ( done_cmd ) beginwave_reg <= wave;mode_reg <= mode;freq_reg <= freq;phas_reg <= phas;ampl_reg <= ampl;done_cmd_reg <=done_cmd;endelsedone_cmd_reg <= 0;
end//狀態機--------------------//
localparam  IDLE = 7'b0000001,   //等待key_outWAVE = 7'b0000010,   //波形判斷PHAS = 7'b0000100,   //相位:rom地址起始值FREQ = 7'b0001000,   //頻率:01:隔n個地址取一次數據,10:同一個地址數據取n次AMPL = 7'b0010000,   //計算幅值DATA = 7'b0100000,   //輸出波形 + doneSTOP = 7'b1000000;   //等待done_tx 構成循環
reg    [6:0]   cur_state , next_state;
reg    [3:0]    cnt;//
always @(posedge clk) beginif(!rst_n)cur_state <= IDLE;elsecur_state <= next_state;
endalways @(*) beginif(!rst_n) beginnext_state = IDLE;endelsecase (cur_state)IDLE: beginif(done_cmd_reg)next_state = WAVE;elsenext_state = cur_state;endWAVE: beginif(wave_reg == 8'h02)next_state = PHAS;else if (wave_reg != 8'h02)next_state = IDLE;elsenext_state = cur_state;endPHAS:beginif(done_cmd_reg)next_state = WAVE;elsenext_state = FREQ;endFREQ:beginif(done_cmd_reg)next_state = WAVE;else if( cnt == freq_reg - 1 && mode_reg == 2'b01 )next_state = AMPL;else if( mode_reg == 2'b10 )next_state = AMPL;elsenext_state = cur_state;endAMPL:beginif(done_cmd_reg)next_state = WAVE;elsenext_state = DATA;endDATA:beginif(done_cmd_reg)next_state = WAVE;elsenext_state = STOP;endSTOP: beginif(done_cmd_reg)next_state = WAVE;else if( done_tx )next_state = FREQ;elsenext_state = cur_state;enddefault: next_state = IDLE;endcase
endalways @(posedge clk) beginif(!rst_n) begindata_wave2 <= 0;done_wave2 <= 0;address    <= 0;cnt        <= 0;q_reg      <= 0;endelsecase (cur_state)IDLE:begindata_wave2 <= 0;done_wave2 <= 0;address    <= 0;cnt        <= 0;q_reg      <= 0;endWAVE:begindata_wave2 <= 0;done_wave2 <= 0;address    <= 0;cnt        <= 0;q_reg      <= 0;endPHAS:begin//rom起始地址address    <= phas_reg;endFREQ:begincase (mode) //頻率:01:隔n個地址取一次數據,10:同一個地址數據取n次2'b01:beginaddress <= address + 1;if( cnt == freq_reg - 1 )cnt <= 0;elsecnt <= cnt + 1;end2'b10: beginif( cnt == freq_reg - 1 ) begincnt <= 0;address <= address + 1;endelsecnt <= cnt + 1;enddefault: beginaddress    <= 0;cnt        <= 0;endendcaseendAMPL:beginq_reg      <= q/ampl_reg;endDATA:begindata_wave2 <= q_reg;done_wave2 <= 1; //短信號endSTOP: begindata_wave2 <= 0;done_wave2 <= 0;q_reg      <= 0;enddefault: begindata_wave2 <= 0;done_wave2 <= 0;address    <= 0;cnt        <= 0;q_reg      <= 0;endendcase
end//rom2
rom2	rom2_inst (.aclr     ( !rst_n     ),.address  ( address    ),.clock    ( clk        ),.q        ( q          ));endmodule

ctrl_rom3.v

module ctrl_rom3 (
input       wire             clk         ,
input       wire             rst_n       ,
input       wire     [7:0]   wave        ,//波形
input       wire     [1:0]   mode        ,//01:除法(  );10:乘法(  )
input       wire     [7:0]   freq        ,//頻率
input       wire             done_tx     ,
input       wire     [7:0]   phas        ,//相位
input       wire     [7:0]   ampl        ,//幅值
input       wire             done_cmd    ,//命令解析完成
output      reg      [7:0]   data_wave3  ,
output      reg              done_wave3   
);
//rom1
wire    [7:0]   q;
reg     [7:0]   address;
reg     [7:0]   q_reg ;//幅度計算寄存器//------------信號寄存---------//
reg    done_cmd_reg;
reg    [7:0]   wave_reg;
reg    [1:0]   mode_reg;
reg    [7:0]   freq_reg;
reg    [7:0]   phas_reg;
reg    [7:0]   ampl_reg;always @(posedge clk) beginif(!rst_n) beginwave_reg <= 0;mode_reg <= 0;freq_reg <= 0;phas_reg <= 0;ampl_reg <= 0;done_cmd_reg <= 0;endelse if ( done_cmd ) beginwave_reg <= wave;mode_reg <= mode;freq_reg <= freq;phas_reg <= phas;ampl_reg <= ampl;done_cmd_reg <=done_cmd;endelsedone_cmd_reg <= 0;
end//狀態機--------------------//
localparam  IDLE = 7'b0000001,   //等待key_outWAVE = 7'b0000010,   //波形判斷PHAS = 7'b0000100,   //相位:rom地址起始值FREQ = 7'b0001000,   //頻率:01:隔n個地址取一次數據,10:同一個地址數據取n次AMPL = 7'b0010000,   //計算幅值DATA = 7'b0100000,   //輸出波形 + doneSTOP = 7'b1000000;   //等待done_tx 構成循環
reg    [6:0]   cur_state , next_state;
reg    [3:0]    cnt;//
always @(posedge clk) beginif(!rst_n)cur_state <= IDLE;elsecur_state <= next_state;
endalways @(*) beginif(!rst_n) beginnext_state = IDLE;endelsecase (cur_state)IDLE: beginif(done_cmd_reg)next_state = WAVE;elsenext_state = cur_state;endWAVE: beginif(wave_reg == 8'h03)next_state = PHAS;else if (wave_reg != 8'h03)next_state = IDLE;elsenext_state = cur_state;endPHAS:beginif(done_cmd_reg)next_state = WAVE;elsenext_state = FREQ;endFREQ:beginif(done_cmd_reg)next_state = WAVE;else if( cnt == freq_reg - 1 && mode_reg == 2'b01 )next_state = AMPL;else if( mode_reg == 2'b10 )next_state = AMPL;elsenext_state = cur_state;endAMPL:beginif(done_cmd_reg)next_state = WAVE;elsenext_state = DATA;endDATA:beginif(done_cmd_reg)next_state = WAVE;elsenext_state = STOP;endSTOP: beginif(done_cmd_reg)next_state = WAVE;else if( done_tx )next_state = FREQ;elsenext_state = cur_state;enddefault: next_state = IDLE;endcase
endalways @(posedge clk) beginif(!rst_n) begindata_wave3 <= 0;done_wave3 <= 0;address    <= 0;cnt        <= 0;q_reg      <= 0;endelsecase (cur_state)IDLE:begindata_wave3 <= 0;done_wave3 <= 0;address    <= 0;cnt        <= 0;q_reg      <= 0;endWAVE:begindata_wave3 <= 0;done_wave3 <= 0;address    <= 0;cnt        <= 0;q_reg      <= 0;endPHAS:begin//rom起始地址address    <= phas_reg;endFREQ:begincase (mode) //頻率:01:隔n個地址取一次數據,10:同一個地址數據取n次2'b01:beginaddress <= address + 1;if( cnt == freq_reg - 1 )cnt <= 0;elsecnt <= cnt + 1;end2'b10: beginif( cnt == freq_reg - 1 ) begincnt <= 0;address <= address + 1;endelsecnt <= cnt + 1;enddefault: beginaddress    <= 0;cnt        <= 0;endendcaseendAMPL:beginq_reg      <= q/ampl_reg;endDATA:begindata_wave3 <= q_reg;done_wave3 <= 1; //短信號endSTOP: begindata_wave3 <= 0;done_wave3 <= 0;q_reg      <= 0;enddefault: begindata_wave3 <= 0;done_wave3 <= 0;address    <= 0;cnt        <= 0;q_reg      <= 0;endendcase
end//rom3
rom3	rom3_inst (.aclr     ( !rst_n     ),.address  ( address    ),.clock    ( clk        ),.q        ( q          ));endmodule

ctrl_rom4.v

module ctrl_rom4 (
input       wire             clk         ,
input       wire             rst_n       ,
input       wire     [7:0]   wave        ,//波形
input       wire     [1:0]   mode        ,//01:除法(  );10:乘法(  )
input       wire     [7:0]   freq        ,//頻率
input       wire             done_tx     ,
input       wire     [7:0]   phas        ,//相位
input       wire     [7:0]   ampl        ,//幅值
input       wire             done_cmd    ,//命令解析完成
output      reg      [7:0]   data_wave4  ,
output      reg              done_wave4   
);
//rom1
wire    [7:0]   q;
reg     [7:0]   address;
reg     [7:0]   q_reg ;//幅度計算寄存器//------------信號寄存---------//
reg    done_cmd_reg;
reg    [7:0]   wave_reg;
reg    [1:0]   mode_reg;
reg    [7:0]   freq_reg;
reg    [7:0]   phas_reg;
reg    [7:0]   ampl_reg;always @(posedge clk) beginif(!rst_n) beginwave_reg <= 0;mode_reg <= 0;freq_reg <= 0;phas_reg <= 0;ampl_reg <= 0;done_cmd_reg <= 0;endelse if ( done_cmd ) beginwave_reg <= wave;mode_reg <= mode;freq_reg <= freq;phas_reg <= phas;ampl_reg <= ampl;done_cmd_reg <=done_cmd;endelsedone_cmd_reg <= 0;
end//狀態機--------------------//
localparam  IDLE = 7'b0000001,   //等待key_outWAVE = 7'b0000010,   //波形判斷PHAS = 7'b0000100,   //相位:rom地址起始值FREQ = 7'b0001000,   //頻率:01:隔n個地址取一次數據,10:同一個地址數據取n次AMPL = 7'b0010000,   //計算幅值DATA = 7'b0100000,   //輸出波形 + doneSTOP = 7'b1000000;   //等待done_tx 構成循環
reg    [6:0]   cur_state , next_state;
reg    [3:0]    cnt;//
always @(posedge clk) beginif(!rst_n)cur_state <= IDLE;elsecur_state <= next_state;
endalways @(*) beginif(!rst_n) beginnext_state = IDLE;endelsecase (cur_state)IDLE: beginif(done_cmd_reg)next_state = WAVE;elsenext_state = cur_state;endWAVE: beginif(wave_reg == 8'h04)next_state = PHAS;else if (wave_reg != 8'h04)next_state = IDLE;elsenext_state = cur_state;endPHAS:beginif(done_cmd_reg)next_state = WAVE;elsenext_state = FREQ;endFREQ:beginif(done_cmd_reg)next_state = WAVE;else if( cnt == freq_reg - 1 && mode_reg == 2'b01 )next_state = AMPL;else if( mode_reg == 2'b10 )next_state = AMPL;elsenext_state = cur_state;endAMPL:beginif(done_cmd_reg)next_state = WAVE;elsenext_state = DATA;endDATA:beginif(done_cmd_reg)next_state = WAVE;elsenext_state = STOP;endSTOP: beginif(done_cmd_reg)next_state = WAVE;else if( done_tx )next_state = FREQ;elsenext_state = cur_state;enddefault: next_state = IDLE;endcase
endalways @(posedge clk) beginif(!rst_n) begindata_wave4 <= 0;done_wave4 <= 0;address    <= 0;cnt        <= 0;q_reg      <= 0;endelsecase (cur_state)IDLE:begindata_wave4 <= 0;done_wave4 <= 0;address    <= 0;cnt        <= 0;q_reg      <= 0;endWAVE:begindata_wave4 <= 0;done_wave4 <= 0;address    <= 0;cnt        <= 0;q_reg      <= 0;endPHAS:begin//rom起始地址address    <= phas_reg;endFREQ:begincase (mode) //頻率:01:隔n個地址取一次數據,10:同一個地址數據取n次2'b01:beginaddress <= address + 1;if( cnt == freq_reg - 1 )cnt <= 0;elsecnt <= cnt + 1;end2'b10: beginif( cnt == freq_reg - 1 ) begincnt <= 0;address <= address + 1;endelsecnt <= cnt + 1;enddefault: beginaddress    <= 0;cnt        <= 0;endendcaseendAMPL:beginq_reg      <= q/ampl_reg;endDATA:begindata_wave4 <= q_reg;done_wave4 <= 1; //短信號endSTOP: begindata_wave4 <= 0;done_wave4 <= 0;q_reg      <= 0;enddefault: begindata_wave4 <= 0;done_wave4 <= 0;address    <= 0;cnt        <= 0;q_reg      <= 0;endendcase
end//rom4
rom4	rom4_inst (.aclr     ( !rst_n     ),.address  ( address    ),.clock    ( clk        ),.q        ( q          ));endmodule

select_wave.v

module select_wave (
input       wire             clk         ,
input       wire             rst_n       ,
input       wire             done_cmd    ,//命令解析完成
input       wire     [7:0]   wave        ,//波形
input       wire     [7:0]   data_wave1  ,
input       wire             done_wave1  ,
input       wire     [7:0]   data_wave2  ,
input       wire             done_wave2  ,
input       wire     [7:0]   data_wave3  ,
input       wire             done_wave3  ,
input       wire     [7:0]   data_wave4  ,
input       wire             done_wave4  ,
output      reg      [7:0]   data_wave   ,
output      reg              done_wave   
);
reg [7:0]  wave_reg;always @(posedge clk) beginif(!rst_n)wave_reg <= 0;elsewave_reg <= wave;
endalways @(*) beginif(!rst_n) begindata_wave = 0;done_wave = 0;endelsecase (wave_reg )8'h01:beginif( done_wave1 ) begindata_wave = data_wave1;done_wave = done_wave1;endelsebegindata_wave = 0;done_wave = 0;endend8'h02: beginif( done_wave2 ) begindata_wave = data_wave2;done_wave = done_wave2;endelse begindata_wave = 0;done_wave = 0;endend8'h03: beginif( done_wave3 ) begindata_wave = data_wave3;done_wave = done_wave3;endelse begindata_wave = 0;done_wave = 0;endend8'h04: beginif( done_wave4 ) begindata_wave = data_wave4;done_wave = done_wave4;endelse begindata_wave = 0;done_wave = 0;endenddefault: begindata_wave = 0;done_wave = 0;endendcase
endendmodule

串口發送模塊和按鍵模塊可以去我的其它學習筆記找,這里就不發了。

(2)仿真代碼

tb文件

`timescale 1ns/1ns
module tb();
parameter   sysclk = 50_000_000  ,//系統時鐘下:1sbps    = 115200      , //波特率delay  = sysclk / bps * 20;//1bit工作周期reg             clk    ;
reg             rst_n  ;
reg             rx     ;
reg             key    ;
wire    [7:0]   data_rx;
wire            done_rx;
wire            key_out;always #10 clk = ~clk;initial beginclk = 0;rst_n = 0;rx = 1;key   = 1;#100rst_n = 1;key   = 0;#200key   = 1;send_data(8'hFE);#200send_data(8'h01);#200send_data(8'h01);#200send_data(8'h01);#200send_data(8'h01);#200send_data(8'h01);#200send_data(8'hee);
endtask send_data ;input [7:0] data ;
beginrx = 1;#100 //空閑rx = 0; #delay //起始位rx = data[0]; #delay //數據位 rx = data[1]; #delay //數據位rx = data[2]; #delay //數據位rx = data[3]; #delay //數據位rx = data[4]; #delay //數據位rx = data[5]; #delay //數據位rx = data[6]; #delay //數據位rx = data[7]; #delay //數據位rx = 1; #delay; //停止位
endendtaskrx rx_u(
.   clk      (clk    )   ,
.   rst_n    (rst_n  )   ,
.   rx       (rx     )   ,//數據接收信號線
.   data_rx  (data_rx)   ,//并行數據 ,其它模塊用
.   done_rx  (done_rx)    //握手信號 ,接收結束信號 , 結束成功信號  
);top top_u(
.      clk    (clk  )         ,
.      rst_n  (rst_n)         ,
.      rx     (rx   )         ,
.      key    (key  )         ,
.      led    (led  )          
);key key_u(
.     clk       (clk    ) ,
.     rst_n     (rst_n  ) ,
.     key       (key    ) ,
.     key_out   (key_out)
);endmodule

六、仿真

這里就列舉波形一的,其它的,可以自己嘗試嘗試。


七、實驗現象

波形一

波形二

波形三

波形四


以上就是簡易DDS信號發生器。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/94910.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/94910.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/94910.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

在NVIDIA Orin上用TensorRT對YOLO12進行多路加速并行推理時內存泄漏 (中)

接上篇 在NVIDIA Orin上用TensorRT對YOLO12進行多路加速并行推理時內存泄漏&#xff08;上&#xff09; 通過上篇的分析&#xff0c;發現問題在采集數據到傳入GPU之前的階段。但隨著新一輪長時間測試發現&#xff0c;問題依然存在。 如上圖&#xff0c;在運行20多分鐘內存開始…

計數組合學7.17(Murnaghan–Nakayama 規則 )

7.17 Murnaghan–Nakayama 規則 我們已經成功地用基 mλm_\lambdamλ?、hλh_\lambdahλ? 和 eλe_\lambdaeλ? 表示了 Schur 函數 sλs_\lambdasλ?。本節我們將考慮冪和對稱函數 pλp_\lambdapλ?。一個斜分劃 λ/μ\lambda / \muλ/μ 是連通的&#xff0c;如果其分拆圖…

使用 jlink 構建輕巧的自定義JRE

從 JDK 9 開始&#xff0c;Oracle JDK 和 OpenJDK 不再默認包含獨立的 JRE 目錄&#xff0c;而是提供了 jlink 工具&#xff08;Java 鏈接器&#xff09;&#xff0c;允許你根據需求自定義生成最小化的 JRE&#xff08;包含必要的模塊&#xff09;。以下是使用 jlink 生成 JRE …

[IOMMU]面向芯片/SoC驗證工程的IOMMU全景速覽

面向芯片/SoC驗證工程的IOMMU全景速覽 摘要:面向芯片/SoC 驗證工程的 IOMMU 全景速覽:包含基礎概念、主流架構要點(ARM SMMU、Intel VT?d、RISC?V IOMMU),Linux 軟件棧關系,SoC 上的驗證方法(功能、錯誤、性能、系統化流程和覆蓋),以及一個可用的“通用 IOMM…

Jenkins全鏈路教程——Jenkins用戶權限矩陣配置

在企業級CI/CD場景中&#xff0c;“權限混亂”往往比“構建失敗”更致命——測試員誤刪生產流水線、實習生修改關鍵插件配置、多團隊共用賬號導致責任無法追溯……這些問題&#xff0c;99%都能用權限矩陣徹底解決&#xff01;今天&#xff0c;我們不僅會拆解權限矩陣的底層邏輯…

庫函數蜂鳴器的使用(STC8)

使用庫函數控制蜂鳴器&#xff08;STC8&#xff09; 在STC8系列單片機中&#xff0c;可以通過庫函數或直接操作寄存器來控制蜂鳴器。以下是基于STC8庫函數的常用方法&#xff1a; GPIO板蜂鳴器 #include "GPIO.h" #include "Delay.h"void GPIO_config()…

redis8.0.3部署于mac

macOS11因版本過低&#xff0c;安裝redis時&#xff0c;Homebrew和源碼編譯兩種方式都無法成功。將操作系統升級至macOS15再安裝。Redis&#xff08;Remote Dictionary Server&#xff09;是一個開源的內存數據庫&#xff0c;遵守 BSD 協議&#xff0c;它提供了一個高性能的鍵值…

【和春筍一起學C++】(三十三)名稱空間的其他特性

目錄 嵌套式名稱空間 拓展——未命名的名稱空間 嵌套式名稱空間 示例代碼1&#xff1a; namespace electronicEquipment {namespace computer{double price 4999.0;string modelNumber;string name;}namespace ElectronicWatch{double price 99.0;string modelNumber;stri…

異步電動機負載運行特性全解析

異步電動機負載運行特性詳解 ——從空載到負載的完整分析一、為什么需要再談“負載運行” 在上一篇《感應電動機空載特性深度剖析》中&#xff0c;我們已經看到&#xff1a;空載時&#xff0c;若定子加額定電壓&#xff0c;轉子轉速 $n \approx n_s$&#xff08;同步轉速&#…

使用 Ansys Discovery 進行動態設計和分析

Ansys Discovery 是一款多功能工具&#xff0c;為創建模型、探索仿真設計和分析解決方案提供了一個單一的交互式工作區。它允許用戶使用直接建模技術創建和修改幾何結構&#xff0c;定義仿真并與結果實時交互。Discovery 支持結構、流體流動、熱和電磁設計&#xff0c;提供直觀…

力扣熱題100-----118.楊輝三角

案例 給定一個非負整數 numRows&#xff0c;生成「楊輝三角」的前 numRows 行。 在「楊輝三角」中&#xff0c;每個數是它左上方和右上方的數的和。 示例 1: 輸入: numRows 5 輸出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]] 示例 2: 輸入: numRows 1 輸出: [[1]] 提示: 1 …

NTP /Chrony 網絡時間協議

一、NTP&#xff08;network time protocol&#xff09;網絡時間協議&#xff1a;實現時間同步&#xff0c;讓設備時間與國際標準時間保持一致設備日志、服務日志需要記錄時間分布式系統&#xff08;分布式數據庫、分布式緩存、分布式儲存、消息隊列&#xff09;時間戳&#xf…

VSCode 刷 LeetCode 算法題配置教程

LeetCode 在線刷題地址&#xff1a;https://leetcode-cn.com/ 一、安裝 Node.js 環境 LeetCode 插件依賴 node.js 運行環境&#xff0c;因此必須先安裝&#xff1a; 前往官網下載安裝&#xff1a;https://nodejs.cn/download/下載好的壓縮包解壓&#xff0c;可以看到當前文件…

非常簡單!從零學習如何免費制作一個lofi視頻

想必大家在網上會看到如下類似的音樂頻道&#xff0c;這類頻道都只是上傳簡單的Lo-Fi音樂帶著循環播放的背景就可以賺錢。 那么上面的效果如何實現的呢&#xff1f;今天做一個可以免費制作lo-Fi音樂的教程。 Lo-Fi音樂&#xff1a; Lo-Fi音樂是一種以低保真度和模擬音色為特點…

基于 RAUC 的 Jetson OTA 升級全攻略

&#x1f4d6; 推薦閱讀&#xff1a;《Yocto項目實戰教程:高效定制嵌入式Linux系統》 &#x1f3a5; 更多學習視頻請關注 B 站&#xff1a;嵌入式Jerry 基于 RAUC 的 Jetson OTA 升級全攻略 0. 引子&#xff1a;常見問題 在 Jetson 平臺做 OTA 升級時&#xff0c;你可能會問&…

MySQL 主備(Master-Slave)復制 的搭建

一、主備架構簡介 Master&#xff08;主庫&#xff09;&#xff1a;負責處理所有寫操作&#xff08;INSERT/UPDATE/DELETE&#xff09;&#xff0c;并記錄二進制日志&#xff08;binlog&#xff09;。Slave&#xff08;備庫&#xff09;&#xff1a;從主庫拉取 binlog&#xff…

【三個數絕對值排序】2022-10-10

緣由絕對值比較&#xff0c;總是跑不過怎么辦-編程語言-CSDN問答 template <class 形參> inline void 算交換(形參& a, 形參& b){ 形參 ab a - b; a - ab; b ab; } template <class 形參> void 三個升序(形參& a, 形參& b, 形參& c) {if (a…

【LoRA模型訓練】Stable Diffusion LoRA 模型秋葉訓練器詳細教程

一、工具簡介與安裝指南 1.1 秋葉 LoRA 訓練器概述 秋葉 LoRA 訓練器&#xff08;基于 Akegarasu/lora-scripts 項目&#xff09;是針對 Stable Diffusion 模型的輕量化微調工具&#xff0c;通過低秩適應&#xff08;LoRA&#xff09;技術實現高效參數微調。其核心優勢在于&a…

C++2024 年一級

1 單選題 (每題 2 分,共 30 分) 12 ? 題號 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 答案 C C D B B D B C C C D C D B D 第 1 題 2024年10?8? &#xff0c;諾貝爾物理學獎“意外地”頒給了兩位計算機科學家約翰霍普菲爾德&#xff08;John J. Hopfield&#xff09;和杰 弗??…

react-window

下面&#xff0c;我們來系統的梳理關于 React 虛擬化列表&#xff1a;react-window 的基本知識點&#xff1a;一、虛擬化列表核心概念 1.1 什么是虛擬化列表&#xff1f; 虛擬化列表&#xff08;也稱為窗口化&#xff09;是一種只渲染當前可見區域列表項的技術&#xff0c;而不…