mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-04 22:32:36 +00:00
12 files changed
+510
-296
No files matched your search
+9
-6
@@ -76,12 +76,13 @@
|
||||
#define reg_i2c0_status (*(volatile uint32_t*)0x1000601C)
|
||||
// i2s
|
||||
#define reg_i2s_mode (*(volatile uint32_t*)0x10007000)
|
||||
#define reg_i2s_upbound (*(volatile uint32_t*)0x10007004)
|
||||
#define reg_i2s_lowbound (*(volatile uint32_t*)0x10007008)
|
||||
#define reg_i2s_recven (*(volatile uint32_t*)0x1000700C)
|
||||
#define reg_i2s_txdata (*(volatile uint32_t*)0x10007010)
|
||||
#define reg_i2s_rxdata (*(volatile uint32_t*)0x10007014)
|
||||
#define reg_i2s_status (*(volatile uint32_t*)0x10007018)
|
||||
#define reg_i2s_format (*(volatile uint32_t*)0x10007004)
|
||||
#define reg_i2s_upbound (*(volatile uint32_t*)0x10007008)
|
||||
#define reg_i2s_lowbound (*(volatile uint32_t*)0x1000700C)
|
||||
#define reg_i2s_recven (*(volatile uint32_t*)0x10007010)
|
||||
#define reg_i2s_txdata (*(volatile uint32_t*)0x10007014)
|
||||
#define reg_i2s_rxdata (*(volatile uint32_t*)0x10007018)
|
||||
#define reg_i2s_status (*(volatile uint32_t*)0x1000701C)
|
||||
// 1-wire
|
||||
#define reg_onewire_clkdiv (*(volatile uint32_t*)0x10008000)
|
||||
#define reg_onewire_zerocnt (*(volatile uint32_t*)0x10008004)
|
||||
@@ -157,6 +158,8 @@
|
||||
#define reg_dvp_status (*(volatile uint32_t*)0x1000E008)
|
||||
// sdio
|
||||
#define reg_sdio_cfg (*(volatile uint32_t*)0x1000F000)
|
||||
// gpu
|
||||
#define reg_gpu_cfg (*(volatile uint32_t*)0x10010000)
|
||||
// apb
|
||||
// archinfo
|
||||
#define reg_archinfo_sys (*(volatile uint32_t*)0x20000000)
|
||||
|
||||
@@ -47,7 +47,7 @@ void app_info() {
|
||||
printf(" contributor: MrAMS <https://github.com/MrAMS>\n");
|
||||
printf(" license: MulanPSL-2.0 license\n\n");
|
||||
printf(" series: retroSoC Mini\n");
|
||||
printf(" specs: Gen2\n");
|
||||
printf(" specs: Gen2 Plus\n");
|
||||
printf(" version: %s(commit: %s)\n\n", RETROSOC_BRANCH, RETROSOC_COMMIT);
|
||||
|
||||
printf("User Processors:\n");
|
||||
@@ -107,6 +107,7 @@ void app_info() {
|
||||
printf(" 1 x SDRAM @0x%x\n", ®_sdram_clkdiv);
|
||||
printf(" 1 x DVP @0x%x\n", ®_dvp_recven);
|
||||
printf(" 1 x SDIO @0x%x\n", ®_sdio_cfg);
|
||||
printf(" 1 x GPU(mini) @0x%x\n", ®_gpu_cfg);
|
||||
printf(" 1 x ARCHINFO @0x%x\n", ®_archinfo_sys);
|
||||
printf(" 1 x RNG @0x%x\n", ®_rng_ctrl);
|
||||
printf(" 1 x UART1(ADV) @0x%x\n", ®_uart1_lcr);
|
||||
|
||||
+9
-7
@@ -18,6 +18,8 @@ void i2s_init(uint32_t mode) {
|
||||
}
|
||||
|
||||
void i2s_simp_test() {
|
||||
reg_i2s_mode = (uint32_t)1;
|
||||
reg_i2s_format = (uint32_t)0;
|
||||
for(uint32_t i = 0; i < 6; ++i) {
|
||||
// while(reg_i2s_status & (uint32_t)1); // check if fifo is full or not
|
||||
reg_i2s_txdata = test_data[i];
|
||||
@@ -25,14 +27,14 @@ void i2s_simp_test() {
|
||||
printf("i2s tx done\n");
|
||||
|
||||
reg_i2s_recven = (uint32_t)1;
|
||||
for(uint32_t i = 0; i < 6; ++i) {
|
||||
test_data[i] = reg_i2s_rxdata;
|
||||
uint32_t tmp = 0;
|
||||
for(uint32_t i = 0; i < 6; ) {
|
||||
tmp = reg_i2s_rxdata;
|
||||
if(tmp != 0) {
|
||||
printf("rx data: %x\n", tmp);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
reg_i2s_recven = (uint32_t)0;
|
||||
for(uint32_t i = 0; i < 6; ++i) {
|
||||
printf("test_data[%d]: %x\n", i, test_data[i]);
|
||||
}
|
||||
|
||||
printf("i2s rx done\n");
|
||||
}
|
||||
|
||||
|
||||
+27
-173
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2023-2025 Yuchi Miao <miaoyuchi@ict.ac.cn>
|
||||
// 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:
|
||||
@@ -8,18 +8,7 @@
|
||||
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
// See the Mulan PSL v2 for more details.
|
||||
|
||||
`ifndef NATV_I2S_DEF_SV
|
||||
`define NATV_I2S_DEF_SV
|
||||
|
||||
// verilog_format: off
|
||||
`define NATV_I2S_MODE 8'h00
|
||||
`define NATV_I2S_UPBOUND 8'h04
|
||||
`define NATV_I2S_LOWBOUND 8'h08
|
||||
`define NATV_I2S_RECVEN 8'h0C
|
||||
`define NATV_I2S_TXDATA 8'h10
|
||||
`define NATV_I2S_RXDATA 8'h14
|
||||
`define NATV_I2S_STATUS 8'h18
|
||||
// verilog_format: on
|
||||
`include "i2s_define.svh"
|
||||
|
||||
interface nv_i2s_if ();
|
||||
logic mclk_o;
|
||||
@@ -37,16 +26,14 @@ interface nv_i2s_if ();
|
||||
input adcdat_i,
|
||||
output irq_o
|
||||
);
|
||||
|
||||
endinterface
|
||||
|
||||
`endif
|
||||
|
||||
module nmi_i2s (
|
||||
// verilog_format: off
|
||||
input logic clk_i,
|
||||
input logic rst_n_i,
|
||||
input logic clk_aud_i ,
|
||||
input logic clk_aud_i,
|
||||
input logic rst_aud_n_i,
|
||||
output logic dma_tx_stall_o,
|
||||
output logic dma_rx_stall_o,
|
||||
@@ -55,20 +42,9 @@ module nmi_i2s (
|
||||
// verilog_format: on
|
||||
);
|
||||
|
||||
logic s_nmi_wr_hdshk, s_nmi_rd_hdshk;
|
||||
logic s_nmi_ready_d, s_nmi_ready_q;
|
||||
logic s_nmi_rdata_en;
|
||||
logic [31:0] s_nmi_rdata_d, s_nmi_rdata_q;
|
||||
|
||||
logic s_i2s_mode_en;
|
||||
logic s_i2s_mode_d, s_i2s_mode_q;
|
||||
logic s_i2s_upbound_en;
|
||||
logic [7:0] s_i2s_upbound_d, s_i2s_upbound_q;
|
||||
logic s_i2s_lowbound_en;
|
||||
logic [7:0] s_i2s_lowbound_d, s_i2s_lowbound_q;
|
||||
logic s_i2s_recven_en;
|
||||
logic s_i2s_recven_d, s_i2s_recven_q;
|
||||
logic [1:0] s_i2s_status_d, s_i2s_status_q;
|
||||
logic s_i2s_mode;
|
||||
logic [1:0] s_i2s_format;
|
||||
logic s_i2s_recven;
|
||||
// tx fifo
|
||||
logic s_tx_push_valid, s_tx_full, s_tx_empty;
|
||||
logic s_tx_pop_valid, s_tx_pop_ready;
|
||||
@@ -79,149 +55,25 @@ module nmi_i2s (
|
||||
logic s_rx_pop_valid, s_rx_pop_ready;
|
||||
logic [31:0] s_rx_push_data, s_rx_pop_data;
|
||||
logic [7:0] s_rx_elem_num;
|
||||
// common
|
||||
logic s_tx_fifo_stall_d, s_tx_fifo_stall_q;
|
||||
logic s_rx_fifo_stall_d, s_rx_fifo_stall_q;
|
||||
|
||||
assign s_nmi_wr_hdshk = nmi.valid && (~s_nmi_ready_q) && (|nmi.wstrb);
|
||||
assign s_nmi_rd_hdshk = nmi.valid && (~s_nmi_ready_q) && (~(|nmi.wstrb));
|
||||
assign nmi.ready = s_nmi_ready_q;
|
||||
assign nmi.rdata = s_nmi_rdata_q;
|
||||
|
||||
assign dma_tx_stall_o = s_tx_fifo_stall_q;
|
||||
assign dma_rx_stall_o = s_rx_fifo_stall_q;
|
||||
|
||||
assign s_i2s_mode_en = s_nmi_wr_hdshk && nmi.addr[7:0] == `NATV_I2S_MODE;
|
||||
assign s_i2s_mode_d = nmi.wdata[0];
|
||||
dffer #(1) u_i2s_mode_dffer (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_i2s_mode_en,
|
||||
s_i2s_mode_d,
|
||||
s_i2s_mode_q
|
||||
);
|
||||
|
||||
assign s_i2s_upbound_en = s_nmi_wr_hdshk && nmi.addr[7:0] == `NATV_I2S_UPBOUND;
|
||||
assign s_i2s_upbound_d = nmi.wdata[7:0];
|
||||
dfferh #(8) u_i2s_upbound_dfferh (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_i2s_upbound_en,
|
||||
s_i2s_upbound_d,
|
||||
s_i2s_upbound_q
|
||||
);
|
||||
|
||||
|
||||
assign s_i2s_lowbound_en = s_nmi_wr_hdshk && nmi.addr[7:0] == `NATV_I2S_LOWBOUND;
|
||||
assign s_i2s_lowbound_d = nmi.wdata[7:0];
|
||||
dffer #(8) u_i2s_lowbound_dffer (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_i2s_lowbound_en,
|
||||
s_i2s_lowbound_d,
|
||||
s_i2s_lowbound_q
|
||||
);
|
||||
|
||||
|
||||
assign s_i2s_recven_en = s_nmi_wr_hdshk && nmi.addr[7:0] == `NATV_I2S_RECVEN;
|
||||
assign s_i2s_recven_d = nmi.wdata[0];
|
||||
dffer #(1) u_i2s_recven_dffer (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_i2s_recven_en,
|
||||
s_i2s_recven_d,
|
||||
s_i2s_recven_q
|
||||
);
|
||||
|
||||
|
||||
always_comb begin
|
||||
s_tx_fifo_stall_d = s_tx_fifo_stall_q;
|
||||
if (~s_tx_fifo_stall_q && s_tx_elem_num > s_i2s_upbound_q) begin
|
||||
s_tx_fifo_stall_d = 1'b1;
|
||||
end else if (s_tx_fifo_stall_q && s_tx_elem_num < s_i2s_lowbound_q) begin
|
||||
s_tx_fifo_stall_d = 1'b0;
|
||||
end
|
||||
end
|
||||
dffr #(1) u_tx_fifo_stall_dffr (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_tx_fifo_stall_d,
|
||||
s_tx_fifo_stall_q
|
||||
);
|
||||
|
||||
|
||||
always_comb begin
|
||||
s_rx_fifo_stall_d = s_rx_fifo_stall_q;
|
||||
if (~s_rx_fifo_stall_q && s_rx_elem_num < s_i2s_lowbound_q) begin
|
||||
s_rx_fifo_stall_d = 1'b1;
|
||||
end else if (s_rx_fifo_stall_q && s_rx_elem_num > s_i2s_upbound_q) begin
|
||||
s_rx_fifo_stall_d = 1'b0;
|
||||
end
|
||||
end
|
||||
dffr #(1) u_rx_fifo_stall_dffr (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_rx_fifo_stall_d,
|
||||
s_rx_fifo_stall_q
|
||||
);
|
||||
|
||||
|
||||
// TODO: need to handle when tx fifo is full(DMA is fine)
|
||||
always_comb begin
|
||||
s_tx_push_valid = 1'b0;
|
||||
s_tx_push_data = '0;
|
||||
if (s_nmi_wr_hdshk && nmi.addr[7:0] == `NATV_I2S_TXDATA) begin
|
||||
s_tx_push_valid = 1'b1;
|
||||
if (nmi.wstrb[0]) s_tx_push_data[7:0] = nmi.wdata[7:0];
|
||||
if (nmi.wstrb[1]) s_tx_push_data[15:8] = nmi.wdata[15:8];
|
||||
if (nmi.wstrb[2]) s_tx_push_data[23:16] = nmi.wdata[23:16];
|
||||
if (nmi.wstrb[3]) s_tx_push_data[31:24] = nmi.wdata[31:24];
|
||||
end
|
||||
end
|
||||
|
||||
// [0] wr fifo full, [1] rd fifo empty
|
||||
always_comb begin
|
||||
s_i2s_status_d[0] = s_tx_full;
|
||||
s_i2s_status_d[1] = s_rx_empty;
|
||||
end
|
||||
dffr #(2) u_i2s_status_dffr (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_i2s_status_d,
|
||||
s_i2s_status_q
|
||||
);
|
||||
|
||||
assign s_nmi_ready_d = nmi.valid && (~s_nmi_ready_q);
|
||||
dffr #(1) u_nmi_ready_dffr (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_nmi_ready_d,
|
||||
s_nmi_ready_q
|
||||
);
|
||||
|
||||
assign s_nmi_rdata_en = s_nmi_rd_hdshk;
|
||||
always_comb begin
|
||||
s_rx_pop_valid = 1'b0;
|
||||
s_nmi_rdata_d = s_nmi_rdata_q;
|
||||
unique case (nmi.addr[7:0])
|
||||
`NATV_I2S_MODE: s_nmi_rdata_d = {31'd0, s_i2s_mode_q};
|
||||
`NATV_I2S_RXDATA: begin
|
||||
if (s_nmi_rd_hdshk) begin
|
||||
s_rx_pop_valid = 1'b1;
|
||||
if (!s_rx_empty) s_nmi_rdata_d = s_rx_pop_data;
|
||||
else s_nmi_rdata_d = '0;
|
||||
end
|
||||
end
|
||||
`NATV_I2S_STATUS: s_nmi_rdata_d = {30'd0, s_i2s_status_q};
|
||||
default: s_nmi_rdata_d = s_nmi_rdata_q;
|
||||
endcase
|
||||
end
|
||||
dffer #(32) u_nmi_rdata_dffer (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_nmi_rdata_en,
|
||||
s_nmi_rdata_d,
|
||||
s_nmi_rdata_q
|
||||
i2s_reg u_i2s_reg (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.nmi (nmi),
|
||||
.mode_o (s_i2s_mode),
|
||||
.format_o (s_i2s_format),
|
||||
.recven_o (s_i2s_recven),
|
||||
.tx_push_valid_o(s_tx_push_valid),
|
||||
.tx_push_data_o (s_tx_push_data),
|
||||
.tx_full_i (s_tx_full),
|
||||
.tx_elem_num_i (s_tx_elem_num),
|
||||
.rx_pop_valid_o (s_rx_pop_valid),
|
||||
.rx_pop_data_i (s_rx_pop_data),
|
||||
.rx_empty_i (s_rx_empty),
|
||||
.rx_elem_num_i (s_rx_elem_num),
|
||||
.dma_tx_stall_o (dma_tx_stall_o),
|
||||
.dma_rx_stall_o (dma_rx_stall_o)
|
||||
);
|
||||
|
||||
|
||||
@@ -249,7 +101,7 @@ module nmi_i2s (
|
||||
) u_rx_async_fifo (
|
||||
.wr_clk_i (clk_aud_i),
|
||||
.wr_rst_n_i(rst_aud_n_i),
|
||||
.wr_en_i (s_rx_push_valid & s_i2s_recven_q),
|
||||
.wr_en_i (s_rx_push_valid & s_i2s_recven),
|
||||
.wr_data_i (s_rx_push_data),
|
||||
.wr_full_o (s_rx_full),
|
||||
.rd_clk_i (clk_i),
|
||||
@@ -260,10 +112,12 @@ module nmi_i2s (
|
||||
.elem_num_o(s_rx_elem_num)
|
||||
);
|
||||
|
||||
|
||||
i2s_core u_i2s_core (
|
||||
.clk_i (clk_aud_i),
|
||||
.rst_n_i (rst_aud_n_i),
|
||||
.mode_i (s_i2s_mode_q),
|
||||
.mode_i (s_i2s_mode),
|
||||
.format_i (s_i2s_format),
|
||||
.tx_valid_o(s_tx_pop_valid),
|
||||
.tx_data_i (s_tx_pop_data),
|
||||
.tx_empty_i(s_tx_empty),
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
// 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.
|
||||
|
||||
`include "i2s_define.svh"
|
||||
|
||||
module i2s_clkgen (
|
||||
input logic clk_i,
|
||||
input logic rst_n_i,
|
||||
input logic [1:0] format_i,
|
||||
output logic sclk_pos_o,
|
||||
output logic sclk_fall_o,
|
||||
output logic sclk_o,
|
||||
output logic lrck_o
|
||||
);
|
||||
|
||||
logic [2:0] s_sclk_div_num;
|
||||
logic [2:0] s_sclk_div_cnt_d, s_sclk_div_cnt_q;
|
||||
logic s_sclk_d, s_sclk_q;
|
||||
logic [4:0] s_lrck_div_num;
|
||||
logic [4:0] s_lrck_div_cnt_d, s_lrck_div_cnt_q;
|
||||
logic s_lrck_d, s_lrck_q;
|
||||
|
||||
|
||||
assign sclk_pos_o = (~s_sclk_q) && (s_sclk_div_cnt_q == s_sclk_div_num);
|
||||
assign sclk_fall_o = s_sclk_q && (s_sclk_div_cnt_q == s_sclk_div_num);
|
||||
assign sclk_o = s_sclk_q;
|
||||
assign lrck_o = s_lrck_q;
|
||||
|
||||
|
||||
always_comb begin
|
||||
s_sclk_div_num = 3'd5;
|
||||
unique case (format_i)
|
||||
`I2S_16b_48K: s_sclk_div_num = 3'd5;
|
||||
`I2S_16b_96K: s_sclk_div_num = 3'd2;
|
||||
`I2S_24b_48K: s_sclk_div_num = 3'd3;
|
||||
`I2S_24b_96K: s_sclk_div_num = 3'd1;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
always_comb begin
|
||||
s_sclk_d = s_sclk_q;
|
||||
if (s_sclk_div_cnt_q == s_sclk_div_num) begin
|
||||
s_sclk_div_cnt_d = '0;
|
||||
s_sclk_d = ~s_sclk_q;
|
||||
end else begin
|
||||
s_sclk_div_cnt_d = s_sclk_div_cnt_q + 3'd1;
|
||||
end
|
||||
end
|
||||
dffr #(3) u_sclk_div_cnt_dffr (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_sclk_div_cnt_d,
|
||||
s_sclk_div_cnt_q
|
||||
);
|
||||
dffr #(1) u_sclk_dffr (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_sclk_d,
|
||||
s_sclk_q
|
||||
);
|
||||
|
||||
|
||||
always_comb begin
|
||||
s_lrck_div_num = 5'd15;
|
||||
unique case (format_i)
|
||||
`I2S_16b_48K: s_lrck_div_num = 5'd15;
|
||||
`I2S_16b_96K: s_lrck_div_num = 5'd15;
|
||||
`I2S_24b_48K: s_lrck_div_num = 5'd23;
|
||||
`I2S_24b_96K: s_lrck_div_num = 5'd23;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
always_comb begin
|
||||
s_lrck_d = s_lrck_q;
|
||||
if (s_lrck_div_cnt_q == s_lrck_div_num) begin
|
||||
s_lrck_div_cnt_d = '0;
|
||||
s_lrck_d = ~s_lrck_q;
|
||||
end else begin
|
||||
s_lrck_div_cnt_d = s_lrck_div_cnt_q + 5'd1;
|
||||
end
|
||||
end
|
||||
dffer #(5) u_lrck_div_cnt_dffer (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
sclk_fall_o,
|
||||
s_lrck_div_cnt_d,
|
||||
s_lrck_div_cnt_q
|
||||
);
|
||||
dffer #(1) u_lrck_dffer (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
sclk_fall_o,
|
||||
s_lrck_d,
|
||||
s_lrck_q
|
||||
);
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
+63
-84
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2023-2025 Yuchi Miao <miaoyuchi@ict.ac.cn>
|
||||
// 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:
|
||||
@@ -13,6 +13,7 @@ module i2s_core (
|
||||
input logic clk_i,
|
||||
input logic rst_n_i,
|
||||
input logic mode_i,
|
||||
input logic [1:0] format_i,
|
||||
output logic tx_valid_o,
|
||||
input logic [31:0] tx_data_i,
|
||||
input logic tx_empty_i,
|
||||
@@ -23,33 +24,38 @@ module i2s_core (
|
||||
// verilog_format: on
|
||||
);
|
||||
|
||||
// clk_i / 8 / 32
|
||||
logic [1:0] s_sclk_div_cnt_d, s_sclk_div_cnt_q;
|
||||
logic s_sclk_d, s_sclk_q;
|
||||
logic [3:0] s_lrck_div_cnt_d, s_lrck_div_cnt_q;
|
||||
logic s_lrck_d, s_lrck_q;
|
||||
// i2s clk
|
||||
logic s_sclk_pos, s_sclk_fall;
|
||||
logic [15:0] s_loopback_data;
|
||||
|
||||
logic [15:0] s_recv_data, s_send_data;
|
||||
logic [15:0] s_recv_data_d, s_recv_data_q;
|
||||
logic s_sclk, s_lrck;
|
||||
// common
|
||||
logic [23:0] s_loopback_data;
|
||||
logic [23:0] s_recv_data, s_send_data;
|
||||
logic [23:0] s_recv_data_d, s_recv_data_q;
|
||||
logic [31:0] s_send_data_d, s_send_data_q;
|
||||
logic s_recv_done, s_send_done;
|
||||
logic s_recv_done_pos, s_send_done_pos;
|
||||
logic s_recv_done_re, s_send_done_re;
|
||||
logic s_recv_cnt_d, s_recv_cnt_q;
|
||||
logic s_send_cnt_d, s_send_cnt_q;
|
||||
|
||||
// i2s
|
||||
assign i2s.mclk_o = clk_i;
|
||||
assign i2s.sclk_o = s_sclk;
|
||||
assign i2s.lrck_o = s_lrck;
|
||||
assign i2s.irq_o = '0;
|
||||
|
||||
|
||||
edge_det_sync_re u_recv_done_edge_det_sync_re (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_recv_done,
|
||||
s_recv_done_pos
|
||||
s_recv_done_re
|
||||
);
|
||||
|
||||
edge_det_sync_re u_send_done_edge_det_sync_re (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_send_done,
|
||||
s_send_done_pos
|
||||
s_send_done_re
|
||||
);
|
||||
|
||||
always_comb begin
|
||||
@@ -60,14 +66,22 @@ module i2s_core (
|
||||
s_recv_data_d = s_recv_data_q;
|
||||
if (!mode_i) s_loopback_data = s_recv_data;
|
||||
else begin
|
||||
if (s_recv_done_pos) begin
|
||||
if (~rx_full_i && s_recv_cnt_q == '1) begin
|
||||
if (s_recv_done_re) begin
|
||||
if (format_i[1]) begin
|
||||
s_recv_cnt_d = '0;
|
||||
rx_valid_o = 1'b1;
|
||||
rx_data_o = {s_recv_data, s_recv_data_q};
|
||||
if (~rx_full_i) begin
|
||||
rx_valid_o = 1'b1;
|
||||
rx_data_o = {8'd0, s_recv_data};
|
||||
end
|
||||
end else begin
|
||||
s_recv_cnt_d = s_recv_cnt_q + 1'b1;
|
||||
s_recv_data_d = s_recv_data;
|
||||
if (~rx_full_i && s_recv_cnt_q == 1'b1) begin
|
||||
s_recv_cnt_d = '0;
|
||||
rx_valid_o = 1'b1;
|
||||
rx_data_o = {s_recv_data[15:0], s_recv_data_q[15:0]};
|
||||
end else begin
|
||||
s_recv_cnt_d = s_recv_cnt_q + 1'b1;
|
||||
s_recv_data_d[15:0] = s_recv_data[15:0];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -78,7 +92,7 @@ module i2s_core (
|
||||
s_recv_cnt_d,
|
||||
s_recv_cnt_q
|
||||
);
|
||||
dffr #(16) u_recv_data_dffr (
|
||||
dffr #(24) u_recv_data_dffr (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_recv_data_d,
|
||||
@@ -92,16 +106,26 @@ module i2s_core (
|
||||
s_send_data_d = s_send_data_q;
|
||||
if (!mode_i) s_send_data = s_loopback_data;
|
||||
else begin
|
||||
s_send_data = s_send_data_q[15:0];
|
||||
if (s_send_done_pos) begin
|
||||
if (s_send_cnt_q == 1'b1) begin
|
||||
s_send_cnt_d = '0;
|
||||
s_send_data_d = {16'd0, s_send_data_q[31:16]};
|
||||
end else if (~tx_empty_i) begin
|
||||
if (format_i[1]) begin
|
||||
s_send_data = s_send_data_q[23:0];
|
||||
s_send_cnt_d = '0;
|
||||
if (s_send_done_re && (~tx_empty_i)) begin // NOTE:
|
||||
tx_valid_o = 1'b1;
|
||||
s_send_cnt_d = s_send_cnt_q + 1'b1;
|
||||
s_send_data_d = tx_data_i;
|
||||
end
|
||||
end else begin
|
||||
s_send_data[15:0] = s_send_data_q[15:0];
|
||||
if (s_send_done_re) begin
|
||||
if (s_send_cnt_q == 1'b1) begin
|
||||
s_send_cnt_d = '0;
|
||||
s_send_data_d = {16'd0, s_send_data_q[31:16]};
|
||||
end else if (~tx_empty_i) begin // NOTE:
|
||||
tx_valid_o = 1'b1;
|
||||
s_send_cnt_d = s_send_cnt_q + 1'b1;
|
||||
s_send_data_d = tx_data_i;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -119,59 +143,14 @@ module i2s_core (
|
||||
);
|
||||
|
||||
|
||||
assign i2s.mclk_o = clk_i;
|
||||
assign i2s.sclk_o = s_sclk_q;
|
||||
assign i2s.lrck_o = s_lrck_q;
|
||||
assign i2s.irq_o = '0;
|
||||
|
||||
assign s_sclk_pos = (~s_sclk_q) && (s_sclk_div_cnt_q == '0);
|
||||
assign s_sclk_fall = s_sclk_q && (s_sclk_div_cnt_q == '0);
|
||||
|
||||
always_comb begin
|
||||
s_sclk_d = s_sclk_q;
|
||||
if (s_sclk_div_cnt_q == '0) begin
|
||||
s_sclk_div_cnt_d = '1;
|
||||
s_sclk_d = ~s_sclk_q;
|
||||
end else begin
|
||||
s_sclk_div_cnt_d = s_sclk_div_cnt_q - 1'b1;
|
||||
end
|
||||
end
|
||||
dffrh #(2) u_sclk_div_cnt_dffrh (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_sclk_div_cnt_d,
|
||||
s_sclk_div_cnt_q
|
||||
);
|
||||
dffr #(1) u_sclk_dffr (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_sclk_d,
|
||||
s_sclk_q
|
||||
);
|
||||
|
||||
|
||||
always_comb begin
|
||||
s_lrck_d = s_lrck_q;
|
||||
if (s_lrck_div_cnt_q == '0) begin
|
||||
s_lrck_div_cnt_d = '1;
|
||||
s_lrck_d = ~s_lrck_q;
|
||||
end else begin
|
||||
s_lrck_div_cnt_d = s_lrck_div_cnt_q - 1'b1;
|
||||
end
|
||||
end
|
||||
dfferh #(4) u_lrck_div_cnt_dfferh (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_sclk_fall,
|
||||
s_lrck_div_cnt_d,
|
||||
s_lrck_div_cnt_q
|
||||
);
|
||||
dffer #(1) u_lrck_dffer (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_sclk_fall,
|
||||
s_lrck_d,
|
||||
s_lrck_q
|
||||
i2s_clkgen u_i2s_clkgen (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.format_i (format_i),
|
||||
.sclk_pos_o (s_sclk_pos),
|
||||
.sclk_fall_o(s_sclk_fall),
|
||||
.sclk_o (s_sclk),
|
||||
.lrck_o (s_lrck)
|
||||
);
|
||||
|
||||
|
||||
@@ -179,24 +158,24 @@ module i2s_core (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.sclk_pos_i(s_sclk_pos),
|
||||
.lrck_i (s_lrck_q),
|
||||
.lrck_i (s_lrck),
|
||||
.bitmode_i (format_i[1]),
|
||||
.adcdat_i (i2s.adcdat_i),
|
||||
.data_o (s_recv_data),
|
||||
.done_o (s_recv_done)
|
||||
);
|
||||
|
||||
|
||||
i2s_send u_i2s_send (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.sclk_pos_i (s_sclk_pos),
|
||||
.sclk_fall_i(s_sclk_fall),
|
||||
.lrck_i (s_lrck_q),
|
||||
.lrck_i (s_lrck),
|
||||
.bitmode_i (format_i[1]),
|
||||
.data_i (s_send_data),
|
||||
.dacdat_o (i2s.dacdat_o),
|
||||
.done_o (s_send_done)
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,30 @@
|
||||
// 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.
|
||||
|
||||
`ifndef NMI_I2S_DEF_SV
|
||||
`define NMI_I2S_DEF_SV
|
||||
|
||||
// verilog_format: off
|
||||
`define NMI_I2S_MODE 8'h00
|
||||
`define NMI_I2S_FORMAT 8'h04
|
||||
`define NMI_I2S_UPBOUND 8'h08
|
||||
`define NMI_I2S_LOWBOUND 8'h0C
|
||||
`define NMI_I2S_RECVEN 8'h10
|
||||
`define NMI_I2S_TXDATA 8'h14
|
||||
`define NMI_I2S_RXDATA 8'h18
|
||||
`define NMI_I2S_STATUS 8'h1C
|
||||
// verilog_format: on
|
||||
|
||||
`define I2S_16b_48K 2'd0
|
||||
`define I2S_16b_96K 2'd1
|
||||
`define I2S_24b_48K 2'd2
|
||||
`define I2S_24b_96K 2'd3
|
||||
|
||||
`endif
|
||||
+16
-11
@@ -13,8 +13,9 @@ module i2s_recv (
|
||||
input logic rst_n_i,
|
||||
input logic sclk_pos_i,
|
||||
input logic lrck_i,
|
||||
input logic bitmode_i,
|
||||
input logic adcdat_i,
|
||||
output logic [15:0] data_o,
|
||||
output logic [23:0] data_o,
|
||||
output logic done_o
|
||||
|
||||
);
|
||||
@@ -22,13 +23,17 @@ module i2s_recv (
|
||||
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 [15:0] s_recv_data_d, s_recv_data_q;
|
||||
logic [15:0] s_data_d, s_data_q;
|
||||
logic [4:0] s_bit_num;
|
||||
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_bit_cnt_q == 5'd15;
|
||||
assign done_o = s_bit_cnt_q == s_bit_num;
|
||||
assign s_lrck_trg = lrck_i ^ s_lrck_dely_q;
|
||||
|
||||
|
||||
assign s_lrck_dely_d = lrck_i;
|
||||
dffer #(1) u_lrck_dely_dffer (
|
||||
clk_i,
|
||||
@@ -39,11 +44,10 @@ module i2s_recv (
|
||||
);
|
||||
|
||||
|
||||
// 0-15
|
||||
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 < 5'd15) begin
|
||||
else if (s_bit_cnt_q < s_bit_num) begin
|
||||
s_bit_cnt_d = s_bit_cnt_q + 1'b1;
|
||||
end
|
||||
end
|
||||
@@ -58,11 +62,12 @@ module i2s_recv (
|
||||
|
||||
always_comb begin
|
||||
s_recv_data_d = s_recv_data_q;
|
||||
if (s_bit_cnt_q <= 5'd15) begin
|
||||
s_recv_data_d[15-s_bit_cnt_q] = adcdat_i;
|
||||
if (s_bit_cnt_q <= s_bit_num) begin
|
||||
if (bitmode_i) s_recv_data_d[5'd23-s_bit_cnt_q] = adcdat_i;
|
||||
else s_recv_data_d[5'd15-s_bit_cnt_q] = adcdat_i;
|
||||
end
|
||||
end
|
||||
dffer #(16) u_recv_data_dffer (
|
||||
dffer #(24) u_recv_data_dffer (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
sclk_pos_i,
|
||||
@@ -71,8 +76,8 @@ module i2s_recv (
|
||||
);
|
||||
|
||||
|
||||
assign s_data_d = s_bit_cnt_q == 5'd15 ? s_recv_data_d : s_data_q;
|
||||
dffer #(16) u_data_dffer (
|
||||
assign s_data_d = s_bit_cnt_q == s_bit_num ? s_recv_data_d : s_data_q;
|
||||
dffer #(24) u_data_dffer (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
sclk_pos_i,
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
// 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.
|
||||
|
||||
`include "i2s_define.svh"
|
||||
|
||||
module i2s_reg (
|
||||
// verilog_format: off
|
||||
input logic clk_i,
|
||||
input logic rst_n_i,
|
||||
nmi_if.slave nmi,
|
||||
output logic mode_o,
|
||||
output logic [ 1:0] format_o,
|
||||
output logic recven_o,
|
||||
output logic tx_push_valid_o,
|
||||
output logic [31:0] tx_push_data_o,
|
||||
input logic tx_full_i,
|
||||
input logic [ 7:0] tx_elem_num_i,
|
||||
output logic rx_pop_valid_o,
|
||||
input logic [31:0] rx_pop_data_i,
|
||||
input logic rx_empty_i,
|
||||
input logic [ 7:0] rx_elem_num_i,
|
||||
output logic dma_tx_stall_o,
|
||||
output logic dma_rx_stall_o
|
||||
// verilog_format: on
|
||||
);
|
||||
|
||||
// nmi
|
||||
logic s_nmi_wr_hdshk, s_nmi_rd_hdshk;
|
||||
logic s_nmi_ready_d, s_nmi_ready_q;
|
||||
logic s_nmi_rdata_en;
|
||||
logic [31:0] s_nmi_rdata_d, s_nmi_rdata_q;
|
||||
// register
|
||||
logic s_i2s_mode_en;
|
||||
logic s_i2s_mode_d, s_i2s_mode_q;
|
||||
logic s_i2s_format_en;
|
||||
logic [1:0] s_i2s_format_d, s_i2s_format_q;
|
||||
logic s_i2s_upbound_en;
|
||||
logic [7:0] s_i2s_upbound_d, s_i2s_upbound_q;
|
||||
logic s_i2s_lowbound_en;
|
||||
logic [7:0] s_i2s_lowbound_d, s_i2s_lowbound_q;
|
||||
logic s_i2s_recven_en;
|
||||
logic s_i2s_recven_d, s_i2s_recven_q;
|
||||
logic [1:0] s_i2s_status_d, s_i2s_status_q;
|
||||
// common
|
||||
logic s_tx_fifo_stall_d, s_tx_fifo_stall_q;
|
||||
logic s_rx_fifo_stall_d, s_rx_fifo_stall_q;
|
||||
|
||||
|
||||
// nmi
|
||||
assign s_nmi_wr_hdshk = nmi.valid && (~s_nmi_ready_q) && (|nmi.wstrb);
|
||||
assign s_nmi_rd_hdshk = nmi.valid && (~s_nmi_ready_q) && (~(|nmi.wstrb));
|
||||
assign nmi.ready = s_nmi_ready_q;
|
||||
assign nmi.rdata = s_nmi_rdata_q;
|
||||
// reg
|
||||
assign mode_o = s_i2s_mode_q;
|
||||
assign format_o = s_i2s_format_q;
|
||||
assign recven_o = s_i2s_recven_q;
|
||||
// dma
|
||||
assign dma_tx_stall_o = s_tx_fifo_stall_q;
|
||||
assign dma_rx_stall_o = s_rx_fifo_stall_q;
|
||||
|
||||
|
||||
assign s_i2s_mode_en = s_nmi_wr_hdshk && nmi.addr[7:0] == `NMI_I2S_MODE;
|
||||
assign s_i2s_mode_d = nmi.wdata[0];
|
||||
dffer #(1) u_i2s_mode_dffer (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_i2s_mode_en,
|
||||
s_i2s_mode_d,
|
||||
s_i2s_mode_q
|
||||
);
|
||||
|
||||
|
||||
assign s_i2s_format_en = s_nmi_wr_hdshk && nmi.addr[7:0] == `NMI_I2S_FORMAT;
|
||||
assign s_i2s_format_d = nmi.wdata[1:0];
|
||||
dffer #(2) u_i2s_format_dffer (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_i2s_format_en,
|
||||
s_i2s_format_d,
|
||||
s_i2s_format_q
|
||||
);
|
||||
|
||||
|
||||
assign s_i2s_upbound_en = s_nmi_wr_hdshk && nmi.addr[7:0] == `NMI_I2S_UPBOUND;
|
||||
assign s_i2s_upbound_d = nmi.wdata[7:0];
|
||||
dfferh #(8) u_i2s_upbound_dfferh (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_i2s_upbound_en,
|
||||
s_i2s_upbound_d,
|
||||
s_i2s_upbound_q
|
||||
);
|
||||
|
||||
|
||||
assign s_i2s_lowbound_en = s_nmi_wr_hdshk && nmi.addr[7:0] == `NMI_I2S_LOWBOUND;
|
||||
assign s_i2s_lowbound_d = nmi.wdata[7:0];
|
||||
dffer #(8) u_i2s_lowbound_dffer (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_i2s_lowbound_en,
|
||||
s_i2s_lowbound_d,
|
||||
s_i2s_lowbound_q
|
||||
);
|
||||
|
||||
|
||||
assign s_i2s_recven_en = s_nmi_wr_hdshk && nmi.addr[7:0] == `NMI_I2S_RECVEN;
|
||||
assign s_i2s_recven_d = nmi.wdata[0];
|
||||
dffer #(1) u_i2s_recven_dffer (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_i2s_recven_en,
|
||||
s_i2s_recven_d,
|
||||
s_i2s_recven_q
|
||||
);
|
||||
|
||||
|
||||
always_comb begin
|
||||
s_tx_fifo_stall_d = s_tx_fifo_stall_q;
|
||||
if (~s_tx_fifo_stall_q && tx_elem_num_i > s_i2s_upbound_q) begin
|
||||
s_tx_fifo_stall_d = 1'b1;
|
||||
end else if (s_tx_fifo_stall_q && tx_elem_num_i < s_i2s_lowbound_q) begin
|
||||
s_tx_fifo_stall_d = 1'b0;
|
||||
end
|
||||
end
|
||||
dffr #(1) u_tx_fifo_stall_dffr (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_tx_fifo_stall_d,
|
||||
s_tx_fifo_stall_q
|
||||
);
|
||||
|
||||
|
||||
always_comb begin
|
||||
s_rx_fifo_stall_d = s_rx_fifo_stall_q;
|
||||
if (~s_rx_fifo_stall_q && rx_elem_num_i < s_i2s_lowbound_q) begin
|
||||
s_rx_fifo_stall_d = 1'b1;
|
||||
end else if (s_rx_fifo_stall_q && rx_elem_num_i > s_i2s_upbound_q) begin
|
||||
s_rx_fifo_stall_d = 1'b0;
|
||||
end
|
||||
end
|
||||
dffr #(1) u_rx_fifo_stall_dffr (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_rx_fifo_stall_d,
|
||||
s_rx_fifo_stall_q
|
||||
);
|
||||
|
||||
|
||||
// TODO: need to handle when tx fifo is full(DMA is fine)
|
||||
always_comb begin
|
||||
tx_push_valid_o = 1'b0;
|
||||
tx_push_data_o = '0;
|
||||
if (s_nmi_wr_hdshk && nmi.addr[7:0] == `NMI_I2S_TXDATA) begin
|
||||
tx_push_valid_o = 1'b1;
|
||||
if (nmi.wstrb[0]) tx_push_data_o[7:0] = nmi.wdata[7:0];
|
||||
if (nmi.wstrb[1]) tx_push_data_o[15:8] = nmi.wdata[15:8];
|
||||
if (nmi.wstrb[2]) tx_push_data_o[23:16] = nmi.wdata[23:16];
|
||||
if (nmi.wstrb[3]) tx_push_data_o[31:24] = nmi.wdata[31:24];
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always_comb begin
|
||||
s_i2s_status_d[0] = tx_full_i;
|
||||
s_i2s_status_d[1] = rx_empty_i;
|
||||
end
|
||||
dffr #(2) u_i2s_status_dffr (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_i2s_status_d,
|
||||
s_i2s_status_q
|
||||
);
|
||||
|
||||
assign s_nmi_ready_d = nmi.valid && (~s_nmi_ready_q);
|
||||
dffr #(1) u_nmi_ready_dffr (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_nmi_ready_d,
|
||||
s_nmi_ready_q
|
||||
);
|
||||
|
||||
assign s_nmi_rdata_en = s_nmi_rd_hdshk;
|
||||
always_comb begin
|
||||
rx_pop_valid_o = 1'b0;
|
||||
s_nmi_rdata_d = s_nmi_rdata_q;
|
||||
unique case (nmi.addr[7:0])
|
||||
`NMI_I2S_MODE: s_nmi_rdata_d = {31'd0, s_i2s_mode_q};
|
||||
`NMI_I2S_FORMAT: s_nmi_rdata_d = {30'd0, s_i2s_format_q};
|
||||
`NMI_I2S_RXDATA: begin
|
||||
if (s_nmi_rd_hdshk) begin
|
||||
rx_pop_valid_o = 1'b1;
|
||||
if (!rx_empty_i) s_nmi_rdata_d = rx_pop_data_i;
|
||||
else s_nmi_rdata_d = '0;
|
||||
end
|
||||
end
|
||||
`NMI_I2S_STATUS: s_nmi_rdata_d = {30'd0, s_i2s_status_q};
|
||||
default: s_nmi_rdata_d = s_nmi_rdata_q;
|
||||
endcase
|
||||
end
|
||||
dffer #(32) u_nmi_rdata_dffer (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
s_nmi_rdata_en,
|
||||
s_nmi_rdata_d,
|
||||
s_nmi_rdata_q
|
||||
);
|
||||
|
||||
endmodule
|
||||
+23
-10
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2023-2025 Yuchi Miao <miaoyuchi@ict.ac.cn>
|
||||
// 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:
|
||||
@@ -14,7 +14,8 @@ module i2s_send (
|
||||
input logic sclk_pos_i,
|
||||
input logic sclk_fall_i,
|
||||
input logic lrck_i,
|
||||
input logic [15:0] data_i,
|
||||
input logic bitmode_i,
|
||||
input logic [23:0] data_i,
|
||||
output logic dacdat_o,
|
||||
output logic done_o
|
||||
);
|
||||
@@ -22,12 +23,16 @@ module i2s_send (
|
||||
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 [15:0] s_xfer_data_d, s_xfer_data_q;
|
||||
logic [4:0] s_bit_num;
|
||||
logic [23:0] s_xfer_data_d, s_xfer_data_q;
|
||||
logic s_dacdat_d, s_dacdat_q;
|
||||
|
||||
assign dacdat_o = s_dacdat_q;
|
||||
assign done_o = s_bit_cnt_q == 5'd15;
|
||||
|
||||
assign s_bit_num = bitmode_i ? 5'd23 : 5'd15;
|
||||
assign s_lrck_trg = lrck_i ^ s_lrck_dely_q;
|
||||
assign dacdat_o = s_dacdat_q;
|
||||
assign done_o = s_bit_cnt_q == s_bit_num;
|
||||
|
||||
|
||||
assign s_lrck_dely_d = lrck_i;
|
||||
dffer #(1) u_lrck_dely_dffer (
|
||||
@@ -38,12 +43,14 @@ module i2s_send (
|
||||
s_lrck_dely_q
|
||||
);
|
||||
|
||||
// 0-15
|
||||
|
||||
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 < 5'd15) begin
|
||||
s_bit_cnt_d = s_bit_cnt_q + 1'b1;
|
||||
else begin
|
||||
if (s_bit_cnt_q < s_bit_num) begin
|
||||
s_bit_cnt_d = s_bit_cnt_q + 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
dffer #(5) u_bit_cnt_dffer (
|
||||
@@ -56,7 +63,7 @@ module i2s_send (
|
||||
|
||||
|
||||
assign s_xfer_data_d = s_lrck_trg ? data_i : s_xfer_data_q;
|
||||
dffer #(16) u_xfer_data_dffer (
|
||||
dffer #(24) u_xfer_data_dffer (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
sclk_pos_i,
|
||||
@@ -65,7 +72,13 @@ module i2s_send (
|
||||
);
|
||||
|
||||
|
||||
assign s_dacdat_d = s_bit_cnt_q <= 5'd15 ? s_xfer_data_q[15-s_bit_cnt_q] : s_dacdat_q;
|
||||
always_comb begin
|
||||
s_dacdat_d = s_dacdat_q;
|
||||
if (s_bit_cnt_q <= s_bit_num) begin
|
||||
if (bitmode_i) s_dacdat_d = s_xfer_data_q[5'd23-s_bit_cnt_q];
|
||||
else s_dacdat_d = s_xfer_data_q[5'd15-s_bit_cnt_q];
|
||||
end
|
||||
end
|
||||
dffer #(1) u_dacdat_dffer (
|
||||
clk_i,
|
||||
rst_n_i,
|
||||
|
||||
@@ -52,6 +52,8 @@
|
||||
../../ip/native/spisd.sv
|
||||
../../ip/native/i2c_core.sv
|
||||
../../ip/native/i2c.sv
|
||||
../../ip/native/i2s_reg.sv
|
||||
../../ip/native/i2s_clkgen.sv
|
||||
../../ip/native/i2s_recv.sv
|
||||
../../ip/native/i2s_send.sv
|
||||
../../ip/native/i2s_core.sv
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
// `default_nettype none
|
||||
|
||||
module retrosoc_tb;
|
||||
localparam real XTAL_CPU_FREQ = 24.0; // MHz
|
||||
localparam real XTAL_CPU_FREQ = 24.0;
|
||||
localparam real EXT_CPU_FREQ = 72.0;
|
||||
localparam real AUD_CPU_FREQ = 12.288;
|
||||
localparam real AUD_CPU_FREQ = 18.432;
|
||||
|
||||
reg r_ext_clk;
|
||||
wire s_ext_clk;
|
||||
@@ -392,8 +392,8 @@ module retrosoc_tb;
|
||||
// #205541740;
|
||||
// #382928081;
|
||||
// #300000;
|
||||
// #45050000;
|
||||
#86869320;
|
||||
#45050000;
|
||||
// #86869320;
|
||||
// #21149063;
|
||||
// #1667652;
|
||||
// #327820116;
|
||||
|
||||
Reference in new issue
Block a user