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,
|
||||
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)
|
||||
|
||||
@@ -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
|
||||
// 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
|
||||
|
||||
@@ -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
|
||||
.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)
|
||||
|
||||
Reference in New Issue
Block a user