Skip to content

Commit 71fb640

Browse files
committed
drivers/ak4619: switch to ioregs on ice40 and ecp5
- This was previously never really necessary, and P&R would always create nice bitstreams, however it seems required to meet timings on more recent versions of oss-cad-suite.
1 parent 2d20a69 commit 71fb640

File tree

4 files changed

+45
-14
lines changed

4 files changed

+45
-14
lines changed

gateware/drivers/ak4619.sv

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,10 @@ always_ff @(posedge clk_256fs) begin
9393
// BICK transition HI -> LO: Clock in W bits
9494
// On HI -> LO both SDIN and SDOUT do not transition.
9595
// (determined by AK4619 transition polarity register BCKP)
96-
if (bit_counter < W) begin
97-
adc_words[channel][W - bit_counter - 1] <= sdout1;
96+
//
97+
// 1-bit offset comes from IO reg on sdout1 pin (1 cycle delay)
98+
if ((bit_counter > 0) && (bit_counter <= W)) begin
99+
adc_words[channel][W - bit_counter] <= sdout1;
98100
end
99101
clkdiv <= clkdiv + 1;
100102
end else begin // BICK: LO -> HI

gateware/sim/ak4619/tb_ak4619.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ async def strobe():
3939
dut.rst.value = 0
4040

4141
cocotb.start_soon(strobe())
42-
await i2s_clock_out_u32(dut.bick, dut.sdout1, TEST_L0)
43-
await i2s_clock_out_u32(dut.bick, dut.sdout1, TEST_R0)
44-
await i2s_clock_out_u32(dut.bick, dut.sdout1, TEST_L1)
45-
await i2s_clock_out_u32(dut.bick, dut.sdout1, TEST_R1)
42+
await i2s_clock_out_u32(dut.bick, dut.sdout1, TEST_L0, ioreg_delay=True)
43+
await i2s_clock_out_u32(dut.bick, dut.sdout1, TEST_R0, ioreg_delay=True)
44+
await i2s_clock_out_u32(dut.bick, dut.sdout1, TEST_L1, ioreg_delay=True)
45+
await i2s_clock_out_u32(dut.bick, dut.sdout1, TEST_R1, ioreg_delay=True)
4646

4747
await FallingEdge(dut.strobe)
4848

gateware/sim/util/i2s.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,18 @@
44
from cocotb.triggers import Timer, FallingEdge, RisingEdge, ClockCycles
55
from cocotb.handle import Force, Release
66

7-
async def i2s_clock_out_u32(bick, sdout, word):
7+
async def i2s_clock_out_u32(bick, sdout, word, ioreg_delay=False):
88
"""Clock out a 32-bit word over I2S."""
9-
for i in range(32):
10-
await RisingEdge(bick)
11-
sdout.value = (word >> (0x1F-i)) & 1
9+
if ioreg_delay:
10+
sdout.value = (word >> 0x1F) & 1
11+
for i in range(32):
12+
await RisingEdge(bick)
13+
if i >= 2:
14+
sdout.value = (word >> (0x20-i)) & 1
15+
else:
16+
for i in range(32):
17+
await RisingEdge(bick)
18+
sdout.value = (word >> (0x1F-i)) & 1
1219

1320
async def i2s_clock_in_u32(bick, sdin):
1421
"""Clock in a 32-bit word over I2S."""

gateware/top.sv

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,12 @@ logic signed [W-1:0] debug_adc1;
8585
logic signed [W-1:0] debug_adc2;
8686
logic signed [W-1:0] debug_adc3;
8787

88+
// Internal signals for I2S interface (after IO regs).
89+
logic pmod_lrck_int;
90+
logic pmod_bick_int;
91+
logic pmod_sdin1_int;
92+
logic pmod_sdout1_int;
93+
8894
// PLL bringup and reset state management / debouncing.
8995
sysmgr sysmgr_instance (
9096
`ifndef INTERNAL_CLOCK
@@ -147,13 +153,29 @@ TRELLIS_IO #(.DIR("BIDIR")) i2c_tristate_sda (
147153
.B(PMOD_I2C_SDA),
148154
.O(i2c_sda_i)
149155
);
156+
// ECP5 IO regs for I2S signals.
157+
OFS1P3DX ofs_bick (.D(pmod_bick_int), .SP(1'b1), .SCLK(clk_256fs), .CD(1'b0), .Q(PMOD_BICK));
158+
OFS1P3DX ofs_lrck (.D(pmod_lrck_int), .SP(1'b1), .SCLK(clk_256fs), .CD(1'b0), .Q(PMOD_LRCK));
159+
OFS1P3DX ofs_sdin1 (.D(pmod_sdin1_int), .SP(1'b1), .SCLK(clk_256fs), .CD(1'b0), .Q(PMOD_SDIN1));
160+
IFS1P3DX ifs_sdout1 (.D(PMOD_SDOUT1), .SP(1'b1), .SCLK(clk_256fs), .CD(1'b0), .Q(pmod_sdout1_int));
150161
`endif
151162
`else
152163
// For iCE40 this is not necessary.
153164
assign PMOD_I2C_SCL = i2c_scl_oe ? 1'b0 : 1'bz;
154165
assign PMOD_I2C_SDA = i2c_sda_oe ? 1'b0 : 1'bz;
155166
assign i2c_scl_i = PMOD_I2C_SCL;
156167
assign i2c_sda_i = PMOD_I2C_SDA;
168+
`ifndef VERILATOR_LINT_ONLY
169+
// ICE40 IO regs for I2S signals.
170+
SB_IO #(.PIN_TYPE(6'b110101)) sb_io_bick (
171+
.PACKAGE_PIN(PMOD_BICK), .OUTPUT_CLK(clk_256fs), .D_OUT_0(pmod_bick_int), .OUTPUT_ENABLE(1'b1));
172+
SB_IO #(.PIN_TYPE(6'b110101)) sb_io_lrck (
173+
.PACKAGE_PIN(PMOD_LRCK), .OUTPUT_CLK(clk_256fs), .D_OUT_0(pmod_lrck_int), .OUTPUT_ENABLE(1'b1));
174+
SB_IO #(.PIN_TYPE(6'b110101)) sb_io_sdin1 (
175+
.PACKAGE_PIN(PMOD_SDIN1), .OUTPUT_CLK(clk_256fs), .D_OUT_0(pmod_sdin1_int), .OUTPUT_ENABLE(1'b1));
176+
SB_IO #(.PIN_TYPE(6'b000000)) sb_io_sdout1 (
177+
.PACKAGE_PIN(PMOD_SDOUT1), .INPUT_CLK(clk_256fs), .D_IN_0(pmod_sdout1_int));
178+
`endif
157179
`endif
158180

159181
eurorack_pmod #(
@@ -169,10 +191,10 @@ eurorack_pmod #(
169191
.i2c_sda_i (i2c_sda_i),
170192
.pdn (PMOD_PDN),
171193
.mclk (PMOD_MCLK),
172-
.sdin1 (PMOD_SDIN1),
173-
.sdout1 (PMOD_SDOUT1),
174-
.lrck (PMOD_LRCK),
175-
.bick (PMOD_BICK),
194+
.sdin1 (pmod_sdin1_int),
195+
.sdout1 (pmod_sdout1_int),
196+
.lrck (pmod_lrck_int),
197+
.bick (pmod_bick_int),
176198

177199
.cal_in0 (in0),
178200
.cal_in1 (in1),

0 commit comments

Comments
 (0)