From 7a8135bf3024e5eb653dfeedd56c0641b7aa76f4 Mon Sep 17 00:00:00 2001 From: Imants Pulkstenis Date: Sun, 20 Oct 2019 19:27:16 +0300 Subject: [PATCH] repaired i2s (loopback audio working) --- i2s_receiver.v | 6 +-- i2s_sender.v | 2 +- i2s_transceiver.v | 124 ------------------------------------------- i2s_transceiver_tb.v | 87 ------------------------------ 4 files changed, 3 insertions(+), 216 deletions(-) delete mode 100644 i2s_transceiver.v delete mode 100644 i2s_transceiver_tb.v diff --git a/i2s_receiver.v b/i2s_receiver.v index a3fd409..cc7e9dd 100644 --- a/i2s_receiver.v +++ b/i2s_receiver.v @@ -42,11 +42,9 @@ 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 [3: 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 @@ -61,7 +59,7 @@ always@(posedge mclk, posedge reset_n) begin 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 + 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 diff --git a/i2s_sender.v b/i2s_sender.v index 82b1802..8a42567 100644 --- a/i2s_sender.v +++ b/i2s_sender.v @@ -70,7 +70,7 @@ always@(posedge mclk, posedge reset_n) begin 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 (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 diff --git a/i2s_transceiver.v b/i2s_transceiver.v deleted file mode 100644 index 8d5cd9a..0000000 --- a/i2s_transceiver.v +++ /dev/null @@ -1,124 +0,0 @@ -// 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_transceiver #( 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 sd_tx, //serial data transmit - 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 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] 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 = '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 - 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 <= '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 - 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 - - 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 - r_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 - r_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 -// 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 - 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 -//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 ; - -endmodule \ No newline at end of file diff --git a/i2s_transceiver_tb.v b/i2s_transceiver_tb.v deleted file mode 100644 index a657d5b..0000000 --- a/i2s_transceiver_tb.v +++ /dev/null @@ -1,87 +0,0 @@ -// This file is Test Bench for top_vga_mem module -// -// - -// 100MHz clock on Basys3 -> 10ns period -// 50% duty cycle 5ns HIGH and 5ns LOW -//`timescale [time unit] / [time precision] -`timescale 10 ns / 1ns - - -//top module -`include "i2s_transceiver.v" - -module i2s_transceiver_tb#( parameter - sclk_ws_ratio = 48, // number of sclk periods per word select period - mclk_sclk_ratio = 4, // number of mclk periods per sclk period - d_width = 24 // data width -)(); - -reg clk = 1'b0; -reg reset_n = 0; -reg sd_rx = 0; -reg [d_width-1: 0] l_data_tx = 0; -reg [d_width-1: 0] r_data_tx = 0; - -wire sclk; -wire ws; -wire sd_tx; -wire [d_width-1: 0] l_data_rx; -wire [d_width-1: 0] r_data_rx; - -// 50% duty cycle clock -always #0.5 clk <= ~clk; - -always #4 sd_rx <= ~sd_rx; - -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 -) UUT( - .reset_n(reset_n), //asynchronous active low reset - .mclk(clk), //master clock - .sclk(sclk), //serial clock (or bit clock) - .ws(ws), //word select (or left-right clock) - .sd_tx(sd_tx), //serial data transmit - .sd_rx(sd_rx), //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 -); - - -initial begin - #0 - reset_n <= 0; -// #200 - l_data_tx = 'hbbbbbb; - r_data_tx = 'haaaaaa; -// #20 -// sd_rx = 'h1; -end - - - -initial begin - #3_000_000; - $display("*"); - - $display(" "); - $display("Use this command to open timing diagram:"); - $display("gtkwave -f wave.vcd"); - $display("----------------------------------------------"); - $finish(); -end - -initial - begin - $display(" "); - $display("----------------------------------------------"); - $display(" Starting Testbench..."); - $dumpfile("wave.vcd"); - $dumpvars(0); -end - -endmodule \ No newline at end of file