分享一个I2S从机接收的Verilog模块,用在了ZYNQ里,音频AD用的是WM87825,主模式24bit,I2S格式,工作得还比较稳定。
1`timescale 1ns / 1ps
2`define LEFT_CHANNEL 1'b0
3`define RIGHT_CHANNEL 1'b1
4
5`define FIRST_SIDE `LEFT_CHANNEL
6//////////////////////////////////////////////////////////////////////////////////
7// Company:
8// Engineer:
9//
10// Create Date: 2023/03/09 16:44:04
11// Design Name:
12// Module Name: i2s
13// Project Name:
14// Target Devices:
15// Tool Versions:
16// Description:
17//
18// Dependencies:
19//
20// Revision:
21// Revision 0.01 - File Created
22// Additional Comments:
23//
24//////////////////////////////////////////////////////////////////////////////////
25
26module i2s(
27 input sys_clk,
28 input rst_n,
29 input i2s_mclk,
30 input i2s_sdout,
31 input i2s_lrck,
32 input i2s_brck,
33 output reg ch_l_valid,
34 output reg ch_r_valid,
35 output data_valid,
36 output reg [23:0] ch_l_data,
37 output reg [23:0] ch_r_data
38);
39
40
41 reg[4:0] timer_cnt_buf = 5'b0;
42
43
44 reg [23:0] ch_l_data_buf;
45 reg [23:0] ch_r_data_buf;
46 reg [1:0] i2s_brck_buf;
47 reg [1:0] i2s_lrck_buf;
48
49 reg ch_lrck = 0;
50
51 reg i2s_brck_d;
52 always@(i2s_brck) begin
53 i2s_brck_d <= i2s_brck;
54 end
55
56 always@(posedge sys_clk or negedge rst_n)
57 begin
58 if(!rst_n)
59 begin
60 i2s_brck_buf <= 2'b00;
61 i2s_lrck_buf <= 2'b00;
62 end
63 else begin
64 if(i2s_brck_d == 1'b1) begin
65 i2s_brck_buf <= {i2s_brck_buf[0], 1'b1};
66 end
67 else begin
68 i2s_brck_buf <= {i2s_brck_buf[0], 1'b0};
69 end
70 //i2s_brck_buf <= {i2s_brck_buf[0], i2s_brck};
71
72
73 if(i2s_lrck == `LEFT_CHANNEL) begin
74 ch_lrck <= `LEFT_CHANNEL;
75 i2s_lrck_buf <= {i2s_lrck_buf[0], `LEFT_CHANNEL};
76 end
77 else begin
78 i2s_lrck_buf <= {i2s_lrck_buf[0], `RIGHT_CHANNEL};
79 ch_lrck <= `RIGHT_CHANNEL;
80 end
81 end
82 end
83
84 wire ch_brck, ch_brck_shift, lrch_reset, sample_reset;
85 assign ch_brck = (i2s_brck_buf == 2'b01);
86 assign ch_brck_shift = !ch_brck;
87 assign lrch_reset = (i2s_lrck_buf == 2'b01) || (i2s_lrck_buf == 2'b10);
88 assign sample_reset = ((i2s_lrck_buf == 2'b10));
89
90 always@(posedge lrch_reset or posedge ch_brck_shift or negedge rst_n )
91 begin
92 if(!rst_n) begin
93 timer_cnt_buf <= 5'h1f;
94 end
95 else if(lrch_reset == 1'b1) begin
96 timer_cnt_buf <= 5'b0;
97 end
98 else begin
99 if(ch_brck_shift == 1'b1) begin
100 timer_cnt_buf <= timer_cnt_buf + 1'b1;
101 end
102 else begin
103 timer_cnt_buf <= timer_cnt_buf;
104 end
105 end
106 end
107
108 always@(posedge ch_brck or negedge rst_n or posedge lrch_reset or posedge sample_reset)
109 begin
110 if(!rst_n)
111 begin
112 ch_l_data_buf <= 24'b0;
113 ch_r_data_buf <= 24'b0;
114
115 ch_r_valid <= 1'b0;
116 ch_l_valid <= 1'b0;
117
118 end
119 else if(lrch_reset == 1'b1)
120 begin
121 ch_l_data_buf <= ch_l_data_buf;
122 ch_r_data_buf <= ch_r_data_buf;
123
124
125 if(sample_reset == 1'b1)
126 begin
127 ch_r_valid <= 1'b0;
128 ch_l_valid <= 1'b0;
129 end
130 else begin
131 ch_r_valid <= ch_r_valid;
132 ch_l_valid <= ch_l_valid;
133 end
134 end
135 else
136 begin
137 if(timer_cnt_buf <= 5'd24 && timer_cnt_buf >= 5'd1)
138 begin
139 if(ch_lrck == `LEFT_CHANNEL)
140 begin
141 ch_l_data_buf <= {ch_l_data_buf[22:0], i2s_sdout};
142 ch_r_data_buf <= ch_r_data_buf;
143
144 ch_r_valid <= ch_r_valid;
145 ch_l_valid <= 1'b0;
146 end
147 else
148 begin
149 ch_r_data_buf <= {ch_r_data_buf[22:0], i2s_sdout};
150 ch_l_data_buf <= ch_l_data_buf;
151
152 ch_r_valid <= 1'b0;
153 ch_l_valid <= ch_l_valid;
154 end
155 end
156 else if(timer_cnt_buf > 5'd24)
157 begin
158 if(ch_lrck == `LEFT_CHANNEL)
159 begin
160 ch_l_valid <= 1'b1;
161 ch_r_valid <= 1'b0;
162 end
163 else begin
164 ch_l_valid <= ch_l_valid;
165 ch_r_valid <= 1'b1;
166 end
167
168 ch_l_data_buf <= ch_l_data_buf;
169 ch_r_data_buf <= ch_r_data_buf;
170 end
171 else
172 begin
173 ch_l_data_buf <= ch_l_data_buf;
174 ch_r_data_buf <= ch_r_data_buf;
175
176 ch_r_valid <= ch_r_valid;
177 ch_l_valid <= ch_l_valid;
178 end
179 end
180 end
181
182 wire sample_valid;
183 assign sample_valid = (ch_r_valid & ch_l_valid);
184 always@(posedge sample_valid or negedge rst_n)
185 begin
186 if(!rst_n) begin
187 ch_l_data <= 24'b0;
188 ch_r_data <= 24'b0;
189 end
190 else if(sample_valid == 1'b1)
191 begin
192 ch_l_data <= ch_l_data_buf;
193 ch_r_data <= ch_r_data_buf;
194 end
195 else
196 begin
197 ch_l_data <= ch_l_data;
198 ch_r_data <= ch_r_data;
199 end
200 end
201
202
203 assign data_valid = sample_valid;
204
205
206endmodule
207