2010年12月29日水曜日

DSD Phase Modulation Mode 受信回路

 DSD Phase Modulation ModeのデータをBCKを使用せずに、DSDdataのエッジを利用して受信しSignalTapIIにキャプチャする回路の回路図とSystemVerilogのコードです。片チャネル分。
 この回路をベースにI2S、ADAT、S/PDIF受信回路にDSD受信機能として統合する予定。片チャネル分のため、2回路化、L/Rの多重処理が追加で必要になります。現在サンプリングクロックとして98.3040MHzを使用していますが、90.3168MHzに変更します。

     DSD Phase Modulation Mode 受信回路構成


DSD Phase Modulation Mode 受信回路 SystemVerilogコード
   

`timescale 1ns/1ns
module DSD_capture(

  input  wire          m_clk,                 //sampling clock 98MHz
  input  wire          resetN,        
 
  input  logic         dsd_in,                //DSD_L or DSD_R input
 
  output logic         dsd_out,               //DSD monitor out
  output logic         dsd_alt_out,           //DSD monitor out alt
 
  output logic         cap_clk,               //SignalTapII capture sampling clock
  output logic         dsd_cmp,               //DSD and DSD alt inv compare
  output logic         dsd_5apat              //5A5A5A5A pattern match
);

 logic [3:0]  sdata_input_shift;
 logic     edge_detect;

 logic [5:0]   dsd_inc_word_time = 6'h0;
 logic     fw_window_clr;
 logic     fw_window;
 logic     hw_window;
 logic     fw_edge_det_flg;
 logic     fw_edge_det;
 logic     fw_edge_nodet;
 logic     hw_edge_det_flg;
 logic     hw_edge_nodet;

 logic    bit_clk;
 logic    bit_clk_mask;
 logic    alt_bit_clk;
 logic    alt_bit_clk_mask;

 logic    cmp_ini_flag;

 logic [31:0] dsd_data;
 logic [31:0] dsd_data_alt;

 logic [4:0]    capture_counter;

 
 enum {synclos=0,presync1 =1,presync2 =2,presync3 =3,presync4 =4, sync =5, fwprtect =6 } State, NextState;
 

//// dsd input section ////  
//shift_adat_input :
   always_ff @(posedge m_clk)
      sdata_input_shift <= {sdata_input_shift[2:0] , dsd_in};

// detect_adat_sync :
   always_ff @(posedge m_clk)begin
      if ((sdata_input_shift[2:1]==2'b01) || (sdata_input_shift[2:1]==2'b10))
         edge_detect <= 1'b1;
      else
         edge_detect <= 1'b0;
   end

   always_ff @(posedge m_clk)begin
      if (edge_detect==1'b1 && State == synclos)   dsd_inc_word_time <= '0;
      else if(edge_detect==1'b1 && fw_window == 1) dsd_inc_word_time <= '0;
      else                                         dsd_inc_word_time <= dsd_inc_word_time + 1;
   end

// edge detect window
   assign fw_window_clr = (dsd_inc_word_time==6'd02)  || (dsd_inc_word_time==6'd37) ;
   always_ff @(posedge m_clk)begin
      if (dsd_inc_word_time==6'd32)      fw_window <= '1;
      else if(fw_window_clr)             fw_window <= '0;
   end

   always_ff @(posedge m_clk)begin
      if (dsd_inc_word_time==6'd15)      hw_window <= '1;
      else if(dsd_inc_word_time==6'd20)  hw_window <= '0;
   end

// fw_edge_det & hw_edge_det
   always_ff @(posedge m_clk)begin
      if (fw_window && edge_detect)      fw_edge_det_flg <= '1;
      else if(fw_window_clr)             fw_edge_det_flg <= '0;
   end

   always_ff @(posedge m_clk)begin
      if (fw_edge_det_flg && fw_window_clr)   fw_edge_det <= '1;
      else                                    fw_edge_det <= '0;
   end
 
   always_ff @(posedge m_clk)begin
      if (! fw_edge_det_flg && fw_window_clr) fw_edge_nodet <= '1;
      else                                    fw_edge_nodet <= '0;
   end
 
 
   always_ff @(posedge m_clk)begin
      if (hw_window && edge_detect)      hw_edge_det_flg  <= '1;
      else if(dsd_inc_word_time==6'd20)  hw_edge_det_flg  <= '0;
   end

   always_ff @(posedge m_clk)begin
      if (! hw_edge_det_flg && dsd_inc_word_time==6'd20) hw_edge_nodet <= '1;
      else                                               hw_edge_nodet <= '0;
   end

// Sync State Control
   always_ff @(posedge m_clk, negedge resetN )begin
         if(!resetN)                                            State <= synclos;
         else if(m_clk=='1)                                     State <= NextState;
      end           

   always_comb begin
      case (State)
         synclos:begin
                if(hw_edge_nodet)                               NextState = presync1;
                else                                            NextState = synclos;
            end
         presync1:begin
                if(fw_edge_det)                                 NextState = presync2;
                else if(fw_edge_nodet)                          NextState = synclos;
                else                                            NextState = presync1;
            end
         presync2:begin
                if(fw_edge_det)                                 NextState = presync3;
                else if(fw_edge_nodet)                          NextState = synclos;
                else                                            NextState = presync2;
            end
         presync3:begin
                if(fw_edge_det)                                 NextState = presync4;
                else if(fw_edge_nodet)                          NextState = synclos;
                else                                            NextState = presync3;
            end
         presync4:begin
                if(fw_edge_det)                                 NextState = sync;
                else if(fw_edge_nodet)                          NextState = synclos;
                else                                            NextState = presync4;
            end
         sync:begin
                if(fw_edge_nodet)                               NextState = fwprtect;
                else                                            NextState = sync;
            end
         fwprtect:begin
                if(fw_edge_nodet)                               NextState = synclos;
                else if(fw_edge_det)                            NextState = sync;
                else                                            NextState = fwprtect;
            end
      endcase
   end


//bit_clk gen :
   always_ff @(posedge m_clk)begin
      if (dsd_inc_word_time==6'd26 && bit_clk == 1'b0 && bit_clk_mask == 1'b0)
               bit_clk  <=  1'b1;
            else
               bit_clk  <=  1'b0;
   end

   always_ff @(posedge m_clk)begin
      bit_clk_mask  <= bit_clk;
   end

   always_ff @(posedge m_clk)begin
      if (dsd_inc_word_time==6'd09 && alt_bit_clk == 1'b0 && alt_bit_clk_mask == 1'b0)
               alt_bit_clk  <=  1'b1;
            else
               alt_bit_clk  <=  1'b0;
   end

   always_ff @(posedge m_clk)begin
      alt_bit_clk_mask  <= alt_bit_clk;
   end


//dsd data s/p
   always_ff @(posedge m_clk)begin
      if(bit_clk)  dsd_data <= {dsd_data[30:0],sdata_input_shift[2]};
   end

   assign dsd_out = dsd_data[31] ;
  
   always_ff @(posedge m_clk)begin
      if(alt_bit_clk)  dsd_data_alt <= {dsd_data_alt[30:0], !sdata_input_shift[2]};
   end

   assign dsd_alt_out = dsd_data_alt[31] ;
  
//clk_counter
   always_ff @(posedge m_clk)begin
      if(dsd_data == 32'h5a5a5a5a && cmp_ini_flag) capture_counter <= 5'h0;
      else if (bit_clk)                            capture_counter <= capture_counter + 1;
   end

   always_ff @(posedge m_clk)begin
      if(State == presync4)                             cmp_ini_flag <= 1'b1;
      else if (dsd_data == 32'h5a5a5a5a && cmp_ini_flag)cmp_ini_flag <= 1'b0;
   end

//signaltap clk gen
   always_ff @(posedge m_clk)begin
      if(capture_counter == 5'd00 && hw_window) cap_clk <= 1'b1;
      else                                      cap_clk <= 1'b0;
   end

//compare dsd & alt_dad data
   always_ff @(posedge m_clk)begin
      if(capture_counter == 5'd00 && hw_window)begin
         if(dsd_data == dsd_data_alt) dsd_cmp <= 1'b1;
         else                         dsd_cmp <= 1'b0;
      end
   end

//detect dsd data 5a5a5a5a pattern

   always_ff @(posedge m_clk)begin
      if(capture_counter == 5'd00 && hw_window)begin
         if(dsd_data == 32'h5a5a5a5a) dsd_5apat <= 1'b1;
         else                         dsd_5apat <= 1'b0;
      end
   end


endmodule

0 件のコメント:

コメントを投稿