Created
June 20, 2024 03:01
-
-
Save DatanoiseTV/6eed01690855a6bdc67ea86d3625fb91 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Verilog ADAT receiver - based on https://opencores.org/projects/adat_optical_feed_forward_receiver | |
module ADAT_receiver ( | |
input m_clk, | |
input adat_in, | |
output reg [3:0] adat_user, // ADAT user bits | |
output reg adat_wordclock, // ADAT wordclock out (approx 50% symmetry) | |
output reg i2s_bclk, // I2S bit clock | |
output reg i2s_lrclk, // I2S left-right clock | |
output reg i2s_data0, // I2S data channel 0 | |
output reg i2s_data1, // I2S data channel 1 | |
output reg i2s_data2, // I2S data channel 2 | |
output reg i2s_data3 // I2S data channel 3 | |
); | |
reg [1:0] adat_input_shift; | |
reg adat_edge_detect; | |
reg [1:0] adat_edge_shift; | |
reg [9:0] adat_edge_cur_time = 10'b0; | |
reg [9:0] adat_edge_max_time = 10'b0; | |
reg [15:0] wait_increase; | |
reg [11:0] adat_inc_word_time = 12'b0; | |
reg [11:0] adat_cur_word_time = 12'b0; | |
reg [8:0] adat_sync_mask_time = 9'b0; | |
reg adat_sync_mask = 1'b0; | |
reg [1:0] adat_sync_mask_shift = 2'b0; | |
reg [7:0] adat_bit_counter = 8'b0; | |
reg [11:0] adat_bit_sample = 12'b0; | |
reg adat_bit_clk; | |
reg [1:0] adat_data; | |
reg [255:0] adat_data_shift = {256{1'b1}}; | |
reg [23:0] audio_buffer_0, audio_buffer_1, audio_buffer_2, audio_buffer_3; | |
reg [23:0] audio_buffer_4, audio_buffer_5, audio_buffer_6, audio_buffer_7; | |
reg [9:0] lrclk_cnt = 0; | |
reg lrclk = 0; | |
// Instantiate the multiplier | |
wire [11:0] mult_result; | |
mult12x8 multiplier ( | |
.dataa(adat_cur_word_time), | |
.datab(adat_bit_counter), | |
.result(mult_result) | |
); | |
always @(posedge m_clk) begin | |
adat_input_shift <= {adat_input_shift[0], adat_in}; | |
end | |
always @(posedge m_clk) begin | |
if ((adat_input_shift == 2'b01) || (adat_input_shift == 2'b10)) begin | |
adat_edge_detect <= 1; | |
adat_edge_cur_time <= 0; | |
end else begin | |
adat_edge_cur_time <= adat_edge_cur_time + 1; | |
adat_edge_detect <= 0; | |
if (adat_edge_cur_time > adat_edge_max_time) begin | |
adat_edge_max_time <= adat_edge_cur_time; | |
wait_increase <= 0; | |
end else begin | |
wait_increase <= wait_increase + 1; | |
if (wait_increase == (1 << (wait_increase[15:0] - 1))) begin | |
adat_edge_max_time <= adat_edge_max_time - 1; | |
end | |
end | |
end | |
end | |
always @(posedge m_clk) begin | |
adat_edge_shift <= {adat_edge_shift[0], adat_edge_detect}; | |
end | |
always @(posedge m_clk) begin | |
adat_sync_mask_time <= adat_edge_max_time[9:1] + adat_edge_max_time[9:2]; | |
if (adat_edge_cur_time <= adat_sync_mask_time) begin | |
adat_sync_mask <= 1; | |
end else begin | |
adat_sync_mask <= 0; | |
end | |
end | |
always @(posedge m_clk) begin | |
adat_sync_mask_shift <= {adat_sync_mask_shift[0], adat_sync_mask}; | |
end | |
always @(posedge m_clk) begin | |
adat_inc_word_time <= adat_inc_word_time + 1; | |
if (adat_edge_detect && !adat_sync_mask) begin | |
adat_cur_word_time <= adat_inc_word_time; | |
adat_bit_counter <= 0; // set to bit 0 for first sample point | |
end | |
if (adat_sync_mask_shift == 2'b01) begin | |
adat_inc_word_time <= 0; | |
end | |
if (adat_inc_word_time == mult_result) begin | |
adat_bit_clk <= 1; | |
adat_data <= {adat_data[0], adat_in}; | |
adat_bit_counter <= adat_bit_counter + 1; | |
end else begin | |
adat_bit_clk <= 0; | |
end | |
end | |
always @(posedge adat_bit_clk) begin | |
if ((adat_data == 2'b00) || (adat_data == 2'b11)) begin | |
adat_data_shift <= {adat_data_shift[254:0], 1'b0}; | |
end else begin | |
adat_data_shift <= {adat_data_shift[254:0], 1'b1}; | |
end | |
end | |
always @(posedge adat_bit_clk) begin | |
if (adat_bit_counter <= 8'd127) begin | |
adat_wordclock <= 0; | |
end else begin | |
adat_wordclock <= 1; | |
end | |
end | |
always @(posedge adat_bit_clk) begin | |
if (adat_data_shift[255:246] == 10'b0000000000) begin | |
adat_user <= adat_data_shift[245:242]; | |
audio_buffer_0 <= {adat_data_shift[241:238], adat_data_shift[237:234], adat_data_shift[233:230], adat_data_shift[229:226], adat_data_shift[225:222], adat_data_shift[221:218]}; | |
audio_buffer_1 <= {adat_data_shift[217:214], adat_data_shift[213:210], adat_data_shift[209:206], adat_data_shift[205:202], adat_data_shift[201:198], adat_data_shift[197:194]}; | |
audio_buffer_2 <= {adat_data_shift[193:190], adat_data_shift[189:186], adat_data_shift[185:182], adat_data_shift[181:178], adat_data_shift[177:174], adat_data_shift[173:170]}; | |
audio_buffer_3 <= {adat_data_shift[169:166], adat_data_shift[165:162], adat_data_shift[161:158], adat_data_shift[157:154], adat_data_shift[153:150], adat_data_shift[149:146]}; | |
audio_buffer_4 <= {adat_data_shift[145:142], adat_data_shift[141:138], adat_data_shift[137:134], adat_data_shift[133:130], adat_data_shift[129:126], adat_data_shift[125:122]}; | |
audio_buffer_5 <= {adat_data_shift[121:118], adat_data_shift[117:114], adat_data_shift[113:110], adat_data_shift[109:106], adat_data_shift[105:102], adat_data_shift[101:98]}; | |
audio_buffer_6 <= {adat_data_shift[97:94], adat_data_shift[93:90], adat_data_shift[89:86], adat_data_shift[85:82], adat_data_shift[81:78], adat_data_shift[77:74]}; | |
audio_buffer_7 <= {adat_data_shift[73:70], adat_data_shift[69:66], adat_data_shift[65:62], adat_data_shift[61:58], adat_data_shift[57:54], adat_data_shift[53:50]}; | |
end | |
end | |
// I2S Bit Clock Generation | |
always @(posedge m_clk) begin | |
lrclk_cnt <= lrclk_cnt + 1; | |
if (lrclk_cnt == 32) begin // Assuming 32 bits per LRCLK period | |
lrclk <= ~lrclk; | |
lrclk_cnt <= 0; | |
end | |
i2s_bclk <= ~i2s_bclk; // BCLK runs at double the speed of m_clk | |
end | |
// I2S Data Transmission | |
always @(posedge i2s_bclk) begin | |
if (lrclk == 0) begin | |
i2s_data0 <= audio_buffer_0[23]; | |
audio_buffer_0 <= {audio_buffer_0[22:0], 1'b0}; | |
i2s_data1 <= audio_buffer_1[23]; | |
audio_buffer_1 <= {audio_buffer_1[22:0], 1'b0}; | |
i2s_data2 <= audio_buffer_2[23]; | |
audio_buffer_2 <= {audio_buffer_2[22:0], 1'b0}; | |
i2s_data3 <= audio_buffer_3[23]; | |
audio_buffer_3 <= {audio_buffer_3[22:0], 1'b0}; | |
end else begin | |
i2s_data0 <= audio_buffer_4[23]; | |
audio_buffer_4 <= {audio_buffer_4[22:0], 1'b0}; | |
i2s_data1 <= audio_buffer_5[23]; | |
audio_buffer_5 <= {audio_buffer_5[22:0], 1'b0}; | |
i2s_data2 <= audio_buffer_6[23]; | |
audio_buffer_6 <= {audio_buffer_6[22:0], 1'b0}; | |
i2s_data3 <= audio_buffer_7[23]; | |
audio_buffer_7 <= {audio_buffer_7[22:0], 1'b0}; | |
end | |
end | |
assign i2s_lrclk = lrclk; | |
endmodule |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment