From a71c9bed2a1acaac8877f9a70ab57c23d85bb674 Mon Sep 17 00:00:00 2001 From: Andrey Miroshnikov Date: Wed, 19 Jan 2022 00:04:12 +0000 Subject: [PATCH] Fixed issue with out/in not updating io. Now issue with address resetting... --- src/spec/simple_gpio.py | 73 ++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/src/spec/simple_gpio.py b/src/spec/simple_gpio.py index 1231952..40d548e 100644 --- a/src/spec/simple_gpio.py +++ b/src/spec/simple_gpio.py @@ -91,6 +91,9 @@ class SimpleGPIO(Elaboratable): pden_list = Array(list(pden)) puen_list = Array(list(puen)) + # Flag for indicating rd/wr transactions + new_transaction = Signal(1) + #print("Types:") #print("gpio_addr: ", type(gpio_addr)) #print("gpio_o_list: ", type(gpio_o_list)) @@ -100,32 +103,38 @@ class SimpleGPIO(Elaboratable): with m.If(bus.cyc & bus.stb): comb += wb_ack.eq(1) # always ack comb += gpio_addr.eq(bus.adr) + + sync += new_transaction.eq(1) with m.If(bus.we): # write # Configure CSR sync += csrbus.eq(wb_wr_data) with m.Else(): # read # Read the state of CSR bits - # Return state of input if ie - with m.If(gpio_ie_list[gpio_addr] == 1): - sync += csrbus.io.eq(gpio_i_list[gpio_addr]) - comb += wb_rd_data.eq(csrbus) - # Return state of out if oe - with m.Else(): - sync += csrbus.io.eq(gpio_o_list[gpio_addr]) - comb += wb_rd_data.eq(csrbus) - - # Combinatorial - comb += gpio_oe_list[gpio_addr].eq(csrbus.oe) - comb += gpio_ie_list[gpio_addr].eq(csrbus.ie) - # Check to prevent output being set if GPIO configured as input - # TODO: Is this necessary? PAD might deal with this - # check GPIO is in output mode and NOT input (oe high, ie low) - #with m.If(csrbus.oe & (~csrbus.ie)): - with m.If(gpio_oe_list[gpio_addr] & (~gpio_ie_list[gpio_addr])): - comb += gpio_o_list[gpio_addr].eq(csrbus.io) - comb += puen_list[gpio_addr].eq(csrbus.puen) - comb += pden_list[gpio_addr].eq(csrbus.pden) - comb += bank_sel[gpio_addr].eq(csrbus.bank_sel) + comb += wb_rd_data.eq(csrbus) + with m.Else(): + sync += new_transaction.eq(0) + # Update the state of "io" while no WB transactions + with m.If(gpio_oe_list[gpio_addr] & (~gpio_ie_list[gpio_addr])): + sync += csrbus.io.eq(gpio_o_list[gpio_addr]) + with m.If(gpio_ie_list[gpio_addr] & (~gpio_oe_list[gpio_addr])): + sync += csrbus.io.eq(gpio_i_list[gpio_addr]) + with m.Else(): + sync += csrbus.io.eq(csrbus.io) + + # Only update GPIOs config if a new transaction happened last cycle + # (read or write). Always lags from csrbus by 1 clk cycle, most + # sane way I could think of while using Record(). + with m.If(new_transaction): + sync += gpio_oe_list[gpio_addr].eq(csrbus.oe) + sync += gpio_ie_list[gpio_addr].eq(csrbus.ie) + # Check to prevent output being set if GPIO configured as input + # TODO: Is this necessary? PAD might deal with this + # check GPIO is in output mode and NOT input (oe high, ie low) + with m.If(gpio_oe_list[gpio_addr] & (~gpio_ie_list[gpio_addr])): + sync += gpio_o_list[gpio_addr].eq(csrbus.io) + sync += puen_list[gpio_addr].eq(csrbus.puen) + sync += pden_list[gpio_addr].eq(csrbus.pden) + sync += bank_sel[gpio_addr].eq(csrbus.bank_sel) return m def __iter__(self): @@ -145,6 +154,8 @@ def gpio_configure(dut, gpio, oe, ie, puen, pden, outval, bank_sel): | (bank_sel << BANKSHIFT) ) print("Configuring CSR to {0:x}".format(csr_val)) yield from wb_write(dut.bus, gpio, csr_val) + yield # Allow one clk cycle to propagate + return csr_val # return the config state def reg_write(dut, gpio, reg_val): @@ -177,6 +188,7 @@ def gpio_rd_input(dut, gpio): def gpio_set_out(dut, gpio, csr_val, output): print("Setting GPIO{0} output to {1}".format(gpio, output)) yield from wb_write(dut.bus, gpio, csr_val | (output<