diff --git a/hardware/hdl/interfaces/i2s.sv b/hardware/hdl/interfaces/i2s.sv new file mode 100644 index 0000000..31d3685 --- /dev/null +++ b/hardware/hdl/interfaces/i2s.sv @@ -0,0 +1,419 @@ +/* +I2S Codec interface. + +Specifically written for the Analog Devices SSM2603. + +@param BIT_DEPTH: The bit depth of the codec. +@param MCLK_FREQ: The MCLK frequency used for the codec and interface. +@param BCLK_DIV: The number of MCLK cycles per BCLK cycle. +@param LRCLK_DIV: The number of BCLK cycles per LRCLK cycle. +*/ + +`begin_keywords "1800-2017" // Use SystemVerilog 2017 keywords +`default_nettype none + +module i2s +#( + parameter BIT_DEPTH = 24, + parameter MCLK_FREQ = 12_288_000, + parameter BCLK_DIV = 4, + parameter LRCLK_DIV = 64 +) +( + input wire rst_n, + + // i2s common + input wire mclk, + output logic bclk, + + // i2s rx + output logic rx, + output logic rx_lrclk, + output logic [BIT_DEPTH-1:0] rx_data, + input wire rx_ready, + output logic rx_valid, + + // i2s tx + output logic tx, + output logic tx_lrclk, + input logic [BIT_DEPTH-1:0] tx_data, + output logic tx_ready, + input wire tx_valid, + + // device specific //TODO: move to higher level module + output logic mute +); + timeunit 1ns; timeprecision 100ps; + +/* + * ============================================================================= + * local parameters + * ============================================================================= + */ + // general + localparam BUFFER_COUNTER_BITS = $clog2(BIT_DEPTH); + localparam WORD_LENGTH = LRCLK_DIV / 2; + + // clk dividers + localparam BCLK_COUNTER_BITS = $clog2(BCLK_DIV); + localparam LRCLK_COUNTER_BITS = $clog2(LRCLK_DIV); + + +/* + * ============================================================================= + * states + * ============================================================================= + */ + // I2S states + typedef enum logic [7:0] { + RESET = 8'b00000000, + IDLE = 8'b00000001, + LEFT_START = 8'b00000010, + LEFT = 8'b00000100, + LEFT_IDLE = 8'b00001000, + RIGHT_START = 8'b00010000, + RIGHT = 8'b00100000, + RIGHT_IDLE = 8'b01000000, + ERROR = 8'b10000000 + } i2s_state_t; + + +/* + * ============================================================================= + * bclk clk divider + * ============================================================================= + */ + logic [BCLK_COUNTER_BITS-1:0] bclk_counter; + + // bclk counter + initial bclk_counter = '0; + always_ff @( posedge mclk ) begin : _bclk_clk_counter + if (bclk_counter == '0) + bclk_counter <= (BCLK_COUNTER_BITS)'(LRCLK_DIV - 1); + else + bclk_counter <= bclk_counter - 1; + end + + // bclk_output + always_comb begin : _bclk_clk_divider + if (bclk_counter[BCLK_COUNTER_BITS-1:0] >= (BCLK_COUNTER_BITS)'(BCLK_DIV / 2)) + bclk = 0; + else + bclk = 1; + end + + // // TODO: synthesis difference between this and the block above + // always_ff @( posedge mclk ) begin : _bclk_clk_divider + // if (!rst_n) + // bclk <= 0; + // else if (bclk_counter[BCLK_COUNTER_BITS-1:0] >= (BCLK_COUNTER_BITS)'(BCLK_DIV / 2)) + // bclk <= 0; + // else + // bclk <= 1; + // end + + // inverted bclk output + logic bclk_inv; + always_comb begin : _bclk_inv_clk_divider + if (bclk_counter[BCLK_COUNTER_BITS-1:0] >= (BCLK_COUNTER_BITS)'(BCLK_DIV / 2)) + bclk_inv = 1; + else + bclk_inv = 0; + end + +/* + * ============================================================================= + * receive + * ============================================================================= + */ + + // internal rx variables + i2s_state_t rx_state, rx_next_state; + logic [BUFFER_COUNTER_BITS-1:0] rx_bit_counter; + logic rx_shift_en, rx_bit_counter_rst_n; + + // rx current state logic + initial rx_state = RESET; + always_ff @( posedge bclk ) begin : _rx_current_state_logic + if (!rst_n) + rx_state <= RESET; + else + rx_state <= rx_next_state; + end + + // rx next state logic + always_comb begin : _rx_next_state_logic + unique case (rx_state) + RESET: + rx_next_state = LEFT_START; + IDLE: + rx_next_state = LEFT_START; + LEFT_START: + if (rx_lrclk_counter == (LRCLK_COUNTER_BITS)'(LRCLK_DIV - 2)) + rx_next_state = LEFT; + LEFT: + if (rx_bit_counter == '0) + rx_next_state = LEFT_IDLE; + LEFT_IDLE: + if (rx_lrclk_counter == (LRCLK_COUNTER_BITS)'((LRCLK_DIV/2) - 1)) + rx_next_state = RIGHT_START; + RIGHT_START: + rx_next_state = RIGHT; + RIGHT: + if (rx_bit_counter == '0) + rx_next_state = RIGHT_IDLE; + RIGHT_IDLE: + if (rx_lrclk_counter == 0) + rx_next_state = LEFT_START; + ERROR: + rx_next_state = ERROR; + default: + rx_next_state = ERROR; // catch glitches + endcase + end + + // rx fsm outputs + always_comb begin : _rx_fsm_outputs + unique case (rx_state) + RESET, ERROR: begin + {rx_shift_en, rx_bit_counter_rst_n} = 2'b00; + {rx_lrclk_rst_n} = 1'b0; + {rx_valid} = 1'b0; + end + IDLE: begin + {rx_shift_en, rx_bit_counter_rst_n} = 2'b00; + {rx_lrclk_rst_n} = 1'b0; + {rx_valid} = 1'b0; + end + LEFT_START: begin + {rx_shift_en, rx_bit_counter_rst_n} = 2'b00; + {rx_lrclk_rst_n} = 1'b1; + {rx_valid} = 1'b1; // TODO: this will not be valid first sample after reset + end + LEFT: begin + {rx_shift_en, rx_bit_counter_rst_n} = 2'b11; + {rx_lrclk_rst_n} = 1'b1; + {rx_valid} = 1'b0; + end + LEFT_IDLE: begin + {rx_shift_en, rx_bit_counter_rst_n} = 2'b00; + {rx_lrclk_rst_n} = 1'b1; + {rx_valid} = 1'b1; + end + RIGHT_START: begin + {rx_shift_en, rx_bit_counter_rst_n} = 2'b00; + {rx_lrclk_rst_n} = 1'b1; + {rx_valid} = 1'b1; // TODO: this will not be valid first sample after reset + end + RIGHT: begin + {rx_shift_en, rx_bit_counter_rst_n} = 2'b11; + {rx_lrclk_rst_n} = 1'b1; + {rx_valid} = 1'b0; + end + RIGHT_IDLE: begin + {rx_shift_en, rx_bit_counter_rst_n} = 2'b00; + {rx_lrclk_rst_n} = 1'b1; + {rx_valid} = 1'b1; + end + default: begin + {rx_shift_en, rx_bit_counter_rst_n} = 2'b00; + {rx_lrclk_rst_n} = 1'b0; + {rx_valid} = 1'b0; + end + endcase + end + + // rx shift register + always_ff @( posedge bclk ) begin : _rx_shift_register + if (!rst_n) + rx_data <= '0; + else if (rx_shift_en) + rx_data <= {rx_data[BIT_DEPTH-2:0], rx}; // msb first + else + rx_data <= rx_data; + end + + // rx bit counter + always_ff @( posedge bclk ) begin : _rx_bit_counter + if (!rx_bit_counter_rst_n) + rx_bit_counter <= BIT_DEPTH - 1; + else if (rx_bit_counter == '0) + rx_bit_counter <= BIT_DEPTH - 1; + else + rx_bit_counter <= rx_bit_counter - 1; + end + + logic rx_lrclk_rst_n; + logic [LRCLK_COUNTER_BITS-1:0] rx_lrclk_counter; + + // rx lrclk counter + always_ff @( posedge bclk ) begin : _rx_lrclk_clk_counter + if (!rx_lrclk_rst_n) + rx_lrclk_counter <= 0; + else if (rx_lrclk_counter == '0) + rx_lrclk_counter <= (LRCLK_COUNTER_BITS)'(LRCLK_DIV - 1); + else + rx_lrclk_counter <= rx_lrclk_counter - 1; + end + + // rx lrclk output + always_comb begin : _rx_lrclk_clk_div + if (!rx_lrclk_rst_n) + rx_lrclk = 1; + else if (rx_lrclk_counter[LRCLK_COUNTER_BITS-1:0] >= (LRCLK_COUNTER_BITS)'(LRCLK_DIV / 2)) + rx_lrclk = 0; + else + rx_lrclk = 1; + end + + +/* + * ============================================================================= + * transmit + * ============================================================================= + */ + + // internal tx variables + i2s_state_t tx_state, tx_next_state; + logic [BUFFER_COUNTER_BITS-1:0] tx_bit_counter; + logic tx_shift_en, tx_bit_counter_rst_n; + + // tx current state logic + initial tx_state = RESET; + always_ff @( posedge bclk_inv ) begin : _tx_current_state_logic + if (!rst_n) + tx_state <= RESET; + else + tx_state <= tx_next_state; + end + + // tx next state logic + always_comb begin : _tx_next_state_logic + unique case (tx_state) + RESET: + tx_next_state = IDLE; + IDLE: + if (tx_valid) // TODO: may prevent state transition + tx_next_state = LEFT_START; + LEFT_START: + if (tx_lrclk_counter == (LRCLK_COUNTER_BITS)'(LRCLK_DIV - 2)) + tx_next_state = LEFT; + LEFT: + if (tx_bit_counter == '0) + tx_next_state = LEFT_IDLE; + LEFT_IDLE: + if ((tx_lrclk_counter == (LRCLK_COUNTER_BITS)'((LRCLK_DIV/2) - 1)) && tx_valid) // TODO: may prevent state transition + tx_next_state = RIGHT_START; + RIGHT_START: + tx_next_state = RIGHT; + RIGHT: + if (tx_bit_counter == '0) + tx_next_state = RIGHT_IDLE; + RIGHT_IDLE: + if ((tx_lrclk_counter == 0) && tx_ready) // TODO: may prevent state transition + tx_next_state = LEFT_START; + ERROR: + tx_next_state = ERROR; + default: + tx_next_state = ERROR; // catch glitches + endcase + end + + // tx fsm outputs + always_comb begin : _tx_fsm_outputs + unique case (tx_state) + RESET, ERROR: begin + {tx_shift_en, tx_bit_counter_rst_n} = 2'b00; + {tx_lrclk_rst_n} = 1'b0; + {tx_ready} = 1'b0; + end + IDLE: begin + {tx_shift_en, tx_bit_counter_rst_n} = 2'b00; + {tx_lrclk_rst_n} = 1'b0; + {tx_ready} = 1'b1; + end + LEFT_START: begin + {tx_shift_en, tx_bit_counter_rst_n} = 2'b00; + {tx_lrclk_rst_n} = 1'b1; + {tx_ready} = 1'b0; + end + LEFT: begin + {tx_shift_en, tx_bit_counter_rst_n} = 2'b11; + {tx_lrclk_rst_n} = 1'b1; + {tx_ready} = 1'b0; + end + LEFT_IDLE: begin + {tx_shift_en, tx_bit_counter_rst_n} = 2'b00; + {tx_lrclk_rst_n} = 1'b1; + {tx_ready} = 1'b1; + end + RIGHT_START: begin + {tx_shift_en, tx_bit_counter_rst_n} = 2'b00; + {tx_lrclk_rst_n} = 1'b1; + {tx_ready} = 1'b0; + end + RIGHT: begin + {tx_shift_en, tx_bit_counter_rst_n} = 2'b11; + {tx_lrclk_rst_n} = 1'b1; + {tx_ready} = 1'b0; + end + RIGHT_IDLE: begin + {tx_shift_en, tx_bit_counter_rst_n} = 2'b00; + {tx_lrclk_rst_n} = 1'b1; + {tx_ready} = 1'b1; + end + default: begin + {tx_shift_en, tx_bit_counter_rst_n} = 2'b00; + {tx_lrclk_rst_n} = 1'b0; + {tx_ready} = 1'b0; + end + endcase + end + + // tx shift register + always_ff @( posedge bclk_inv ) begin : _tx_shift_register + if (!rst_n) + tx <= '0; + else if (tx_shift_en) + tx <= tx_data[tx_bit_counter]; // msb first + else + tx <= tx; + end + + // tx bit counter + always_ff @( posedge bclk_inv ) begin : _tx_bit_counter + if (!tx_bit_counter_rst_n) + tx_bit_counter <= BIT_DEPTH - 1; + else if (tx_bit_counter == '0) + tx_bit_counter <= BIT_DEPTH - 1; + else + tx_bit_counter <= tx_bit_counter - 1; + end + + logic tx_lrclk_rst_n; + logic [LRCLK_COUNTER_BITS-1:0] tx_lrclk_counter; + + // tx lrclk counter + always_ff @( posedge bclk ) begin : _tx_lrclk_clk_counter + if (!tx_lrclk_rst_n) + tx_lrclk_counter <= 0; + else if (tx_lrclk_counter == '0) + tx_lrclk_counter <= (LRCLK_COUNTER_BITS)'(LRCLK_DIV - 1); + else + tx_lrclk_counter <= tx_lrclk_counter - 1; + end + + // tx lrclk output + always_comb begin : _tx_lrclk_clk_div + if (!tx_lrclk_rst_n) + tx_lrclk = 1; + else if (tx_lrclk_counter[LRCLK_COUNTER_BITS-1:0] >= (LRCLK_COUNTER_BITS)'(LRCLK_DIV / 2)) + tx_lrclk = 0; + else + tx_lrclk = 1; + end + +endmodule : i2s + +`default_nettype wire +`end_keywords diff --git a/hardware/hdl/interfaces/uart.sv b/hardware/hdl/interfaces/uart.sv index c64235c..17ac30d 100644 --- a/hardware/hdl/interfaces/uart.sv +++ b/hardware/hdl/interfaces/uart.sv @@ -80,7 +80,7 @@ module uart /* * ======================================= - * Receive + * receive * ======================================= */ @@ -311,7 +311,7 @@ module uart else if (tx_next_state == TX_IDLE) // Potentially sketchy. Cycle steal to prevent glitches on tx tx <= '1; - else if (tx_state == TX_START) + else if (tx_state == TX_START) // TODO: should be able to put this in the fsm output block tx <= '0; else if (tx_shift_en) tx <= write_data[BUFFER_WIDTH - tx_bit_counter]; // lsb first diff --git a/hardware/makefile b/hardware/makefile index 2b5d3de..ffe3c68 100644 --- a/hardware/makefile +++ b/hardware/makefile @@ -37,12 +37,12 @@ include hdl/interfaces.mk # Test a module %.test: - ${PYTHON} -m pytest -v -o log_cli=True hardware/verif/py/$* + ${PYTHON} -m pytest -v -o log_cli=True verif/py/interfaces/test_$*.py # Test and display waveforms for a module #TODO: Add config directory for waveforms %.waves: - ${PYTHON} -m pytest -v -o log_cli=True hardware/verif/py/$* - ${SURFER} waves/$*.fst + ${PYTHON} -m pytest -v -o log_cli=True verif/py/interfaces/test_$*.py + ${SURFER} ../sim_build/$*/$*.fst -s waves/interfaces/$*.ron & # Generate a bitstream %.bit: ../scripts/synthesis_place_route.tcl $${%_TOP} $${_XDC} $${%_SRCS} $${%_DEPS} diff --git a/hardware/verif/py/interfaces/test_i2s.py b/hardware/verif/py/interfaces/test_i2s.py new file mode 100644 index 0000000..209f0f5 --- /dev/null +++ b/hardware/verif/py/interfaces/test_i2s.py @@ -0,0 +1,165 @@ +""" +Tests for I2S module. +""" + +import random +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import ClockCycles, RisingEdge, FallingEdge + +import hardware.verif.py.cocotb_runner + +from hardware.util.verif import repeat, parameterize + + +@cocotb.test() +@repeat(num_repeats=3) +async def i2s_random_receive(dut, bit_depth: int = None): + """ + Test random receives with a I2S peripheral. + """ + # setup module parameters and variables + bit_depth = 24 + + # setup clock + clock_period_ns = int(1e9 / 12e6) + clock = Clock(signal=dut.mclk, period=clock_period_ns, units="ns") + await cocotb.start(clock.start()) + + # setup inputs + dut.rx.value = 0 # I2S idle low + + # reset + dut.rst_n.value = 0 + await ClockCycles(signal=dut.bclk, num_cycles=2, rising=True) + dut.rst_n.value = 1 + + # await start of lrclk frame + await ClockCycles(signal=dut.rx_lrclk, num_cycles=1, rising=False) + # I2S typically starts shifting out on the second falling edge of bclk + # after falling edge of lrclk + await ClockCycles(signal=dut.bclk, num_cycles=3, rising=False) + + for sample in range(0, 4): + # receive bits + receive_data = random.randint(0, 2**bit_depth - 1) + for index in range(0, bit_depth): + dut.rx.value = (receive_data >> (bit_depth - index - 1)) & 0b1 + await ClockCycles(signal=dut.bclk, num_cycles=1, rising=False) + + # assert receive data, receive valid, and lrclk + assert dut.rx_data.value == receive_data + assert dut.rx_valid.value == 1 + + # pad rest of lrclk frame, assert lrclk + assert dut.rx_lrclk.value == sample % 2 + await ClockCycles(signal=dut.bclk, num_cycles=32 - bit_depth, rising=False) + + +@cocotb.test() +@repeat(num_repeats=3) +async def i2s_random_transmit(dut, bit_depth: int = None): + """ + Test random transmits with a I2S peripheral. + """ + # setup module parameters and variables + bit_depth = 24 + + # setup clock + clock_period_ns = int(1e9 / 12e6) + clock = Clock(signal=dut.mclk, period=clock_period_ns, units="ns") + await cocotb.start(clock.start()) + + # setup inputs + dut.tx_valid.value = 0 + + # reset + dut.rst_n.value = 0 + await ClockCycles(signal=dut.bclk, num_cycles=2, rising=True) + dut.rst_n.value = 1 + + # await for transmit_ready, continue if already high + if not dut.tx_ready.value: + await RisingEdge(signal=dut.tx_ready) + transmit_data = random.randint(0, 2**bit_depth - 1) + dut.tx_data.value = transmit_data + dut.tx_valid.value = 1 + + # await start of lrclk frame + await ClockCycles(signal=dut.tx_lrclk, num_cycles=1, rising=False) + # I2S typically starts shifting out on the second falling edge of bclk + # after falling edge of lrclk + await ClockCycles(signal=dut.bclk, num_cycles=2, rising=True) + + for sample in range(0, 4): + # transmit bits + for index in range(0, bit_depth): + await ClockCycles(signal=dut.bclk, num_cycles=1, rising=True) + assert dut.tx.value == (transmit_data >> (bit_depth - index - 1)) & 0b1 + + # pad rest of lrclk frame, assert lrclk + assert dut.tx_lrclk.value == sample % 2 + await ClockCycles(signal=dut.bclk, num_cycles=32 - bit_depth, rising=True) + + +@cocotb.test() +@repeat(num_repeats=3) +async def i2s_random_full_duplex(dut, bit_depth: int = None): + """ + Test random transmit and receives with a I2S main. + """ + # setup module parameters and variables + bit_depth = 24 + + # setup clock + clock_period_ns = int(1e9 / 12e6) + clock = Clock(signal=dut.mclk, period=clock_period_ns, units="ns") + await cocotb.start(clock.start()) + + # setup inputs + dut.rx.value = 0 # I2S idle low + dut.tx_valid.value = 0 + + # reset + dut.rst_n.value = 0 + await ClockCycles(signal=dut.bclk, num_cycles=2, rising=True) + dut.rst_n.value = 1 + + # await for transmit_ready, continue if already high + if not dut.tx_ready.value: + await RisingEdge(signal=dut.tx_ready) + transmit_data = random.randint(0, 2**bit_depth - 1) + dut.tx_data.value = transmit_data + dut.tx_valid.value = 1 + + # await start of lrclk frame + await ClockCycles(signal=dut.rx_lrclk, num_cycles=1, rising=False) + # I2S typically starts shifting out on the second falling edge of bclk + # after falling edge of lrclk + await ClockCycles(signal=dut.bclk, num_cycles=3, rising=False) # 3.0 + + for sample in range(0, 4): + # transmit and receive bits + receive_data = random.randint(0, 2**bit_depth - 1) + for index in range(0, bit_depth): + # apply rx value on falling edge + dut.rx.value = (receive_data >> (bit_depth - index - 1)) & 0b1 + + # assert tx value on rising edge + await ClockCycles(signal=dut.bclk, num_cycles=1, rising=True) + assert dut.tx.value == (transmit_data >> (bit_depth - index - 1)) & 0b1 + + # complete cycle + await ClockCycles(signal=dut.bclk, num_cycles=1, rising=False) + + # assert receive data, receive valid, and lrclk + assert dut.rx_data.value == receive_data + assert dut.rx_valid.value == 1 + + # pad rest of lrclk frame, assert lrclk + assert dut.rx_lrclk.value == sample % 2 + await ClockCycles(signal=dut.bclk, num_cycles=32 - bit_depth, rising=False) + + +def test_i2s(): + hardware.verif.py.cocotb_runner.run_cocotb(top="i2s", deps=[]) diff --git a/hardware/verif/py/interfaces/test_uart.py b/hardware/verif/py/interfaces/test_uart.py index c0f8eaf..4d102ee 100644 --- a/hardware/verif/py/interfaces/test_uart.py +++ b/hardware/verif/py/interfaces/test_uart.py @@ -1,5 +1,5 @@ """ -Test for UART module. +Tests for UART module. """ import random @@ -14,7 +14,7 @@ @cocotb.test() @repeat(num_repeats=10) -async def uart_random_read(dut, buffer_width: int = None): +async def uart_random_receive(dut, buffer_width: int = None): """ Test random reads with a UART main. """ @@ -65,7 +65,7 @@ async def uart_random_read(dut, buffer_width: int = None): @cocotb.test() @repeat(num_repeats=10) -async def uart_random_write(dut): +async def uart_random_transmit(dut): """ Test random writes with a UART main. """ diff --git a/hardware/waves/interfaces/i2s.ron b/hardware/waves/interfaces/i2s.ron new file mode 100644 index 0000000..66846b7 --- /dev/null +++ b/hardware/waves/interfaces/i2s.ron @@ -0,0 +1,843 @@ +( + show_hierarchy: None, + show_menu: None, + show_ticks: None, + show_toolbar: None, + show_tooltip: None, + show_scope_tooltip: None, + show_default_timeline: None, + show_overview: None, + show_statusbar: None, + align_names_right: None, + show_variable_indices: None, + show_variable_direction: None, + show_empty_scopes: None, + show_parameters_in_scopes: None, + highlight_focused: None, + waves: Some(( + source: File("../sim_build/i2s/i2s.fst"), + format: Fst, + active_scope: Some(WaveScope(( + strs: [ + "i2s", + ], + ))), + items_tree: ( + items: [ + ( + item_ref: (28), + level: 0, + unfolded: true, + selected: false, + ), + ( + item_ref: (27), + level: 0, + unfolded: true, + selected: false, + ), + ( + item_ref: (26), + level: 0, + unfolded: true, + selected: false, + ), + ( + item_ref: (23), + level: 0, + unfolded: true, + selected: false, + ), + ( + item_ref: (24), + level: 0, + unfolded: true, + selected: false, + ), + ( + item_ref: (21), + level: 0, + unfolded: true, + selected: false, + ), + ( + item_ref: (32), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (29), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (37), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (40), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (33), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (69), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (34), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (39), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (36), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (38), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (31), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (30), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (35), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (22), + level: 0, + unfolded: true, + selected: false, + ), + ( + item_ref: (86), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (73), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (81), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (87), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (88), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (80), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (82), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (77), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (85), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (89), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (75), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (74), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (79), + level: 1, + unfolded: true, + selected: false, + ), + ( + item_ref: (78), + level: 1, + unfolded: true, + selected: false, + ), + ], + ), + displayed_items: { + (38): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "rx_shift_en", + ), + color: None, + background_color: None, + display_name: "rx_shift_en", + display_name_type: Unique, + manual_name: None, + format: None, + field_formats: [], + )), + (87): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "tx_valid", + ), + color: None, + background_color: None, + display_name: "tx_valid", + display_name_type: Unique, + manual_name: None, + format: None, + field_formats: [], + )), + (69): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "bclk", + ), + color: None, + background_color: None, + display_name: "bclk", + display_name_type: Unique, + manual_name: None, + format: None, + field_formats: [], + )), + (39): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "rx_state", + ), + color: None, + background_color: None, + display_name: "rx_state [7:0]", + display_name_type: Unique, + manual_name: None, + format: Some("Binary"), + field_formats: [], + )), + (30): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "rx_bit_counter", + ), + color: None, + background_color: None, + display_name: "rx_bit_counter [4:0]", + display_name_type: Unique, + manual_name: None, + format: Some("Unsigned"), + field_formats: [], + )), + (28): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "rst_n", + ), + color: None, + background_color: None, + display_name: "rst_n", + display_name_type: Unique, + manual_name: None, + format: None, + field_formats: [], + )), + (22): Group(( + name: "transmit", + color: Some("Gray"), + background_color: Some("Gray"), + content: [], + is_open: false, + )), + (37): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "rx_ready", + ), + color: None, + background_color: None, + display_name: "rx_ready", + display_name_type: Unique, + manual_name: None, + format: None, + field_formats: [], + )), + (85): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "bclk", + ), + color: None, + background_color: None, + display_name: "bclk", + display_name_type: Unique, + manual_name: None, + format: None, + field_formats: [], + )), + (21): Group(( + name: "receive", + color: Some("Gray"), + background_color: Some("Gray"), + content: [], + is_open: false, + )), + (79): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "tx_lrclk_rst_n", + ), + color: None, + background_color: None, + display_name: "tx_lrclk_rst_n", + display_name_type: Unique, + manual_name: None, + format: None, + field_formats: [], + )), + (40): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "rx_valid", + ), + color: None, + background_color: None, + display_name: "rx_valid", + display_name_type: Unique, + manual_name: None, + format: None, + field_formats: [], + )), + (35): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "rx_lrclk_rst_n", + ), + color: None, + background_color: None, + display_name: "rx_lrclk_rst_n", + display_name_type: Unique, + manual_name: None, + format: None, + field_formats: [], + )), + (34): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "rx_lrclk_counter", + ), + color: None, + background_color: None, + display_name: "rx_lrclk_counter [5:0]", + display_name_type: Unique, + manual_name: None, + format: Some("Unsigned"), + field_formats: [], + )), + (89): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "bclk_inv", + ), + color: None, + background_color: None, + display_name: "bclk_inv", + display_name_type: Unique, + manual_name: None, + format: None, + field_formats: [], + )), + (81): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "tx_ready", + ), + color: None, + background_color: None, + display_name: "tx_ready", + display_name_type: Unique, + manual_name: None, + format: None, + field_formats: [], + )), + (26): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "mclk", + ), + color: None, + background_color: None, + display_name: "mclk", + display_name_type: Unique, + manual_name: None, + format: None, + field_formats: [], + )), + (29): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "rx", + ), + color: None, + background_color: None, + display_name: "rx", + display_name_type: Unique, + manual_name: None, + format: None, + field_formats: [], + )), + (86): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "tx_data", + ), + color: None, + background_color: None, + display_name: "tx_data [23:0]", + display_name_type: Unique, + manual_name: None, + format: None, + field_formats: [], + )), + (24): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "bclk_counter", + ), + color: None, + background_color: None, + display_name: "bclk_counter [1:0]", + display_name_type: Unique, + manual_name: None, + format: None, + field_formats: [], + )), + (36): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "rx_next_state", + ), + color: None, + background_color: None, + display_name: "rx_next_state [7:0]", + display_name_type: Unique, + manual_name: None, + format: Some("Binary"), + field_formats: [], + )), + (23): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "bclk", + ), + color: None, + background_color: None, + display_name: "bclk", + display_name_type: Unique, + manual_name: None, + format: None, + field_formats: [], + )), + (73): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "tx", + ), + color: None, + background_color: None, + display_name: "tx", + display_name_type: Unique, + manual_name: None, + format: None, + field_formats: [], + )), + (32): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "rx_data", + ), + color: None, + background_color: None, + display_name: "rx_data [23:0]", + display_name_type: Unique, + manual_name: None, + format: Some("Binary"), + field_formats: [], + )), + (82): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "tx_shift_en", + ), + color: None, + background_color: None, + display_name: "tx_shift_en", + display_name_type: Unique, + manual_name: None, + format: None, + field_formats: [], + )), + (31): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "rx_bit_counter_rst_n", + ), + color: None, + background_color: None, + display_name: "rx_bit_counter_rst_n", + display_name_type: Unique, + manual_name: None, + format: None, + field_formats: [], + )), + (80): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "tx_next_state", + ), + color: None, + background_color: None, + display_name: "tx_next_state [7:0]", + display_name_type: Unique, + manual_name: None, + format: Some("Binary"), + field_formats: [], + )), + (88): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "tx_state", + ), + color: None, + background_color: None, + display_name: "tx_state [7:0]", + display_name_type: Unique, + manual_name: None, + format: Some("Binary"), + field_formats: [], + )), + (27): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "mute", + ), + color: None, + background_color: None, + display_name: "mute", + display_name_type: Unique, + manual_name: None, + format: None, + field_formats: [], + )), + (77): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "tx_lrclk", + ), + color: None, + background_color: None, + display_name: "tx_lrclk", + display_name_type: Unique, + manual_name: None, + format: None, + field_formats: [], + )), + (75): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "tx_bit_counter_rst_n", + ), + color: None, + background_color: None, + display_name: "tx_bit_counter_rst_n", + display_name_type: Unique, + manual_name: None, + format: None, + field_formats: [], + )), + (33): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "rx_lrclk", + ), + color: None, + background_color: None, + display_name: "rx_lrclk", + display_name_type: Unique, + manual_name: None, + format: None, + field_formats: [], + )), + (74): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "tx_bit_counter", + ), + color: None, + background_color: None, + display_name: "tx_bit_counter [4:0]", + display_name_type: Unique, + manual_name: None, + format: Some("Unsigned"), + field_formats: [], + )), + (78): Variable(( + variable_ref: ( + path: ( + strs: [ + "i2s", + ], + ), + name: "tx_lrclk_counter", + ), + color: None, + background_color: None, + display_name: "tx_lrclk_counter [5:0]", + display_name_type: Unique, + manual_name: None, + format: Some("Unsigned"), + field_formats: [], + )), + }, + display_item_ref_counter: 89, + viewports: [ + ( + curr_left: (-0.2), + curr_right: (1.2), + target_left: (-0.2), + target_right: (1.2), + move_start_left: (-0.2), + move_start_right: (1.2), + move_duration: None, + move_strategy: Instant, + ), + ], + cursor: Some((1, [ + 8393, + ])), + markers: {}, + focused_item: Some((28)), + focused_transaction: (None, None), + default_variable_name_type: Unique, + scroll_offset: 0.0, + display_variable_indices: true, + graphics: {}, + )), + drag_started: false, + drag_source_idx: None, + drag_target_idx: Some(( + before: (28), + level: 1, + )), + previous_waves: None, + count: None, + blacklisted_translators: [], + show_about: false, + show_keys: false, + show_gestures: false, + show_quick_start: false, + show_license: false, + show_performance: false, + show_logs: false, + show_cursor_window: false, + wanted_timeunit: PicoSeconds, + time_string_format: None, + show_url_entry: false, + variable_name_filter_focused: false, + variable_name_filter_type: Fuzzy, + variable_name_filter_case_insensitive: true, + rename_target: None, + sidepanel_width: Some(100.0), + ui_zoom_factor: None, +) \ No newline at end of file