diff --git a/Basys3_Master.xdc b/Basys3_Master.xdc index d4d8f04..4b2c33c 100644 --- a/Basys3_Master.xdc +++ b/Basys3_Master.xdc @@ -209,31 +209,31 @@ set_property PACKAGE_PIN G3 [get_ports {ad_sdout}] #set_property IOSTANDARD LVCMOS33 [get_ports {JC[7]}] -##Pmod Header JXADC -##Sch name = XA1_P -#set_property PACKAGE_PIN J3 [get_ports {JXADC[0]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[0]}] -##Sch name = XA2_P -#set_property PACKAGE_PIN L3 [get_ports {JXADC[1]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[1]}] -##Sch name = XA3_P -#set_property PACKAGE_PIN M2 [get_ports {JXADC[2]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[2]}] -##Sch name = XA4_P -#set_property PACKAGE_PIN N2 [get_ports {JXADC[3]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[3]}] -##Sch name = XA1_N -#set_property PACKAGE_PIN K3 [get_ports {JXADC[4]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[4]}] -##Sch name = XA2_N -#set_property PACKAGE_PIN M3 [get_ports {JXADC[5]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[5]}] -##Sch name = XA3_N -#set_property PACKAGE_PIN M1 [get_ports {JXADC[6]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[6]}] -##Sch name = XA4_N -#set_property PACKAGE_PIN N1 [get_ports {JXADC[7]}] - #set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[7]}] +#Pmod Header JXADC +#Sch name = XA1_P +set_property PACKAGE_PIN J3 [get_ports {JXADC[0]}] + set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[0]}] +#Sch name = XA2_P +set_property PACKAGE_PIN L3 [get_ports {JXADC[1]}] + set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[1]}] +#Sch name = XA3_P +set_property PACKAGE_PIN M2 [get_ports {JXADC[2]}] + set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[2]}] +#Sch name = XA4_P +set_property PACKAGE_PIN N2 [get_ports {JXADC[3]}] + set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[3]}] +#Sch name = XA1_N +set_property PACKAGE_PIN K3 [get_ports {JXADC[4]}] + set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[4]}] +#Sch name = XA2_N +set_property PACKAGE_PIN M3 [get_ports {JXADC[5]}] + set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[5]}] +#Sch name = XA3_N +set_property PACKAGE_PIN M1 [get_ports {JXADC[6]}] + set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[6]}] +#Sch name = XA4_N +set_property PACKAGE_PIN N1 [get_ports {JXADC[7]}] + set_property IOSTANDARD LVCMOS33 [get_ports {JXADC[7]}] diff --git a/JXADC_controler.v b/JXADC_controler.v new file mode 100644 index 0000000..e5b71f3 --- /dev/null +++ b/JXADC_controler.v @@ -0,0 +1,18 @@ +// This module outputs signals to JXADC PMOD +// where logic analyzer are conected. + +module JXADC_controler ( + input ch0, + input ch1, + input ch2, + input ch3, + input ch4, + input ch5, + input ch6, + input ch7, + output [7: 0] JXADC // output for logic analizer + ); + +assign JXADC = {ch7,ch6,ch5,ch4,ch3,ch2,ch1,ch0}; + +endmodule \ No newline at end of file diff --git a/effect_controler.v b/effect_controler.v index 2b75a42..d8c822a 100644 --- a/effect_controler.v +++ b/effect_controler.v @@ -3,12 +3,21 @@ module effect_controler #( parameter )( // input clk, input signed [d_width-1: 0] i_l_data, - input signed [d_width-1: 0] i_r_data, - output signed [d_width-1: 0] o_l_data, - output signed [d_width-1: 0] o_r_data + input signed [d_width-1: 0] i_r_data, + output reg signed [d_width-1: 0] o_l_data, + output reg signed [d_width-1: 0] o_r_data ); -assign o_l_data = i_l_data; -assign o_r_data = i_r_data; +always@* begin + o_l_data <= i_l_data; + o_r_data <= i_r_data; +end + +//assign o_l_data = i_l_data; +//assign o_r_data = i_r_data; + + +//assign o_l_data = 24'h000000; +//assign o_r_data = 24'h400008; endmodule \ No newline at end of file diff --git a/i2s_receiver.v b/i2s_receiver.v new file mode 100644 index 0000000..a3fd409 --- /dev/null +++ b/i2s_receiver.v @@ -0,0 +1,95 @@ +// This I2S Playback design uses the common 44.1 kHz +// sampling frequency. +// From Figure 2 in Section 4.1.1 of the CS5343 +// Datasheet, it is appropriate to use an SCLK/LRCK +// ratio of 64 and a MCLK/LRCK ratio of 256. +// Therefore, the I2S Transceiver’s generic +// parameter sclk_ws_ratio is set to 64. +// (LRCK, e.g. left-right clock, and ws, +// e.g. word select, are synonymous.) +// The generic parameter mclk_sclk_ratio is set to 4, +// since MCLK/SCLK = (MCLK/LRCK) / (SCLK/LRCK) = 256/64 = 4. +// +// As such, the word select (or left-right clock) frequency +// is 44.1 kHz, the serial clock frequency is 44.1 kHz * 64 = 2.82 MHz, +// and the master clock frequency is 2.82 MHz * 4 = 11.29 MHz. +// Table 1, Section 4.1 of the CS4344 Datasheet confirms this +// selection, listing 11.29 MHz as a common frequency +// for the master clock when the LRCK is 44.1 kHz. +// +// Module is created from sample provided by +// Digilent +// + + +module i2s_receicer #( parameter + sclk_ws_ratio = 64, // number of sclk periods per word select period + mclk_sclk_ratio = 4, // number of mclk periods per sclk period + d_width = 24 // data width +)( + input reset_n, //asynchronous active low reset + input mclk, //master clock + output sclk, //serial clock (or bit clock) + output ws, //word select (or left-right clock) + input sd_rx, //serial data receive + output reg signed [d_width-1: 0] l_data_rx, //left channel data received + output reg signed [d_width-1: 0] r_data_rx //right channel data received + + ); + +reg sclk_int = 0; //internal serial clock wire +reg ws_int = 0; //internal word select wire +reg signed [d_width-1: 0] l_data_rx_int = 'sb0; //internal left channel rx data buffer +reg signed [d_width-1: 0] r_data_rx_int = 'sb0; //internal right channel rx data buffer + +reg signed [d_width-1: 0] reg_r_data_rx = 'sb0; +reg signed [d_width-1: 0] reg_l_data_rx = 'sb0; + + +reg [2: 0] sclk_cnt = 0; //counter of master clocks during half period of serial clock +reg [7: 0] ws_cnt = 0; //counter of serial clock toggles during half period of word select + + + +always@(posedge mclk, posedge reset_n) begin + + if (reset_n == 1) begin + sclk_cnt <= 'b0; //clear mclk/sclk counter + ws_cnt <= 'b0; //clear sclk/ws counter + sclk_int <= 0; //clear serial clock signal + ws_int <= 0; //clear word select signal + l_data_rx_int <= 'sb0; //clear internal left channel rx data buffer + r_data_rx_int <= 'sb0; //clear internal right channel rx data buffer + end + else begin //master clock rising edge + if (sclk_cnt < mclk_sclk_ratio/2-1) begin //less than half period of sclk + sclk_cnt <= sclk_cnt + 1; //increment mclk/sclk counter + end + else begin //half period of sclk + sclk_cnt <= 0; //reset mclk/sclk counter + sclk_int <= ~sclk_int; //toggle serial clock + if (ws_cnt < sclk_ws_ratio - 1) begin //less than half period of ws + ws_cnt <= ws_cnt + 1; //increment sclk/ws counter + if (sclk_int == 0 && ws_cnt > 1 && ws_cnt < d_width * 2 + 2) begin //rising edge of sclk during data word + if (ws_int == 1) begin //right channel + r_data_rx_int <= {r_data_rx_int[d_width-2 : 0] , sd_rx}; //shift data bit into right channel rx data buffer + end else begin //left channel + l_data_rx_int <= {l_data_rx_int[d_width-2 : 0] , sd_rx}; //shift data bit into left channel rx data buffer + end + end + + + end else begin //half period of ws + ws_cnt <= 0; //reset sclk/ws counter + ws_int <= ~ws_int; //toggle word select + r_data_rx <= r_data_rx_int; //output right channel received data + l_data_rx <= l_data_rx_int; //output left channel received data + end + end + end +end + +assign sclk = sclk_int; //output serial clock +assign ws = ws_int; //output word select + +endmodule \ No newline at end of file diff --git a/i2s_sender.v b/i2s_sender.v new file mode 100644 index 0000000..82b1802 --- /dev/null +++ b/i2s_sender.v @@ -0,0 +1,96 @@ +// This I2S Playback design uses the common 44.1 kHz +// sampling frequency. +// From Figure 2 in Section 4.1.1 of the CS5343 +// Datasheet, it is appropriate to use an SCLK/LRCK +// ratio of 64 and a MCLK/LRCK ratio of 256. +// Therefore, the I2S Transceiver’s generic +// parameter sclk_ws_ratio is set to 64. +// (LRCK, e.g. left-right clock, and ws, +// e.g. word select, are synonymous.) +// The generic parameter mclk_sclk_ratio is set to 4, +// since MCLK/SCLK = (MCLK/LRCK) / (SCLK/LRCK) = 256/64 = 4. +// +// As such, the word select (or left-right clock) frequency +// is 44.1 kHz, the serial clock frequency is 44.1 kHz * 64 = 2.82 MHz, +// and the master clock frequency is 2.82 MHz * 4 = 11.29 MHz. +// Table 1, Section 4.1 of the CS4344 Datasheet confirms this +// selection, listing 11.29 MHz as a common frequency +// for the master clock when the LRCK is 44.1 kHz. +// +// Module is created from sample provided by +// Digilent +// + + +module i2s_sender #( parameter + sclk_ws_ratio = 64, // number of sclk periods per word select period + mclk_sclk_ratio = 4, // number of mclk periods per sclk period + d_width = 24 // data width +)( + input reset_n, //asynchronous active low reset + input mclk, //master clock + output sclk, //serial clock (or bit clock) + output ws, //word select (or left-right clock) + output reg sd_tx, //serial data transmit + input signed [d_width-1: 0] l_data_tx, //left channel data to transmit + input signed [d_width-1: 0] r_data_tx //right channel data to transmit + ); + +reg sclk_int = 0; //internal serial clock wire +reg ws_int = 0; //internal word select wire +reg signed [d_width-1: 0] l_data_tx_int = 'sb0; //internal left channel tx data buffer +reg signed [d_width-1: 0] r_data_tx_int = 'sb0; //internal right channel tx data buffer + +reg r_sd_tx = 0; //internal register + + +reg [2: 0] sclk_cnt = 0; //counter of master clocks during half period of serial clock +reg [7: 0] ws_cnt = 0; //counter of serial clock toggles during half period of word select + + + +always@(posedge mclk, posedge reset_n) begin + + if (reset_n == 1) begin + sclk_cnt <= 'b0; //clear mclk/sclk counter + ws_cnt <= 'b0; //clear sclk/ws counter + sclk_int <= 0; //clear serial clock signal + ws_int <= 0; //clear word select signal + l_data_tx_int <= 'sb0; //clear internal left channel tx data buffer + r_data_tx_int <= 'sb0; //clear internal right channel tx data buffer + r_sd_tx <= 0; //clear serial data transmit output + end + else begin //master clock rising edge + if (sclk_cnt < mclk_sclk_ratio/2-1) begin //less than half period of sclk + sclk_cnt <= sclk_cnt + 1; //increment mclk/sclk counter + end + else begin //half period of sclk + sclk_cnt <= 0; //reset mclk/sclk counter + sclk_int <= ~sclk_int; //toggle serial clock + if (ws_cnt < sclk_ws_ratio - 1) begin //less than half period of ws + ws_cnt <= ws_cnt + 1; //increment sclk/ws counter + + if (sclk_int == 1 && ws_cnt > 1 && ws_cnt < d_width*2+3) begin //falling edge of sclk during data word + if (ws_int == 1) begin //right channel + sd_tx <= r_data_tx_int[d_width-1]; //transmit serial data bit + r_data_tx_int <= {r_data_tx_int[d_width-2 : 0] , 1'b0}; //shift data of right channel tx data buffer + end else begin //left channel + sd_tx <= l_data_tx_int[d_width-1]; //ransmit serial data bit + l_data_tx_int <= {l_data_tx_int[d_width-2 : 0] , 1'b0}; //shift data of left channel tx data buffer + end + end + end else begin //half period of ws + ws_cnt <= 0; //reset sclk/ws counter + ws_int <= ~ws_int; //toggle word select + r_data_tx_int <= r_data_tx; + l_data_tx_int <= l_data_tx; + end + end + end +end + +assign sclk = sclk_int; //output serial clock +assign ws = ws_int; //output word select +//assign sd_tx = r_sd_tx; //assign sd_tx + +endmodule \ No newline at end of file diff --git a/i2s_transceiver.v b/i2s_transceiver.v index db49dfb..8d5cd9a 100644 --- a/i2s_transceiver.v +++ b/i2s_transceiver.v @@ -35,21 +35,21 @@ module i2s_transceiver #( parameter input sd_rx, //serial data receive input signed [d_width-1: 0] l_data_tx, //left channel data to transmit input signed [d_width-1: 0] r_data_tx, //right channel data to transmit - output signed [d_width-1: 0] l_data_rx, //left channel data received - output signed [d_width-1: 0] r_data_rx //right channel data received + output reg signed [d_width-1: 0] l_data_rx, //left channel data received + output reg signed [d_width-1: 0] r_data_rx //right channel data received ); reg sclk_int = 0; //internal serial clock wire reg ws_int = 0; //internal word select wire -reg signed [d_width-1: 0] l_data_rx_int = 0; //internal left channel rx data buffer -reg signed [d_width-1: 0] r_data_rx_int = 0; //internal right channel rx data buffer -reg signed [d_width-1: 0] l_data_tx_int = 0; //internal left channel tx data buffer -reg signed [d_width-1: 0] r_data_tx_int = 0; //internal right channel tx data buffer +reg signed [d_width-1: 0] l_data_rx_int = 'sb0; //internal left channel rx data buffer +reg signed [d_width-1: 0] r_data_rx_int = 'sb0; //internal right channel rx data buffer +reg signed [d_width-1: 0] l_data_tx_int = 'sb0; //internal left channel tx data buffer +reg signed [d_width-1: 0] r_data_tx_int = 'sb0; //internal right channel tx data buffer reg r_sd_tx = 0; //internal register -reg signed [d_width-1: 0] reg_r_data_rx = 0; -reg signed [d_width-1: 0] reg_l_data_rx = 0; +reg signed [d_width-1: 0] reg_r_data_rx = 'sb0; +reg signed [d_width-1: 0] reg_l_data_rx = 'sb0; reg [2: 0] sclk_cnt = 0; //counter of master clocks during half period of serial clock @@ -64,13 +64,13 @@ always@(posedge mclk, posedge reset_n) begin ws_cnt <= 'b0; //clear sclk/ws counter sclk_int <= 0; //clear serial clock signal ws_int <= 0; //clear word select signal - l_data_rx_int <= 'b0; //clear internal left channel rx data buffer - r_data_rx_int <= 'b0; //clear internal right channel rx data buffer - l_data_tx_int <= 'b0; //clear internal left channel tx data buffer - r_data_tx_int <= 'b0; //clear internal right channel tx data buffer + l_data_rx_int <= 'sb0; //clear internal left channel rx data buffer + r_data_rx_int <= 'sb0; //clear internal right channel rx data buffer + l_data_tx_int <= 'sb0; //clear internal left channel tx data buffer + r_data_tx_int <= 'sb0; //clear internal right channel tx data buffer r_sd_tx <= 0; //clear serial data transmit output - reg_l_data_rx <= 'b0; //clear left channel received data output - reg_r_data_rx <= 'b0; //clear right channel received data output + //reg_l_data_rx <= 'sb0; //clear left channel received data output + //reg_r_data_rx <= 'sb0; //clear right channel received data output end else begin //master clock rising edge if (sclk_cnt < mclk_sclk_ratio/2-1) begin //less than half period of sclk @@ -103,6 +103,8 @@ always@(posedge mclk, posedge reset_n) begin ws_int <= ~ws_int; //toggle word select // reg_r_data_rx <= r_data_rx_int; //output right channel received data // reg_l_data_rx <= l_data_rx_int; //output left channel received data + r_data_rx <= r_data_rx_int; //output right channel received data + l_data_rx <= l_data_rx_int; //output left channel received data r_data_tx_int <= r_data_tx; //latch in right channel data to transmit l_data_tx_int <= l_data_tx; //latch in left channel data to transmit end @@ -115,7 +117,8 @@ assign ws = ws_int; //output word select assign sd_tx = r_sd_tx; //assign sd_tx //assign r_data_rx = reg_r_data_rx; //assign l_data_rx = reg_l_data_rx; -assign r_data_rx = ~(ws_cnt < sclk_ws_ratio - 1)? r_data_rx_int: r_data_rx ; -assign l_data_rx = ~(ws_cnt < sclk_ws_ratio - 1)? l_data_rx_int: l_data_rx ; + +//assign r_data_rx = ~(ws_cnt < sclk_ws_ratio - 1)? r_data_rx_int: r_data_rx ; +//assign l_data_rx = ~(ws_cnt < sclk_ws_ratio - 1)? l_data_rx_int: l_data_rx ; endmodule \ No newline at end of file diff --git a/top.v b/top.v index a41fecf..73c72b5 100644 --- a/top.v +++ b/top.v @@ -17,13 +17,16 @@ module top #( parameter output da_lrck, output ad_lrck, input ad_sdout, - output da_sdin + output da_sdin, + output [7: 0] JXADC // output for logic analizer ); //------internal wires and registers-------- wire master_clk; // 11.29 MHz master clock -wire serial_clk; -wire word_select; +wire serial_clk_sender; +wire word_select_sender; +wire serial_clk_receicer; +wire word_select_receicer; wire reset_n; wire [d_width-1: 0] r_data_tx; wire [d_width-1: 0] l_data_tx; @@ -33,6 +36,19 @@ wire [d_width-1: 0] l_data_rx; wire w_sd_tx; //internal wire //-----sub modules-------------------------- +// connecting signals to JXADC PMOD to monitor them with signal analyzer +JXADC_controler JXADC_controler( + .ch0(master_clk), + .ch1(serial_clk_receicer), + .ch2(word_select_receicer), + .ch3(ad_sdout), // serial data in + .ch4(master_clk), + .ch5(serial_clk_sender), + .ch6(word_select_sender), + .ch7(w_sd_tx), // serial data out + .JXADC(JXADC) // output for logic analizer +); + //declare PLL to create 11.29 MHz master clock from 100 MHz system clock clk_wiz_0 m_clk( @@ -40,20 +56,48 @@ clk_wiz_0 m_clk( .clk_out1(master_clk) ); -//instantiate I2S Transceiver component -i2s_transceiver #( +// // instantiate I2S Transceiver component +// i2s_transceiver #( +// .mclk_sclk_ratio(mclk_sclk_ratio), //number of mclk periods per sclk period +// .sclk_ws_ratio(sclk_ws_ratio), //number of sclk periods per word select period +// .d_width(d_width) //data width +// ) i2s_transceiver ( +// .reset_n(reset_n), //asynchronous active high reset +// .mclk(master_clk), //master clock +// .sclk(serial_clk), //serial clock (or bit clock) +// .ws(word_select), //word select (or left-right clock) +// .sd_rx(ad_sdout), //serial data transmit +// .sd_tx(w_sd_tx), //serial data receive +// .l_data_tx(l_data_tx), //left channel data to transmit +// .r_data_tx(r_data_tx), //right channel data to transmit +// .l_data_rx(l_data_rx), //left channel data received +// .r_data_rx(r_data_rx) //right channel data received +// ); + +i2s_sender #( .mclk_sclk_ratio(mclk_sclk_ratio), //number of mclk periods per sclk period .sclk_ws_ratio(sclk_ws_ratio), //number of sclk periods per word select period .d_width(d_width) //data width -) i2s_transceiver ( +) i2s_sender ( + .reset_n(reset_n), //asynchronous active high reset + .mclk(master_clk), //master clock + .sclk(serial_clk_sender), //serial clock (or bit clock) + .ws(word_select_sender), //word select (or left-right clock) + .sd_tx(w_sd_tx), //serial data transmit + .l_data_tx(l_data_tx), //left channel data to transmit + .r_data_tx(r_data_tx) //right channel data to transmit +); + +i2s_receicer #( + .mclk_sclk_ratio(mclk_sclk_ratio), //number of mclk periods per sclk period + .sclk_ws_ratio(sclk_ws_ratio), //number of sclk periods per word select period + .d_width(d_width) //data width +) i2s_receicer ( .reset_n(reset_n), //asynchronous active high reset .mclk(master_clk), //master clock - .sclk(serial_clk), //serial clock (or bit clock) - .ws(word_select), //word select (or left-right clock) - .sd_rx(ad_sdout), //serial data transmit - .sd_tx(w_sd_tx), //serial data receive - .l_data_tx(l_data_tx), //left channel data to transmit - .r_data_tx(r_data_tx), //right channel data to transmit + .sclk(serial_clk_receicer), //serial clock (or bit clock) + .ws(word_select_receicer), //word select (or left-right clock) + .sd_rx(ad_sdout), //serial data receive .l_data_rx(l_data_rx), //left channel data received .r_data_rx(r_data_rx) //right channel data received ); @@ -78,10 +122,10 @@ debounce_switch debounce_switch_reset( assign da_mclk = master_clk; //output master clock to ADC assign ad_mclk = master_clk; //output master clock to DAC -assign da_sclk = serial_clk; //output serial clock (from I2S Transceiver) to ADC -assign ad_sclk = serial_clk; //output serial clock (from I2S Transceiver) to DAC -assign da_lrck = word_select; //output word select (from I2S Transceiver) to ADC -assign ad_lrck = word_select; //output word select (from I2S Transceiver) to DAC +assign da_sclk = serial_clk_sender; //output serial clock (from I2S Transceiver) to ADC +assign ad_sclk = serial_clk_receicer; //output serial clock (from I2S Transceiver) to DAC +assign da_lrck = word_select_sender; //output word select (from I2S Transceiver) to ADC +assign ad_lrck = word_select_receicer; //output word select (from I2S Transceiver) to DAC assign da_sdin = w_sd_tx; //assign right channel received data to transmit (to playback out received data)