1. 程式人生 > >基於MATLAB生成ROM查詢表的DDS-中頻載波實現

基於MATLAB生成ROM查詢表的DDS-中頻載波實現

從END CHINA把自己以前寫過的一篇部落格搬到這裡來,以後就在這裡安家寫自己的部落格了。

dds通過matlab 生成的載波nco的實現:

verilog程式碼為:

頂層模組:主要是來組合下面兩個模組

module ddsshiyan1 (clk , dds_out) ; input clk ; output [9:0]  dds_out  ; wire [9:0] add_out ; add_dff u1 (.clk(clk) , .adder_dff_out(add_out)) ; sin u2 (.clock(clk) , .address(add_out) , .q(dds_out)) ; endmodule  ///////////////////////////////////////////////////////////////////////// add_dff模組:主要是產生頻率字和累加頻率字的結果  module add_dff (clk , adder_dff_out ) ; input clk ; output [9:0] adder_dff_out ; reg rst ; reg [4:0] count ; reg [9:0] reg1 ; reg [9:0] dff_out ; parameter  adder_dff_in = 10'd8 ; initial  begin rst = 1'd0 ; count = 5'd0 ; dff_out <= 10'd0 ; end always @ (posedge clk) if (!rst) begin count <= count + 1 ; reg1 <= adder_dff_in ; if (count == 5'd30) begin count <= 5'd0 ; rst <= 1'b1 ; end end else  begin dff_out <= dff_out + reg1 ; end assign adder_dff_out = dff_out ; endmodule ///////////////////////////////////////////////////////////////////// sin模組:主要是利用rom核來產生nco訊號 rom核自動生成程式為: `timescale 1 ps / 1 ps // synopsys translate_on module sin ( address, clock, q); input[9:0]  address; input  clock; output[9:0]  q; wire [9:0] sub_wire0; wire [9:0] q = sub_wire0[9:0]; altsyncram altsyncram_component ( .clock0 (clock), .address_a (address), .q_a (sub_wire0), .aclr0 (1'b0), .aclr1 (1'b0), .address_b (1'b1), .addressstall_a (1'b0), .addressstall_b (1'b0), .byteena_a (1'b1), .byteena_b (1'b1), .clock1 (1'b1), .clocken0 (1'b1), .clocken1 (1'b1), .clocken2 (1'b1), .clocken3 (1'b1), .data_a ({10{1'b1}}), .data_b (1'b1), .eccstatus (), .q_b (), .rden_a (1'b1), .rden_b (1'b1), .wren_a (1'b0), .wren_b (1'b0)); defparam altsyncram_component.address_aclr_a = "NONE", altsyncram_component.clock_enable_input_a = "BYPASS", altsyncram_component.clock_enable_output_a = "BYPASS", `ifdef NO_PLI altsyncram_component.init_file = "DDSrom33.rif" `else altsyncram_component.init_file = "DDSrom33.hex" `endif , altsyncram_component.intended_device_family = "Cyclone III", altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO", altsyncram_component.lpm_type = "altsyncram", altsyncram_component.numwords_a = 1024, altsyncram_component.operation_mode = "ROM", altsyncram_component.outdata_aclr_a = "NONE", altsyncram_component.outdata_reg_a = "UNREGISTERED", altsyncram_component.widthad_a = 10, altsyncram_component.width_a = 10, altsyncram_component.width_byteena_a = 1; endmodule ////////////////////////////////////////////////////////////////////////////// matlab生成rom程式: clc;clear; N = 10;                     %儲存單元地址線 depth=2^N;                 %儲存單元; widths=N;                    %資料寬度為8位; index = linspace(0,pi*2,depth);               sin_value = sin(index);                 sin_value = sin_value * (depth/2 -1);  %擴大正弦幅度值     sin_value = fix((sin_value)+0.5); plot(sin_value); number = [0:depth]; fid=fopen('DDSrom3.mif','w+'); fprintf(fid,'depth=%d;\n',depth); fprintf(fid,'width=%d;\n',widths); fprintf(fid,'address_radix=UNS;\n'); fprintf(fid,'data_radix = DEC;\n'); fprintf(fid,'Content Begin\n'); for i = 1 : depth       fprintf(fid, '%d\t:\t%d;\r\n', number(i),sin_value(i)); end fprintf(fid,'end;'); fclose(fid); 剛開始做出來自己寫的一點總結:

實驗一DDS總結:

一個在例化中(為了好識別埠使本來要直接連的兩個埠共同連一個有意義的net字元,記得要把net字元定義為wire型資料,否則很可能綜合出來的在rtl圖中看見他們不是相連的),一個在modelsim模擬中(modelsim對訊號的初始化要求很高,否則未定義的訊號直接預設為高阻態,而高阻態的反什麼的還是高阻態,最後訊號顯示為高阻態),寫出來總結一下。 還有個就是modelsim嚴格按照計算機補碼區別正負,十進位制的正負號是識別不了的,所以rom要用hex檔案儲存,用mif檔案的符號modelsim識別不了,所以千萬把matlab生成的mif檔案轉成hex檔案 

實驗總結: 主要出現問題有三: 1,在例化中為了例化訊號更好識別,自己加了新的埠,但未在程式的開頭宣告埠,但是quartus還不報錯,導致綜合出來的tll圖模組之間沒有連線起來, 最後是在前面加了wire語句給新定義的埠 2,剛開始學,不知道一開始就要在程式裡面就開始為呼叫modelsim就注意要初始化,因為初始化不完全,導致modelsim模擬不出結果,出錯 3,不知道modelsim不能識別mif檔案中儲存的負數,在觀察波形中,mif中定義也要注意符號數和無符號數,轉化為hex檔案補碼16進位制儲存後波形終於輸出正常。 待解決問題: matlab程式中:sin_value = sin_value * (depth/2 -1);  %擴大正弦幅度值 ,這個對出來的nco波形的精度有影響吧?還有儲存地址的深度的關係。