この回路をベースにI2S、ADAT、S/PDIF受信回路にDSD受信機能として統合する予定。片チャネル分のため、2回路化、L/Rの多重処理が追加で必要になります。現在サンプリングクロックとして98.3040MHzを使用していますが、90.3168MHzに変更します。
DSD Phase Modulation Mode 受信回路構成
DSD Phase Modulation Mode 受信回路 SystemVerilogコード
`timescale 1ns/1nsmodule 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 件のコメント:
コメントを投稿