MAXUPLD入門 その4 DDS  & D/A(Pulse Density Modulation)


D/A(using Pulse Density Modulation)変換後に、Low Pass Filterを通して確認しました、できた!

 
100KHz出力


10KHz出力:高調波があるが、ノイズフロアは80dBC以上(一次LPFはfc=140KHz位なので、LPF無しと同じ)

後ほど、sin波のromデータの上下限値を90%に抑えると、更にきれいになりました。




f=9,999.98Hz(無調整)。 カウンターのクロックはGPSに同期させたクロック



carry_out が PDMによるD/A出力 ( simulated  using VeritakWin CQ )


ModelSim-Alteraでも、確認しました。

 1.DDSも、やってみましょう

    上図は、DDSの出力 data を、PulseDensityModulationにより、D/A変換したものです、 多分......確信は、ない。

    後は、Low Pass Filterを通す実験だけなんですが、まだ、できてませんねん。  <- できました!

2.sin波データを格納する場所は?

    実は、simulationの段階ですが、romに採っています。

        

    実験的に、10bitのデータを、10bitのアドレスで格納していますから、

    データだけでも、

     10bit x 1024 =10240bit

    もの、bitを格納している事になります、ほんまかいな!

    
       717LEで、格納できています。

    こんなん、webでも、書籍でも、何処にも記述されていません!

    
romに格納できれば、DDSの出力周波数も、グンと、上げる事ができるのでは.....

   で、

   Quartusの RTLviewerで、見てみると

    
    正しく、compileされていますね。

    まだ、simulationの段階ですが、私は、「できる」と、信じています。

    私は、全くのド素人ですから、書籍の通りに従って、素直に、自分のアイデアを、試しているだけなのです。

    奇を衒うつもりは、全くありませんが、「何で、こうなるの!」

3.DDSの構成は

   上記の、SinRom(9bit)と、DDS、D/A の3つの部分で出来ています。

   それと、テストベンチの4つです。

module mSinRom(adr,dat);
 input [8:0]  adr;
 output [8:0] dat;
 reg [8:0]  romdat;
 
 assign dat=romdat;
 
 always @(adr) begin
  case(adr)
9'h000:romdat=9'h100;
9'h001:romdat=9'h103;
9'h002:romdat=9'h106;
9'h003:romdat=9'h109;
9'h004:romdat=9'h10C;
9'h005:romdat=9'h10F;
9'h006:romdat=9'h112;
9'h007:romdat=9'h115;
9'h008:romdat=9'h119;
9'h009:romdat=9'h11C;
9'h00A:romdat=9'h11F;
9'h00B:romdat=9'h122;
........
9'h1FA:romdat=9'h0ED;
9'h1FB:romdat=9'h0F0;
9'h1FC:romdat=9'h0F3;
9'h1FD:romdat=9'h0F6;
9'h1FE:romdat=9'h0F9;
9'h1FF:romdat=9'h0FC;

  default romdat=9'h100;
 
  endcase
 end
endmodule
----------------------------------------------
module myDDS1(clk,dat,inc);
 input  clk;
 output [8:0] dat;  //9bit data
 reg [8:0] addr;    // 9bit address

 input [3:0] inc;   //increment
 mSinRom  mSinRom1(addr,dat);
 
 initial begin
  addr  <=0;
 end

 always @(posedge clk) begin
  addr <=addr+inc; 
 end
 
endmodule
----------------------------------------------
module acum(VDA,clk,cy_out);

 input [8:0] VDA ;
 input  clk;
 output   cy_out;
 
 reg [8:0]   R;
 reg    cy_out;
 
 
 initial begin
     R <=0;
 end

 always @(posedge clk) begin
  { cy_out, R } <= VDA +R;
 end
  
endmodule
----------------------------------------------
module test_myDDS1();
 reg clock;
 wire  [8:0] data;
 reg    [8:0]    t_addr;
 wire carry_out;
 reg [3:0] increment;

 myDDS1 myDDS1(clock,data,increment);
 acum    acum(data,clock,carry_out);


 always #10 begin
  clock <=~clock;
 
 end

 initial begin
  $monitor($time,"clock=%b data=%b",clock,data);
 end

 initial begin
  clock <=0;
  t_addr  <=0;
  increment <=1;
 #8000
  increment <=3;
 #5000
  increment <=7;
 #4000
  increment <=14;

 #4000
  $finish;
 end
endmodule

    それぞれのmoduleを、積み重ねていけば、よいみたいです。

    その他、説明出来なかった画像を列挙します。 (手抜きで、ごめんなさい)

50MHz Clockの分周






――――――――――――――――――――――――――――――――――――――――――――――――
addressの9bit & 10bit



    次回は、DDSを考えている時、疑問に思った事を、書いてみたいと、思います。

    全然、間違ってるかも..... (^_^;;

H.21.2.13