From c69d8b6ae5796c43566cfc26eca9b9912f02756c Mon Sep 17 00:00:00 2001 From: Imants Pulkstenis Date: Sun, 13 Oct 2019 17:00:57 +0300 Subject: [PATCH] i2s_transceiver update and testbench --- comands.v | 83 -------------------------------------------- debounce_switch.v | 5 +-- debounce_switch_tb.v | 58 +++++++++++++++++++++++++++++++ i2s_playback.v | 47 ------------------------- i2s_transceiver.v | 21 ++++++----- i2s_transceiver_tb.v | 81 ++++++++++++++++++++++++++++++++++++++++++ top.v | 2 +- 7 files changed, 155 insertions(+), 142 deletions(-) delete mode 100644 comands.v create mode 100644 debounce_switch_tb.v delete mode 100644 i2s_playback.v create mode 100644 i2s_transceiver_tb.v diff --git a/comands.v b/comands.v deleted file mode 100644 index 60a969d..0000000 --- a/comands.v +++ /dev/null @@ -1,83 +0,0 @@ -/* -////////////////////////////////////////////////////////////////// -// -// How do I use the Fully Open Source iCE40 Flow? -// Synthesis for iCE40 FPGAs can be done with Yosys. -// Place-and-route can be done with arachne-pnr. -// Here is an example script for implementing and -// programming the rot example from arachne-pnr -// (this example targets the iCEstick development board): -// -/////////////////////////////////////////////////////////////////// - - yosys -p "synth_ice40 -blif output.blif" blockram.v - arachne-pnr -d 1k -p output.pcf output.blif -o output.asc - icepack output.asc output.bin - iceprog output.bin - -A simple timing analysis report can be generated using the icetime -utility: - - icetime -tmd hx1k rot.asc - -/////////////////////////////////////////////////////////////// -For Go Board - - yosys -p "read_verilog blockram.v; synth_ice40 -blif output.blif" - arachne-pnr -d 1k -p constraints.pcf -P vq100 -o output.asc output.blif - icepack output.asc output.bin - icetime -d hx1k output.asc - iceprog output.bin - -*/ - -////////////////////////////////////////////////////////////////////// -// // -// Icarus Verilog // -// http://iverilog.wikia.com/wiki/Main_Page // -////////////////////////////////////////////////////////////////////// -/* - // Do this in your test bench - - always #1 r_Clock <= ~r_Clock; - - initial - begin - #2_000; - $finish(); - end - - initial - begin - $display(" "); - $display("----------------------------------------------"); - $display(" Starting Testbench..."); - $dumpfile("wave.vcd"); - $dumpvars(0); - $display("----------------------------------------------"); - $display(" "); - end - - -Code: - iverilog -o output.vvp clock_enable_tb.v - vvp output.vvp - gtkwave -f wave.vcd - -Or one line: -iverilog -o output.vvp top_tb.v && vvp output.vvp && gtkwave -f wave.vcd - - -*/ -///////////////////////////////////////////////////// -// -// Serial comunication: Linux -// -// stty -F /dev/ttyUSB1 115200 # set speed -// screen /dev/ttyUSB1 115200 # set spped -// -// -// minicom # -s ender setup screen -// # minicom can send file -//////////////////////////////////////////////////// - diff --git a/debounce_switch.v b/debounce_switch.v index 755565b..c3c32aa 100644 --- a/debounce_switch.v +++ b/debounce_switch.v @@ -3,10 +3,11 @@ module debounce_switch( input i_switch, output o_switch); - parameter c_debounce_limit=250000;// 10ms at 25MHz +// parameter c_debounce_limit=250000;// 2.5ms at 25MHz + parameter c_debounce_limit=1_000_000;// 10ms at 25MHz reg r_state=1'b0; -reg [17:0] r_count = 0; +reg [19:0] r_count = 0; always@(posedge clk)begin if (i_switch != r_state && r_count < c_debounce_limit) diff --git a/debounce_switch_tb.v b/debounce_switch_tb.v new file mode 100644 index 0000000..ab35c7c --- /dev/null +++ b/debounce_switch_tb.v @@ -0,0 +1,58 @@ +// 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 "debounce_switch.v" + +module debounce_switch_tb(); + +reg clk = 1'b0; +reg btnC = 0; +wire reset; + +// 50% duty cycle clock +always #0.5 clk <= ~clk; + +debounce_switch UUT( + .clk(clk), + .i_switch(btnC), + .o_switch(reset) +); + +initial begin + #20 btnC <= 1; + #40 btnC <= 0; + + #40 btnC <= 1; + #1_000_100 btnC <= 0; +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 diff --git a/i2s_playback.v b/i2s_playback.v deleted file mode 100644 index 50aeb6e..0000000 --- a/i2s_playback.v +++ /dev/null @@ -1,47 +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. - - - -module i2c_transceiver #( parameter - d_width = 24 // data width - mclk_sclk_ratio => 4, - sclk_ws_ratio => 64 -)( - input clock, // system clock (100 MHz on Basys board) - input reset_n, // active low asynchronous reset - output mclk, // master clock - output sclk, // serial clock (or bit clock) - output ws, // word select (or left-right clock) - input sd_rx, // serial data in - output sd_tx // serial data out - ); - - wire master_clk; //internal master clock signal - reg serial_clk = 0; //internal serial clock signal - reg word_select = 0; //internal word select signal - wire l_data_rx[d_width-1 : 0]; //left channel data received from I2S Transceiver component - wire r_data_rx[d_width-1 : 0]; //right channel data received from I2S Transceiver component - wire l_data_tx[d_width-1 : 0]; //left channel data to transmit using I2S Transceiver component - wire r_data_tx[d_width-1 : 0]; //right channel data to transmit using I2S Transceiver component - - -//declare PLL to create 11.29 MHz master clock from 100 MHz system clock -clk_wiz_0 clk_wiz_0( - .clk_in1(clock), - .clk_out1(master_clk) - ); - - - - -endmodule \ No newline at end of file diff --git a/i2s_transceiver.v b/i2s_transceiver.v index d4e70cc..c0e2cc9 100644 --- a/i2s_transceiver.v +++ b/i2s_transceiver.v @@ -16,6 +16,10 @@ // 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 @@ -46,19 +50,18 @@ reg [d_width-1: 0] r_data_tx_int = 0; //internal right channel tx data buffer reg r_sd_tx = 0; //internal register reg [d_width-1: 0] reg_r_data_rx = 0; reg [d_width-1: 0] reg_l_data_rx = 0; -reg [d_width-1: 0] reg_r_data_tx = 0; -reg [d_width-1: 0] reg_l_data_tx = 0; -reg sclk_cnt = 0; //counter of master clocks during half period of serial clock -reg ws_cnt = 0; //counter of serial clock toggles during half period of word select + +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@(mclk || reset_n) begin +always@(mclk , reset_n) begin if (reset_n == 0) begin - sclk_cnt <= 0; //clear mclk/sclk counter - ws_cnt <= 0; //clear sclk/ws counter + 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 <= 'b0; //clear internal left channel rx data buffer @@ -89,10 +92,10 @@ always@(mclk || reset_n) begin 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_rx_int <= {r_data_rx_int[d_width-2 : 0] , 0}; //shift data of right channel tx data buffer + 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_rx_int <= {l_data_rx_int[d_width-2 : 0] , 0}; //shift data of left channel tx data buffer + 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 diff --git a/i2s_transceiver_tb.v b/i2s_transceiver_tb.v new file mode 100644 index 0000000..6a3f3d0 --- /dev/null +++ b/i2s_transceiver_tb.v @@ -0,0 +1,81 @@ +// 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 = 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 +)(); + +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; + +i2s_transceiver 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 + #200 + reset_n <= 1; + #200 + l_data_tx = 'h2563; + r_data_tx = 'h1523; + #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 diff --git a/top.v b/top.v index 2306cd8..dd84d80 100644 --- a/top.v +++ b/top.v @@ -55,7 +55,7 @@ i2s_transceiver #( .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 low reset + .reset_n(~reset_n), //asynchronous active low reset .mclk(master_clk), //master clock .sclk(serial_clk), //serial clock (or bit clock) .ws(word_select), //word select (or left-right clock)