[Libre-soc-bugs] [Bug 762] Peripheral Pin Muxing Development

bugzilla-daemon at libre-soc.org bugzilla-daemon at libre-soc.org
Sun May 22 00:31:39 BST 2022


https://bugs.libre-soc.org/show_bug.cgi?id=762

--- Comment #22 from Luke Kenneth Casson Leighton <lkcl at lkcl.net> ---
https://git.libre-soc.org/?p=pinmux.git;a=commitdiff;h=56bf88cdb4ef409ec2d7bfb7621797ddce50857c

this looks good:

+                    GPIO_num = Signal(16) # fixed for now
+                    comb += GPIO_num.eq(bus.adr*len(bus.sel)+i)
+                    with m.If(bus.sel[i]):
+                        sync += rd_multi[i].oe.eq(gpio_ports[GPIO_num].oe)

one of these is either unnecessary or the wrong way round:
you don't want to be reading things that should be written
or writing things that should be read.

+                        with m.If (gpio_ports[GPIO_num].oe):
+                            sync += rd_multi[i].io.eq(gpio_ports[GPIO_num].o)
+                        with m.Else():
+                            sync += rd_multi[i].io.eq(gpio_ports[GPIO_num].i)
+                        sync += rd_multi[i].bank.eq(gpio_ports[GPIO_num].bank)

all of these DESTROY the registers.  the whole, entire purpose of sel
is to **not** overwrite or touch that which has a "sel" bit of zero.

+                    with m.Else():
+                        sync += rd_multi[i].oe.eq(0)
+                        sync += rd_multi[i].ie.eq(0)
+                        sync += rd_multi[i].puen.eq(0)
+                        sync += rd_multi[i].pden.eq(0)
+                        sync += rd_multi[i].io.eq(0)
+                        sync += rd_multi[i].bank.eq(0)

also i noticed that you've got this:

 103                 sync += Cat(*wr_multi).eq(wb_wr_data)

followed later by this:

 141                         sync += gpio_ports[GPIO_num].oe.eq(wr_multi[i].oe)

so what will happen there is:

* firstly, on one clock cycle (cyc & stb & we), the incoming wishbone
  write data will be captured into wr_multi. this will make that data
  available ONLY ON THE NEXT CYCLE

* secondly, on the **NEXT** cycle, "bus.we" will oh wait, whoops, it's
  now the next cycle, which has a totally new set of data, it could
  be a read at this point, and the data is hosed.

actually now that i look at it the exact same thing is happening with
rd_multi.

on one clock:

 113                         sync += rd_multi[i].oe.eq(gpio_ports[GPIO_num].oe)

and on the **NEXT** clock (when bus.we is completely invalid and/or unrelated):

 153                 sync += wb_rd_data.eq(Cat(*rd_multi))

basically you probably want this:

 113                         comb += rd_multi[i].oe.eq(gpio_ports[GPIO_num].oe)
 114 etc. etc.


also, you've made a classic error of using an Array unnecessarily:

  72         self.wr_multicsr = Array(temp)
  90         wr_multi = self.wr_multicsr
 103                 sync += Cat(*wr_multi).eq(wb_wr_data)

and using it with a *static* index:

 137                 for i in range(len(bus.sel)):

Array() is only necessary on a *DYNAMIC* index, like GPIO_num.

lose "Array()" on both rd_multi and wr_multi.

  62         self.rd_multicsr = rd_multi = []
  63         for i in range(self.wordsize):
  64             name = "rd_word%d" % i # please don't use format
  65             rd_multi.append(Record(name=name, layout=csrbus_layout))

-- 
You are receiving this mail because:
You are on the CC list for the bug.


More information about the libre-soc-bugs mailing list