I2S从机接收Verilog模块

Posted by 橙叶 on Sat, Jun 17, 2023

分享一个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


comments powered by Disqus