Files
retroSoC/rtl/ip/serial/i2s_recv.sv
T
maksyuki 952b060a70 feat(tiny): integrate P6 shared IP and eight-channel DMA
Integrate RNG, CRC, WS2812, Crypto, I2S master and the SDIO private AXI owner on SAFE24. Preserve the 128 KiB main SRAM and six private Crypto macros, add product-specific DMA assignments and reject unsupported SDK operations.

Correct APB read strobes, I2S receive assembly and SDIO command timing, backpressure and descriptor retirement. Add pin-level workloads, source-bound evidence checks and publication/commercial consumer compatibility.

Validation of the final P6 worktree: 1726 pytest tests passed with one optional pypdf skip (exit 0, 4021.61 seconds; terminal session 36439). Both PDKs passed both RTL simulators, netlist boot and 38-macro binding checks. Shared formal, Mini compatibility and software/source quality gates passed.

Evidence remains attributed to the retained dirty-worktree snapshots based on b3b30a72cd under build/ics55-tiny-2026-10-12-11-50-2eb98c0e1fae/meta/tiny-r2-p6/. Timing is negative and warning observations are not promoted. This commit does not accept P6, qualify physical operation or enable P7.
2026-10-12 21:43:30 +08:00

124 lines
3.2 KiB
Systemverilog

// Copyright (c) 2023-2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
// retroSoC is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
module i2s_recv (
input logic clk_i,
input logic rst_n_i,
input logic sclk_pos_i,
input logic lrck_i,
input logic bitmode_i,
input logic adcdat_i,
output logic [23:0] data_o,
output logic done_o
);
logic s_lrck_dely_d, s_lrck_dely_q;
logic s_lrck_trg;
logic [4:0] s_bit_cnt_d, s_bit_cnt_q;
logic [4:0] s_bit_num;
logic s_done_d, s_done_q;
logic [23:0] s_recv_data_d, s_recv_data_q;
logic [23:0] s_data_d, s_data_q;
assign s_bit_num = bitmode_i ? 5'd23 : 5'd15;
assign data_o = s_data_q;
assign done_o = s_done_q;
assign s_lrck_trg = lrck_i ^ s_lrck_dely_q;
assign s_lrck_dely_d = lrck_i;
dffer #(
.DATA_WIDTH(1)
) u_lrck_dely_dffer (
.clk_i (clk_i),
.rst_n_i(rst_n_i),
.en_i (sclk_pos_i),
.dat_i (s_lrck_dely_d),
.dat_o (s_lrck_dely_q)
);
always_comb begin
s_bit_cnt_d = s_bit_cnt_q;
if (s_lrck_trg) s_bit_cnt_d = '0;
else if (s_bit_cnt_q < s_bit_num) begin
s_bit_cnt_d = s_bit_cnt_q + 1'b1;
end
end
dffer #(
.DATA_WIDTH(5)
) u_bit_cnt_dffer (
.clk_i (clk_i),
.rst_n_i(rst_n_i),
.en_i (sclk_pos_i),
.dat_i (s_bit_cnt_d),
.dat_o (s_bit_cnt_q)
);
always_comb begin
s_recv_data_d = s_recv_data_q;
if (s_lrck_trg) begin
s_recv_data_d = '0;
end else if (s_bit_cnt_q < s_bit_num) begin
if (bitmode_i) begin
s_recv_data_d[23:0] = {s_recv_data_q[22:0], adcdat_i};
end else begin
s_recv_data_d[23:16] = s_recv_data_q[23:16];
s_recv_data_d[15:0] = {s_recv_data_q[14:0], adcdat_i};
end
end
end
dffer #(
.DATA_WIDTH(24)
) u_recv_data_dffer (
.clk_i (clk_i),
.rst_n_i(rst_n_i),
.en_i (sclk_pos_i),
.dat_i (s_recv_data_d),
.dat_o (s_recv_data_q)
);
// I2S changes LRCK one bit before the next sample's MSB. The bit
// sampled on that transition is the current sample's LSB, not the next
// sample's first bit. Publish completion after data_o has captured it.
assign s_done_d = sclk_pos_i && s_lrck_trg;
dffr #(
.DATA_WIDTH(1)
) u_done_dffr (
.clk_i (clk_i),
.rst_n_i(rst_n_i),
.dat_i (s_done_d),
.dat_o (s_done_q)
);
always_comb begin
s_data_d = s_data_q;
if (s_lrck_trg) begin
if (bitmode_i) s_data_d = {s_recv_data_q[22:0], adcdat_i};
else s_data_d = {8'd0, s_recv_data_q[14:0], adcdat_i};
end
end
dffer #(
.DATA_WIDTH(24)
) u_data_dffer (
.clk_i (clk_i),
.rst_n_i(rst_n_i),
.en_i (sclk_pos_i),
.dat_i (s_data_d),
.dat_o (s_data_q)
);
endmodule