///////////////////////////////////////////////////////////////////////////// // // S/PDOUT output // // Version : 1.00 // // Copyright(c) 2005 Tatsuyuki Satoh , All rights reserved // // Important ! // // This software is freeware for non-commercial use. // This software is provided "AS IS", without warranty of any kind. // You can use this under your own risk. // // histry: // 2005.12.27 ver.1.00 1st release // ///////////////////////////////////////////////////////////////////////////// `ifdef __SPDOUT_CHS_PARAMS_DEFINE__ `else // chs_freq `define SPDIF_CHS_FREQ_44K1 4'b0000 /* 44.1KHz */ `define SPDIF_CHS_FREQ_48K 4'b0100 /* 48.0KHZ */ `define SPDIF_CHS_FREQ_32K 4'b1100 /* 32.0KHz */ `define SPDIF_CHS_FREQ_CNV 4'b1000 /* sampling rate conversion */ // chs_copyright `define SPDIF_CHS_COPYRIGHT_PROTECT 1'b0 /* copy protect */ `define SPDIF_CHS_COPYRIGHT_FREE 1'b1 /* copy free */ // chs_chtype `define SPDIF_CHS_CHTYPE_2CH 3'b000 /* 2ch audio */ `define SPDIF_CHS_CHTYPE_2CH_E 3'b100 /* 2ch 50/15u spreemphasis */ // chs_cat `define SPDIF_CHS_CAT_GENERIC 7'b0000000 /* generic */ `define SPDIF_CHS_CAT_CD 7'b1000000 /* CD */ `define SPDIF_CHS_CAT_SYNTH 7'b1010000 /* Synthesiser */ // chs_copy `define SPDIF_CHS_COPY_ORIG 1'b0 /* original */ `define SPDIF_CHS_COPY_COPY 1'b1 /* copy */ `endif //////////////////////////////////////// // S/PDIF OUTPUT //////////////////////////////////////// module spdout(clk,clk_en,reset,enable,ldata,rdata,lload,rload,chs_freq,spdout); input clk; // 128fs clock input clk_en; // clock enable(When CLK is 128fs, it is fixed on 1'b1.) input reset; // sync reset (output disable) input enable; // 'spdout' output enable input [23:0] ldata; // signed left data input [23:0] rdata; // signed right data output lload,rload; // load signal //Format input [3:0] chs_freq; output spdout; // S/PDIF TX signal //////////////////////////////////////// // frame phase //////////////////////////////////////// reg [7:0] fr_cnt; // frame 0 to 191 reg fr_sub; // sub frame reg [4:0] fr_phase; // sub frame word 0 to 31 reg fr_bit; // half bit // frame select wire b_frame = (fr_cnt==0) && ~fr_sub; // 11101000 = 0M1R1M0 wire m_frame = (fr_cnt!=0) && ~fr_sub; // 11100010 = 0M1M0R1 wire w_frame = fr_sub; // 11100100 = 0M1M1R0 reg spd_out_r; //////////////////////////////////////// // subframe data //////////////////////////////////////// // channel status reg parity; wire ch_status = CH_STS(fr_cnt,fr_sub); wire user_data = 1'b0; reg varidate; reg [23:0] sample_data; // one sub frame wire [31:0] sfr_data = { parity, // 31 parity bit ch_status, // 30 chan user_data, // 29 user data varidate, // 28 validate sample_data, // 27..8/7..3 data + AUX m_frame, // 3 b_frame|w_frame, // 2 b or w frame 2'b10 // 1..0 preample }; //////////////////////////////////////// // channle status data //////////////////////////////////////// // 0:audio data // 1:digital data wire chs_datatype = 1'b0; wire chs_copyright = `SPDIF_CHS_COPYRIGHT_FREE; wire [2:0] chs_chtype = `SPDIF_CHS_CHTYPE_2CH; // 00 wire [1:0] chs_mode = 2'b00; wire [6:0] categoly = `SPDIF_CHS_CAT_GENERIC; wire chs_copied = `SPDIF_CHS_COPY_ORIG; wire [3:0] source = 4'b0000; function CH_STS; input [7:0] frm; input sub; begin case(frm) 0:CH_STS = 1'b0; // 0=commercial 1:CH_STS = chs_datatype; // audio data 0=audio,1=digital data 2:CH_STS = chs_copyright; // copy right 0=free,1=protect 3:CH_STS = chs_chtype[2]; // 2ch audio 4:CH_STS = chs_chtype[1]; 5:CH_STS = chs_chtype[0]; 6:CH_STS = chs_mode[1]; // mode 00 7:CH_STS = chs_mode[0]; 8:CH_STS = categoly[6]; // categoly 9:CH_STS = categoly[5]; 10:CH_STS = categoly[4]; 11:CH_STS = categoly[3]; 12:CH_STS = categoly[2]; 13:CH_STS = categoly[1]; 14:CH_STS = categoly[0]; 15:CH_STS = chs_copied; // copy : ok 16:CH_STS = source[3]; // source number 17:CH_STS = source[2]; 18:CH_STS = source[1]; 19:CH_STS = source[0]; 20:CH_STS = ~sub; // stereo L 1000 or R 0100 21:CH_STS = sub; 22:CH_STS = 1'b0; 23:CH_STS = 1'b0; 24:CH_STS = chs_freq[3]; // sampling rate 44.1KHz 00 , 48K / 32K / conv 25:CH_STS = chs_freq[2]; 26:CH_STS = chs_freq[1]; 27:CH_STS = chs_freq[0]; 28:CH_STS = 1'b0; // clock standard level II 00 29:CH_STS = 1'b0; default: CH_STS = 1'b0; // reserved endcase end endfunction //////////////////////////////////////// // timing generator //////////////////////////////////////// wire last_subframe = (fr_phase==31); always @(posedge clk) begin if(reset) begin fr_bit <= 1'b0; fr_phase <= 0; fr_sub <= 1'b0; fr_cnt <= 1'b0; end else if(clk_en) begin fr_bit <= ~fr_bit; if(fr_bit) begin fr_phase <= fr_phase + 1; if(last_subframe) begin fr_sub <= ~fr_sub; if(fr_sub) begin fr_cnt <= fr_cnt + 1; if(fr_cnt==191) fr_cnt <= 0; end end end end end //////////////////////////////////////// // latch sampling data //////////////////////////////////////// always @(posedge clk) begin if(reset) begin varidate <= 1'b1; sample_data <= 24'h000000; end else if(clk_en) begin if(fr_bit & last_subframe) begin varidate <= ~enable; sample_data <= ~enable ? 0 : fr_sub ? ldata : rdata; end end end assign lload = fr_bit && last_subframe && fr_sub; assign rload = fr_bit && last_subframe && ~fr_sub; //////////////////////////////////////// // parity generator //////////////////////////////////////// always @(posedge clk) begin if(reset) begin parity <= 1'b0; end else if(clk_en & fr_bit) begin parity <= (fr_phase==3) ? 1'b0 : parity ^ sfr_data[fr_phase]; end end //////////////////////////////////////// // encoding //////////////////////////////////////// wire missing_clk = (fr_phase==0) | ((fr_phase==2) & b_frame) | ((fr_phase==1) & ~b_frame); wire bit_rev = (~fr_bit && sfr_data[fr_phase]) | // bit half , DATA ( fr_bit && ~missing_clk); // bit border , keep when missing always @(posedge clk) begin if(reset) begin spd_out_r <= 1'b0; end else if(clk_en) begin spd_out_r <= spd_out_r ^ bit_rev; end end assign spdout = spd_out_r; endmodule