i2s_transceiver update and testbench

This commit is contained in:
Imants Pulkstenis
2019-10-13 17:00:57 +03:00
parent 957a2c5ae5
commit c69d8b6ae5
7 changed files with 155 additions and 142 deletions
-83
View File
@@ -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
////////////////////////////////////////////////////
+3 -2
View File
@@ -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)
+58
View File
@@ -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
-47
View File
@@ -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
+12 -9
View File
@@ -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
+81
View File
@@ -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
+1 -1
View File
@@ -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)