J2-1 | 接続 | 説明 |
---|---|---|
113 | lrclk_i | LRCLK入力 |
115 | bclk_i | BCLK入力 |
119 | data_i | DATA入力 |
GND | ||
121 | ||
125 | ||
127 |
J5-2 | 接続 | 説明 |
---|---|---|
61 | lrclk_o | LRCLK出力(そのまま) |
GND | ||
58 | bclk_o | BCLK出力(そのまま) |
57 | data_o | DATA出力(そのまま) |
GND | ||
54 | datax | DATA出力(フィルタ処理後) |
52 |
BLOCK RESETPATHS ;
BLOCK ASYNCPATHS ;
LOCATE COMP "led[7]" SITE "107" ;
LOCATE COMP "led[6]" SITE "106" ;
LOCATE COMP "led[5]" SITE "105" ;
LOCATE COMP "led[4]" SITE "104" ;
LOCATE COMP "led[3]" SITE "100" ;
LOCATE COMP "led[2]" SITE "99" ;
LOCATE COMP "led[1]" SITE "98" ;
LOCATE COMP "led[0]" SITE "97" ;
LOCATE COMP "rst" SITE "1" ;
LOCATE COMP "clk" SITE "27" ;
LOCATE COMP "oscen" SITE "32" ;
LOCATE COMP "tx" SITE "74" ;
LOCATE COMP "rx" SITE "73" ;
LOCATE COMP "lrclk_i" SITE "113" ;
LOCATE COMP "bclk_i" SITE "115" ;
LOCATE COMP "data_i" SITE "119" ;
LOCATE COMP "lrclk_o" SITE "61" ;
LOCATE COMP "bclk_o" SITE "58" ;
LOCATE COMP "data_o" SITE "57" ;
LOCATE COMP "datax" SITE "54" ;
IOBUF ALLPORTS IO_TYPE=LVCMOS33 ;
module through (
input clk,
input rst,
output oscen,
output [7:0] led,
output tx,
input rx,
input lrclk_i,
input bclk_i,
input data_i,
output lrclk_o,
output bclk_o,
output data_o
);
assign led = 8'h55;;
assign oscen = 1;
assign tx = 1;
assign lrclk_o = lrclk_i;
assign bclk_o = bclk_i;
assign data_o = data_i;
endmodule
module through (
input clk,
input rst,
output oscen,
output [7:0] led,
output tx,
input rx,
input lrclk_i,
input bclk_i,
input data_i,
output lrclk_o,
output bclk_o,
output data_o
);
reg lrclk_last;
reg [7:0] count;
reg [7:0] count_last;
double_ff lrclk_ff (
.clk(clk),
.idata(lrclk_i),
.odata(lrclk_ix)
);
always @(posedge clk) begin
lrclk_last <= lrclk_ix;
end
always @(posedge clk or posedge rst) begin
if (rst) begin
count <= 0;
count_last <= 0;
end
else if (lrclk_last & ~lrclk_ix) begin
count_last <= count;
count <= 0;
end
else
count <= count+1;
end
assign led = ~count_last;
assign oscen = 1;
assign tx = 1;
assign lrclk_o = lrclk_i;
assign bclk_o = bclk_i;
assign data_o = data_i;
endmodule
module double_ff(
input clk,
input idata,
output odata
);
reg [1:0] sreg;
always @(posedge clk) begin
sreg <= {sreg[0], idata};
end
assign odata = sreg[1];
endmodule
方法 | 特徴 | 欠点 |
---|---|---|
1.外部クロック同期でI2S出力させて、データ処理後、I2Sクロックを生成し直す |
・水晶発振器の精度でクロックを生成できる
・回路的にはシンプルになり、伝送路の品質にも影響されない |
・サンプルレートを単純な分周で作れる周波数の発振器が必要12
・RaspberryPi標準で、外部クロック同期のI2S出力はできない13 |
2.I2S入力データをバッファに入れて、データ処理後、I2Sクロックを生成し直す |
・水晶発振器の精度でクロックを生成できる
・I2S入力のクロックの精度は不要 ・外部クロック同期が出来ない場合、例えばUSB Audioとかにも使えると思う |
・サンプルレートを単純な分周で作れる周波数の発振器が必要
・ある程度バッファに貯めてから、再生を開始する必要がある。十分なバッファ容量14が必要 |
3.I2SのLRCLKとBCLKをそのまま通過させ、そのクロックに同期して処理したデータを出力 |
・ほぼI2S入力のクロック精度のまま15で、出力可能
・これも外部クロック同期出来ない場合にも使える |
・データ終了後も、LRCLKとBCLKが供給される必要がある
・でも、RaspberryPiのI2S出力では、データ終了でLRCLKは停止、BCLKもすぐに停止する ・クロックが供給されないと、データの最後は尻切れになる ・サンプルレートを変更したい場合には使えない |
module through (
input clk,
input rst,
output oscen,
output [7:0] led,
output tx,
input rx,
input lrclk_i,
input bclk_i,
input data_i,
output lrclk_o,
output bclk_o,
output data_o,
output datax
);
reg bclk_last, lrclk_last;
reg [15:0] datai, datao;
reg [7:0] bcount;
double_ff lrclk_ff (clk,lrclk_i,lrclk_ix);
double_ff bclk_ff (clk,bclk_i,bclk_ix);
double_ff data_ff (clk,data_i,data_ix);
always @(posedge clk)
begin
bclk_last <= bclk_ix;
end
// ビットカウンタ
always @(posedge clk or posedge rst) begin
if (rst) begin
bcount <= 0;
lrclk_last <= 0;
end else if (~bclk_last & bclk_ix) begin
if (lrclk_last != lrclk_ix) begin
bcount <= 0;
lrclk_last <= lrclk_ix;
end else begin
bcount <= bcount+1;
lrclk_last <= lrclk_ix;
end
end
end
// データ取込み
always @(posedge clk or posedge rst) begin
if (rst) begin
datai <= 0;
end else if (~bclk_last & bclk_ix) begin
if (bcount == 15) begin
datao <= {datai[14:0],data_ix};
datai <= {datai[14:0],data_ix};
end else begin
datai <= {datai[14:0],data_ix};
end
end
end
assign led = 8'h55;
assign oscen = 1;
assign tx = 1;
assign lrclk_o = lrclk_i;
assign bclk_o = bclk_i;
assign data_o = data_i;
endmodule
// データ取込み
always @(posedge clk or posedge rst) begin
if (rst) begin
datai <= 0;
end else if (~bclk_last & bclk_ix) begin
datai <= {datai[14:0],data_ix};
end
end
// データ出力
always @(posedge clk or posedge rst) begin
if (rst) begin
datao <= 0;
end else if (~bclk_last & bclk_ix) begin
if (bcount == 0) begin
datao <= {datai[14:0],data_ix};
end else begin
datao <= {datao[14:0],datao[15]};
end
end else if (bclk_last & ~bclk_ix) begin
datax <= datao[15];
end
end
always @(posedge clk or posedge rst) begin
if (rst) begin
datao <= 0;
end else if (~bclk_last & bclk_ix) begin
if (bcount > 15) begin
datao <= 0;
end else if (bcount == 0) begin
datao <= {datai[14:0],data_ix};
end else begin
datao <= {datao[14:0],datao[15]};
end
end else if (bclk_last & ~bclk_ix) begin
datax <= datao[15];
end
end
// 入力データをL/R別に保存
reg [15:0] datal, datar;
always @(posedge clk or posedge rst) begin
if (rst) begin
datal <= 0;
datar <= 0;
end else if (~bclk_last & bclk_ix && bcount == 0) begin
if (~lrclk_ix) begin
datar <= datai;
end else begin
datal <= datai;
end
end
end
// 保存したデータを出力
always @(posedge clk or posedge rst) begin
if (rst) begin
datao <= 0;
end else if (~bclk_last & bclk_ix) begin
if (bcount > 15) begin
datao <= 0;
end else if (bcount != 15) begin
datao <= {datao[14:0],datao[15]};
end else if (~lrclk_ix) begin
datao <= datal;
end else begin
datao <= datar;
end
end else if (bclk_last & ~bclk_ix) begin
datax <= datao[15];
end
end
module rc_filter(
input clk,
input rst,
input enable,
input [15:0] idata,
output [15:0] odata
);
reg [15:0] data;
always @(posedge clk or posedge rst) begin
if (rst) data <= 0;
else if (enable) begin
data <= ( {data,5'b00000} - {{5{data[15]}},data} + {{5{idata[15]}},idata} ) >> 5;
// data <= idata; // そのまま通過させるテスト用
end
end
assign odata = data;
endmodule
wire [15:0] datal, datar;
rc_filter lfilter(
.clk(clk),
.rst(rst),
.enable(~bclk_last & bclk_ix && bcount == 0 && ~lrclk_ix),
.idata(datai),
.odata(datar)
);
rc_filter rfilter(
.clk(clk),
.rst(rst),
.enable(~bclk_last & bclk_ix && bcount == 0 && lrclk_ix),
.idata(datai),
.odata(datal)
);
( 0 * 31 -29128 ) / 32 = -910.25 → -911
( -911 * 31 +14563 ) / 32 = -427.4375 → -428
( 0 * 31 + 14563 ) / 32 = 455.09375 → 455
( 455 * 31 -7282 ) / 32 = 213.21875 → 213
( 213 * 31 -29128 ) / 32 = -703.90625 → -704
// データ出力
always @(posedge clk or posedge rst) begin
if (rst) begin
datao <= 0;
rstx <= 1;
end else if (~bclk_last & bclk_ix) begin
if (bcount > 15) begin
datao <= 0;
rstx <= 1;
end else if (bcount != 15) begin
datao <= {datao[14:0],datao[15]};
rstx <= 0;
end else if (~lrclk_ix) begin
datao <= datal;
end else begin
datao <= datar;
end
end else if (bclk_last & ~bclk_ix) begin
datax <= datao[15];
end
end
Channel | dout | datax | 計算値 |
---|---|---|---|
1 | 0 | 0 | 0 |
1 | 4652 | 0 | 0 |
1 | 9211 | 145 | 145.375 |
1 | 13582 | 428 | 428.3125 |
1 | 17679 | 839 | 839.0625 |
1 | 21417 | 1365 | 1365.25 |
1 | 24721 | 1991 | 1991.625 |
1 | 27525 | 2701 | 2701.3125 |
1 | 29770 | 3476 | 3476.75 |
1 | 31412 | 4297 | 4297.6875 |
1 | 32418 | 5144 | 5144.34375 |
1 | 32766 | 5996 | 5996.3125 |
1 | 32451 | 6832 | 6832.5625 |
1 | 31478 | 7632 | 7632.59375 |
1 | 29867 | 8377 | 8377.1875 |
1 | 27651 | 9048 | 9048.5625 |
1 | 24874 | 9629 | 9629.34375 |
1 | 21593 | 10105 | 10105.40625 |
1 | 17875 | 10464 | 10464 |
1 | 13795 | 10695 | 10695.59375 |
1 | 9434 | 10791 | 10791.875 |
1 | 4883 | 10748 | 10748.59375 |
1 | 233 | 10564 | 10564.71875 |
1 | -4421 | 10241 | 10241.15625 |
1 | -8986 | 9782 | 9782.8125 |
1 | -13370 | 9195 | 9195.5 |
: | : | : | : |
% tr -d \\r < dfil_rc.csv | cut -d ',' -f 3 | sed -e '1d' | idws 2 > dfil_rc.dat
% txt2wav -44100 dfil_rc.dat
% lame dfil_rc.wav dfil_rc.mp3
(1-a)/(1-a*exp(-j*omega*T));
subst(%i,j,%);
subst(2*%pi*f,omega,%);
subst(1/44100,T,%);
subst(31/32,a,%);
plot2d(cabs(%),[f,0,22050],[logy],[y,0.01,1]);
module mavg_filter(
input clk,
input rst,
input enable,
input [15:0] idata,
output [15:0] odata
);
reg [17:0] data[0:3];
reg [15:0] odata;
always @(posedge clk or posedge rst) begin
if (rst) begin
data[0] <= 0;
data[1] <= 0;
data[2] <= 0;
data[3] <= 0;
end else if (enable) begin
data[0] <= {{2{idata[15]}},idata};
data[1] <= data[0];
data[2] <= data[1];
data[3] <= data[2];
odata <= ( data[0]+data[1]+data[2]+data[3] ) >> 2;
// odata <= idata; // そのまま通過させるテスト用
end
end
endmodule
(1+exp(-j*omega*T)+exp(-2*j*omega*T)+exp(-3*j*omega*T))/4;
subst(%i,j,%);
subst(2*%pi*f,omega,%);
subst(1/44100,T,%);
plot2d(cabs(%),[f,0,22050],[logy],[y,0.01,1]);
FLEXlm not initialized.
`timescale 1ns / 1ps
module throgh_tb;
// Inputs
reg rx;
reg rst;
reg clk;
reg lrclk_i;
reg bclk_i;
reg data_i;
// Outputs
wire oscen;
wire tx;
wire [7:0] led;
wire lrclk_o;
wire bclk_o;
wire data_o;
through UUT (
.clk(clk),
.rst(rst),
.oscen(oscen),
.led(led),
.tx(tx),
.rx(rx),
.lrclk_i(lrclk_i),
.bclk_i(bclk_i),
.data_i(data_i),
.lrclk_o(lrclk_o),
.bclk_o(bclk_o),
.data_o(data_o)
);
parameter CYCLE = 32; // 1サイクルを64と定義する
always #(CYCLE) clk = ~clk; // クロック生成
always #(CYCLE*907) lrclk_i = ~lrclk_i;
always #(CYCLE*907/32) bclk_i = ~bclk_i;
always #(CYCLE*907/32*6) data_i = ~data_i;
initial begin
#0; // 初期化
rx = 1;
rst = 1;
clk = 0;
bclk_i = 0;
data_i = 0;
lrclk_i = 1;
#(CYCLE);
rst = 0; // リセット解除
#(CYCLE*5000);
$finish; // シミュレーション終了
end
endmodule