i2s_transceiver update and testbench
This commit is contained in:
@@ -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
@@ -3,10 +3,11 @@ module debounce_switch(
|
|||||||
input i_switch,
|
input i_switch,
|
||||||
output o_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 r_state=1'b0;
|
||||||
reg [17:0] r_count = 0;
|
reg [19:0] r_count = 0;
|
||||||
|
|
||||||
always@(posedge clk)begin
|
always@(posedge clk)begin
|
||||||
if (i_switch != r_state && r_count < c_debounce_limit)
|
if (i_switch != r_state && r_count < c_debounce_limit)
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
@@ -16,6 +16,10 @@
|
|||||||
// Table 1, Section 4.1 of the CS4344 Datasheet confirms this
|
// Table 1, Section 4.1 of the CS4344 Datasheet confirms this
|
||||||
// selection, listing 11.29 MHz as a common frequency
|
// selection, listing 11.29 MHz as a common frequency
|
||||||
// for the master clock when the LRCK is 44.1 kHz.
|
// for the master clock when the LRCK is 44.1 kHz.
|
||||||
|
//
|
||||||
|
// Module is created from sample provided by
|
||||||
|
// Digilent
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
module i2s_transceiver #( parameter
|
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 r_sd_tx = 0; //internal register
|
||||||
reg [d_width-1: 0] reg_r_data_rx = 0;
|
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_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
|
if (reset_n == 0) begin
|
||||||
sclk_cnt <= 0; //clear mclk/sclk counter
|
sclk_cnt <= 'b0; //clear mclk/sclk counter
|
||||||
ws_cnt <= 0; //clear sclk/ws counter
|
ws_cnt <= 'b0; //clear sclk/ws counter
|
||||||
sclk_int <= 0; //clear serial clock signal
|
sclk_int <= 0; //clear serial clock signal
|
||||||
ws_int <= 0; //clear word select signal
|
ws_int <= 0; //clear word select signal
|
||||||
l_data_rx_int <= 'b0; //clear internal left channel rx data buffer
|
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 (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
|
if (ws_int == 1) begin //right channel
|
||||||
r_sd_tx <= r_data_tx_int[d_width-1]; //transmit serial data bit
|
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
|
end else begin //left channel
|
||||||
r_sd_tx <= l_data_tx_int[d_width-1]; //ransmit serial data bit
|
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
|
end
|
||||||
end else begin //half period of ws
|
end else begin //half period of ws
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -55,7 +55,7 @@ i2s_transceiver #(
|
|||||||
.sclk_ws_ratio(sclk_ws_ratio), //number of sclk periods per word select period
|
.sclk_ws_ratio(sclk_ws_ratio), //number of sclk periods per word select period
|
||||||
.d_width(d_width) //data width
|
.d_width(d_width) //data width
|
||||||
) i2s_transceiver (
|
) i2s_transceiver (
|
||||||
.reset_n(reset_n), //asynchronous active low reset
|
.reset_n(~reset_n), //asynchronous active low reset
|
||||||
.mclk(master_clk), //master clock
|
.mclk(master_clk), //master clock
|
||||||
.sclk(serial_clk), //serial clock (or bit clock)
|
.sclk(serial_clk), //serial clock (or bit clock)
|
||||||
.ws(word_select), //word select (or left-right clock)
|
.ws(word_select), //word select (or left-right clock)
|
||||||
|
|||||||
Reference in New Issue
Block a user