whitequark[cis] changed the topic of #amaranth-lang to: Amaranth hardware definition language · weekly meetings: Amaranth each Mon 1700 UTC, Amaranth SoC each Fri 1700 UTC · play https://amaranth-lang.org/play/ · code https://github.com/amaranth-lang · logs https://libera.irclog.whitequark.org/amaranth-lang · Matrix #amaranth-lang:matrix.org
Degi has quit [Ping timeout: 248 seconds]
Degi has joined #amaranth-lang
BentoMon has quit [Read error: Connection reset by peer]
BentoMon has joined #amaranth-lang
FFY00 has quit [Ping timeout: 248 seconds]
FFY00 has joined #amaranth-lang
frgo has quit [Read error: Connection reset by peer]
frgo has joined #amaranth-lang
sorear has quit [Read error: Connection reset by peer]
sorear has joined #amaranth-lang
adamse has quit [Ping timeout: 248 seconds]
adamse has joined #amaranth-lang
FFY00_ has joined #amaranth-lang
FFY00 has quit [Ping timeout: 244 seconds]
<_whitenotifier> [amaranth] whitequark opened pull request #1573: Add policy on use of LLMs / "generative AI" - https://github.com/amaranth-lang/amaranth/pull/1573
<_whitenotifier> [amaranth] github-merge-queue[bot] created branch gh-readonly-queue/main/pr-1573-199c34ff43d39950add6c85149bd98a5d3569a21 - https://github.com/amaranth-lang/amaranth
<_whitenotifier> [amaranth-lang/amaranth] github-merge-queue[bot] pushed 1 commit to main [+0/-0/±1] https://github.com/amaranth-lang/amaranth/compare/199c34ff43d3...3c3dffa350be
<_whitenotifier> [amaranth-lang/amaranth] whitequark 3c3dffa - CONTRIBUTING: add policy on use of LLMs / "generative AI".
<_whitenotifier> [amaranth] github-merge-queue[bot] deleted branch gh-readonly-queue/main/pr-1573-199c34ff43d39950add6c85149bd98a5d3569a21 - https://github.com/amaranth-lang/amaranth
<_whitenotifier> [amaranth] whitequark closed pull request #1573: Add policy on use of LLMs / "generative AI" - https://github.com/amaranth-lang/amaranth/pull/1573
<_whitenotifier> [amaranth-lang/amaranth-lang.github.io] whitequark pushed 1 commit to main [+0/-0/±35] https://github.com/amaranth-lang/amaranth-lang.github.io/compare/18c6579ea3c7...908f82c31204
<_whitenotifier> [amaranth-lang/amaranth-lang.github.io] github-merge-queue[bot] 908f82c - Deploying to main from @ amaranth-lang/amaranth@3c3dffa350be44756ed1fed3e97353129622efe7 🚀
timkpaine has joined #amaranth-lang
timkpaine has quit [Client Quit]
tim[m]1 has joined #amaranth-lang
<tim[m]1> I was wondering about automatically parsing verilog/systemverilog code for easier use in Instance
<tim[m]1> is this something that would ever be of interest in amaranth
<tim[m]1> instead of m.submodules.my_submodule = Instance(...)
<whitequark[cis]> this would require an SV parser
<tim[m]1> yep slang
<tim[m]1> i noticed you forked recently
<tim[m]1> i was already using this one
<whitequark[cis]> unfortunately slang isn't currently compilable to webassembly
<tim[m]1> is that a prerequisite for any python deps?
<tim[m]1> he seems to publish a reasonable set of platform wheels
<whitequark[cis]> oh, hm, I completely forgot that it has a Python binding
<whitequark[cis]> we could have an optional dependency on slang, yeah
<tim[m]1> its difficult to deal with the full language
Wanda[cis] has joined #amaranth-lang
<Wanda[cis]> tim: what exactly are you proposing?
<tim[m]1> but could be done incrementally
<whitequark[cis]> I'm wondering what specifically would the API be here
<tim[m]1> I have code to parse modules/submodules/ins/outs/parameters
<whitequark[cis]> is this to perform validation of correctness?
<tim[m]1> i was thinking more for just convenience
<tim[m]1> its not too inconvenient already
<whitequark[cis]> what exactly becomes more convenient?
<whitequark[cis]> you still have to wire every one of them up
<tim[m]1> adding verilog ip
<tim[m]1> basically imagine you have a large subdesign
<whitequark[cis]> that doesn't answer my question
<tim[m]1> and just use amaranth as integration layer
<tim[m]1> N black-box submodules
<tim[m]1> with some standard interface
<whitequark[cis]> are you looking for an alternative to SV's .* that can look into SV instances but in Amaranth?
<whitequark[cis]> I thought I understood the use case but now I don't think I do
<tim[m]1> as the most basic (and mostly parsing-free) use case, I have some verilog modules that have submodules, and I need to make sure that i platform.add_file not just the top file but also any files for submodules
<Wanda[cis]> this... does not actually benefit from having a parser though.
<tim[m]1> "mostly parsing-free" :-)
<whitequark[cis]> yeah, the verilog ecosystem solution for this is "file lists" which look precisely the same (and even are compatible with) amaranth
<tim[m]1> im sure folks have use the vivado block designer at some point
<tim[m]1> and it has this autoconnect thing
<whitequark[cis]> i've interacted with vivado almost entirely through the CLI
<whitequark[cis]> s/CLI/Tcl interface/
<tim[m]1> lol #blessed
<whitequark[cis]> ... and even that was mostly generated by Amaranth
<whitequark[cis]> * even that Tcl was mostly
<tim[m]1> yes the amaranth experience is much nicer
<whitequark[cis]> * the same in (and even
<tim[m]1> im going to finish my parsing and see if i can add a little standalone function to replace the `submodule.<whatever> = Instance(...)` call and `platform.add_file`
<tim[m]1> idk if it will be worth it for other peoples use cases but i will share it here
JomerDev[m] has joined #amaranth-lang
<JomerDev[m]> (continuing a discussion started in the rust embedded channel)
<JomerDev[m]> Catherine I currently only need to emulate EPROMs up to 16MHz, so hopefully the speed shouldn't be an issue
<JomerDev[m]> For some smaller light controllers it's even only 8MHz. I tried to emulate it with an RP2040 at first, but I had to run it overclocked at all times (this was before 200MHz was officially supported by them)
<whitequark[cis]> the main problem with emulating EPROMs (or SRAMs) is that most high-density memories have some latency between when you clock in the address and when you start getting the data, while EPROMs and SRAMs have none
<whitequark[cis]> since there is little on-FPGA memory, you generally have to resort to using DRAM or HyperRAM, although in this case a very fast QSPI flash might also work
<whitequark[cis]> consider that at 16 MHz, doing a QSPI Fast Read command requires you to clock it in at (16 MHz * (32 / 4) = 128 MHz) SDR, which is feasible but only just, and will require you to pick your flash carefully
<whitequark[cis]> HyperRAM or octal-SPI (or even hexadeca-SPI) memories would work better in this case but are somewhat more obscure
<whitequark[cis]> (actually, note that the calculation above assumes that your setup and hold times are zero, i.e. that the address is available right at the start of the clock cycle, and the data can be available as late as the next clock cycle. real conditions will be likely worse)
<JomerDev[m]> Hmm, I actually hoped for that part to be less of an issue, but haven't actually calculated any of it yet. I'm fine with with needing an SRAM of some kind, I already planned on having to read the firmware the simulated eprom is supposed to hold before it can actually be available
<whitequark[cis]> if you are fine with an external SRAM then the FPGA firmware could be as simple as loading your data from a QSPI flash and into the SRAM
<whitequark[cis]> but you could just as well use an RP2350 to do that
<whitequark[cis]> s/firmware/bitstream/
<whitequark[cis]> also, consider using an existing SRAM emulation solution
<JomerDev[m]> Well, since the EPROM interface doesn't allow for writing (of course) but I need a two way communications channel my solution so far would have been to use a specific address range of the EPROM to instead read from the data bus and push that into a channel to an rp2350 or write it to a register. So I need something in between the EPROM interface and any potential SRAM to route the address and data bus
<whitequark[cis]> you could probably do this with a single AND gate, haha
zyp[m] has joined #amaranth-lang
<zyp[m]> how big a ROM will you be emulating?
<whitequark[cis]> assuming I know the type of bus you're working with, the EPROM has a !CE or !RE strobe that is connected to the output of a comparator checking whether the high bits of the address indeed resolve to the EPROM
<JomerDev[m]> I mean, sure, but with an FPGA I can change the address where it starts easier than with a soldered gate
<whitequark[cis]> for sure
<whitequark[cis]> I would probably just steal the high bit personally
<JomerDev[m]> Fair, but I don't know yet how large my replacement firmware will end up being and if I might need more than half of the address space for that
<whitequark[cis]> anyway, I understand what you're looking for now; I would be a little concerned about timings since that can make or break your project
<whitequark[cis]> do you have a specific FPGA in mind?
<whitequark[cis]> how sensitive to the cost are you? does your target use 5V logic, and if so, do you understand the tradeoffs with level shifting that will involve?
<JomerDev[m]> I have a breakout board with an iCE40HX8K (https://www.olimex.com/Products/FPGA/iCE40/iCE40HX8K-EVB/open-source-hardware) and was hoping that a similar FPGA would be enough
<whitequark[cis]> iCE40HX8K is slow enough that I would be seriously concerned about your timing budget
<whitequark[cis]> in particular, beware of the IO register's clock-to-out delay which is something like 10 ns if memory serves me right
<JomerDev[m]> It does use 5V logic, I already have some test boards with level shifters on it
<JomerDev[m]> My alternative idea was a dual port ram ic, but those seem to have almost vanished
<whitequark[cis]> have you considered using a CPLD for address decoding? ATF1502 or the like lets you skip the entire timings-and-level-shifting business entirely while retaining the freedom you need
<whitequark[cis]> it's also going to be cheaper
<zyp[m]> are we talking a ROM measured in kilobytes or megabytes?
<whitequark[cis]> (I reverse-engineered the ATF15xx CPLD series but nobody wrote a usable toolchain for it, so you'd be stuck using WinCUPL, unfortunately. on the bright side the equation you need is pretty trivial)
<JomerDev[m]> zyp[m]: 1MiB, so 128Kilobytes
<whitequark[cis]> 128K is small enough that a larger FPGA like one of the cheapest Artix devices might just fit your entire ROM
<JomerDev[m]> whitequark[cis]: I haven't even heard of them before, so no. Reading the datasheet now
<whitequark[cis]> s/128K/128KiB/
<zyp[m]> that'd fit in an ice40up SPRAM
<zyp[m]> or a lifcl LRAM
<whitequark[cis]> PALs and CPLDs have been used for exactly this in the period in which the hardware you're using was designed
<whitequark[cis]> PALs are really quite obsolete now and really annoying to program, but CPLDs are relatively approachable to someone with a modern toolkit
<whitequark[cis]> ah yeah good call zyp; iCE40UP is even slower though so I'd be especially concerned about timings
<zyp[m]> yeah, but SPRAM shouldn't have that much latency
<whitequark[cis]> I'm wary of saying it'll be okay without knowing what the target device actually needs
<whitequark[cis]> it's probably fine, but needs to be checked
<JomerDev[m]> whitequark[cis]: Ah yes, one of the two targets of my project has a GAL built in. Very annoying to reverse engineer
<zyp[m]> a LIFCL-17 has 2.5 Mbits of LRAM, and should be plenty fast, but is probably way overkill :)
<JomerDev[m]> Another reason for me to use an FPGA was to hopefully use the same "emulation/controller" pcb everywhere and just use different carrier boards for the different EPROM footprints
<JomerDev[m]> So I could use a different FPGA firmware depending on the target, but only have one complicated PCB design
<whitequark[cis]> wouldn't you end up with a really complicated level shifting solution then?
<whitequark[cis]> unless you use autosensing level shifters, in which case you're screwed
<JomerDev[m]> So if I'm understanding the CPLD correctly it's an EEPROM with some customizable logic included?
<whitequark[cis]> you can think of a CPLD as a very primitive, 5V-capable (or 5V-tolerant, depending on your pick) FPGA
<whitequark[cis]> it happens to have built-in config memory, but so does iCE40
<whitequark[cis]> (iCE40's config memory is "few time programmable", 2-3 times in practice)
<whitequark[cis]> it has a fundamentally different architecture for the programmable logic part, but if your logic is as simple as decoding a pair of address ranges this does not matter in the slightest
<JomerDev[m]> whitequark[cis]: The idea was to have the level shifters on the carrier board, that way each carrier board would have the level shifters it needs, since in my mind the FPGA wouldn't care which GPIOs would be connected to the address or data bus. I'd just need a firmware matching the carrier board
<whitequark[cis]> you could definitely do that, but again, personally, I would pick a simpler solution
<whitequark[cis]> I'm happy to help you develop your thing though
<JomerDev[m]> whitequark[cis]: Ah. So it would just be an easier way to do the switch between reading and writing in my case
<whitequark[cis]> zyp: one problem with the UP devices is that they have at most 48 pins I think
<whitequark[cis]> JomerDev[m]: correct. they require no config memory, have no loading process, require no additional voltages to 5V or level shifting
<JomerDev[m]> whitequark[cis]: I honestly though that FPGAs were the simpler solution 😅
<whitequark[cis]> basically the "AND gate" solution but more configurable
<whitequark[cis]> like, you could conceivably be done in an evening, including PCB design
<JomerDev[m]> Right. That would solve the reading issue, but maybe not the writing issue? I guess I would have to have two of them, one going to some sort of memory and one to the RP2350 in case something gets written
<whitequark[cis]> no no, you have two outputs
<whitequark[cis]> one that enables the SRAM's output, and one that enables RP2350's output
<tim[m]1> ooo got amaranth to work against a 2.2GB vivado docker image on my macbook 🎉
<whitequark[cis]> basically, you create two "chip select" signals from the high address bits, which is doable with one CPLD
<whitequark[cis]> tim: nice!
<tim[m]1> oh snap sorry hopefully it didnt make that graphic for everyone...
<tim[m]1> s/graphic/animation/
<tim[m]1> s/graphic/animation/
<whitequark[cis]> oh, that matrix thing. I think I have "reduce motion" enabled somewhere in it
<tim[m]1> apologies i didnt know it would do that 😬
<tim[m]1> in a bash script called `vivado` on the path:
<tim[m]1> `docker run -v `pwd`:/home/user --workdir /home/user --entrypoint /opt/Xilinx/Vivado/2023.2/bin/vivado -e LD_PRELOAD=/lib/x86_64-linux-gnu/libudev.so.1 timkpaine/vivtest "$@"`
<tim[m]1> s/`/\`/, s/`://\`://
<tim[m]1> * in a bash script called `vivado` on the path:
<tim[m]1> `docker run -v ``pwd``:/home/user --workdir /home/user --entrypoint /opt/Xilinx/Vivado/2023.2/bin/vivado -e LD\_PRELOAD=/lib/x86\_64-linux-gnu/libudev.so.1 timkpaine/vivtest "$@"\`
<JomerDev[m]> Ah. Right. I also wanted some "registers" (bytes) that could be written to by the rp2350 and read by the motorola processor. Since I assume the rp2350 wont be fast enough either I would have to write every change to the SRAM in between reads by the motorola processor
<whitequark[cis]> to escape a backtick in markdown, use this: `` foo `pwd` bar ``
<tim[m]1> close enough 😅
<whitequark[cis]> pretty sure rp2350 could respond to writes at 16 MHz
<whitequark[cis]> I mean, if your plan with the iCE40 would work, then RP2350 should be able to do so as well
<whitequark[cis]> since their minimum delay is probably roughly in the same ballpark
<JomerDev[m]> whitequark[cis]: I assume you mean only if the value read from the rp2350 is in it's RAM somewhere and not if it is read from the flash? Since in the latter case I could just forget about the SRAM entirely
<whitequark[cis]> well it's just a few registers, right?
<whitequark[cis]> furthermore, it actually almost doesn't matter how slow the RP2350 is, since you control the memory access code
<JomerDev[m]> Sure, in the end it shouldn't be more than a kb or so.
<JomerDev[m]> I do control that, though I don't control the interface. A read has to answer in one cycle
<whitequark[cis]> ah, okay, that does mean it matters whether it's fast
<whitequark[cis]> can I see the bus timings?
<whitequark[cis]> okay, so, looking at RP2350, a single PIO engine can control all 48 of its GPIOs
<whitequark[cis]> sorry, no, up to 30 GPIOs
<JomerDev[m]> Does this help you?
<whitequark[cis]> the PIO engines run off clk_sys so you should be able to run 10 PIO instructions per a single 68K bus cycle
<whitequark[cis]> that appears plenty
<whitequark[cis]> the frequency of CLK is 16 MHz, right?
<JomerDev[m]> That it is. As far as I recall my issue wasn't the PIO speed, but the speed of one round trip PIO -> FIFO -> code that checks the address -> read from RAM into FIFO -> PIO
<JomerDev[m]> whitequark[cis]: For that one, yes. The image is from the 68020 Manual
<whitequark[cis]> I would use a mailbox-style interface to deal with that
<whitequark[cis]> i.e. have a "address" register and "data" register; a write to address register lets the RP2350 capture the desired "inner" register, then you can have any amount of wait states (since you control the memory code), then you read from the data register
<whitequark[cis]> provided you don't require very high bus utilization, this simplifies things quite a bit since now the PIO only needs to capture the GPIOs, or to respond to a read strobe with a pre-set value
<whitequark[cis]> basically on the RP2350 you would only ever have two accessible locations, maybe at 00h and 04h
<whitequark[cis]> and you would use the address in 00h to indirectly access the data via 04h
<JomerDev[m]> Yes, I was talking more about if I wanted to do the whole EPROM with the RP2350. If I only want to read/write the registers then that should be fine
<whitequark[cis]> actually if you have enough spare pins you could do the address decoding on the RP2350 too
<whitequark[cis]> dedicate an entire PIO core to decoding the address and outputting it to some spare pin
<JomerDev[m]> True. But the RP2350 is also supposed to actually run the light controller, so it's not like being ready for register reads/writes is it's only purpose
<whitequark[cis]> right
<JomerDev[m]> And math is notoriously hard with the PIO, but checking if an address is larger or smaller than a given value should be possible
<whitequark[cis]> I was just looking at that; that's actually kind of a pain, but if you only reserve like two addresses for the RP2350 anyway, the math becomes very easy
<whitequark[cis]> I think if you try to do a proper "greater than" operation you'll blow through the timing budget, but slicing a small amount of highest address space is a simple bitmask comparison which should be doable in one operation
<JomerDev[m]> Yes, I think so too
<JomerDev[m]> Though I guess if I'm using an SRAM to do the majority of the EPROM work I could go back to using an FPGA for the rest? The rest being the address decoding, responding to register reads and writes and providing some FIFOs in both directions to make it easier on the RP2350
<whitequark[cis]> yes, absolutely
<whitequark[cis]> I think the ice40hx8k you picked should do just fine
<whitequark[cis]> a key part that I was missing is that the clock is 16 MHz, but the bus is effectively running at 5.3 MHz
<whitequark[cis]> basically any modern FPGA, even the absolute slowest ones, should not have trouble with that
<JomerDev[m]> Is it possible to just connect pins through 99% of the time? So just patching the SRAM GPIOs through as soon as the SRAM is set up and making the Motorola processor just run NOPs until it is
<JomerDev[m]> Ah, fair enough. Yeah, the bus is weird like that
<whitequark[cis]> you could do this but I will recommend against it
<JomerDev[m]> 🤦 Ah, no, I don't need that, I just need the FPGA to not enable the SRAM until it is ready
<whitequark[cis]> yes
<whitequark[cis]> actually, let's backtrack a bit to make sure all of my assumptions are right
<whitequark[cis]> your only interface to the 68K is the EPROM slot, is it? and you aim to make no modifications to the board (besides swapping out the EPROM)?
<JomerDev[m]> Sure
<JomerDev[m]> Yes, exactly
<whitequark[cis]> can I see the pinout?
<JomerDev[m]> The EPROM is socketed, everything else isn't
<JomerDev[m]> Of the EPROM or everything? 😁 I do have the full schematic of the light controllers I want to modify
<whitequark[cis]> EPROM
<whitequark[cis]> or just the full schemati
<whitequark[cis]> s/schemati/schematic/
<whitequark[cis]> either works
<JomerDev[m]> Let's see. This is part of the schematic for the smaller controller, with 68008, EPROM and RAM on it
<whitequark[cis]> IC34 is the ROM I presume?
<JomerDev[m]> Yes, sorry
<JomerDev[m]> And this is the EPROM for the larger controller
<whitequark[cis]> do you realize that you have no way to recognize that a bus write is occurring from just the IC34 socket?
<JomerDev[m]> (Which uses an 68020 and a 68008)
<whitequark[cis]> it has !OE, but no !WE
<JomerDev[m]> Yes, I know, which is why I came up with the address space for writes instead. I don't need to know if it's a write, the data bus is connected regardless. I only need to know if it is the right address
<whitequark[cis]> how would you know when a write has "ended"?
<whitequark[cis]> it is completely legal for the CPU to e.g. set address to ABCDh, data to 69h, strobe !WE, then set data to 12h
<JomerDev[m]> How do you mean "ended"?
<whitequark[cis]> since you have no !WE you have no way to tell the garbage data 12h from the non-garbage data 69h
<JomerDev[m]> Ah, if it is writing to the same address twice?
<whitequark[cis]> no
<whitequark[cis]> it could keep the same address on the address bus and put some random garbage on the data bus
<JomerDev[m]> Ah. But then the !OE for the EPROM would not be on anymore
<whitequark[cis]> the !OE for the EPROM won't be strobed for writes
<whitequark[cis]> from the perspective of IC34, a write to the magic address ABCDh looks like: (random garbage), (desired data), (more random garbage) with no strobes to synchronize the write
<JomerDev[m]> At least for the smaller controller it will, because it is dependent on the address on the bus
<whitequark[cis]> how do you distinguish the (desired data) from the (random garbage)?
<JomerDev[m]> The !OE is connected through a 73138, a demultiplexer
<whitequark[cis]> huh, that's really weird
<whitequark[cis]> what happens if you write to the EPROM address space? bus contention?
<whitequark[cis]> <JomerDev[m]> "image.png" <- can you give me a link to the datasheet?
<JomerDev[m]> Bus contention, yes
<whitequark[cis]> okay, I see, that indeed does make it at least more tractable
<JomerDev[m]> And in my case I should hopefully just be able to read the data from the bus instead, even without !WE
<whitequark[cis]> okay, let's consider the byte write diagram
<whitequark[cis]> you can't read the data when OE is asserted, since it will not be valid yet (data is valid after S2, address since S0)
<whitequark[cis]> this means you can read the data off the bus either when OE is deasserted, or using a pre-set delay
<whitequark[cis]> the deassertion, at least according to the document, has a race condition where the data validity ends at the same time as the address changes, and thus your OE changes
<whitequark[cis]> the only way to deal with this race condition that I can see is to read the data from the bus at the start of S4 by using a delay inside the FPGA or RP2350, although if you get lucky, you might be able to get away with the rising edge of !OE. conversely if you get unlucky the data will always be invalid by that time, i'm not sure whether it ever tries to drive the data bus right away in S0 for some other bus cycle
<whitequark[cis]> does this make sense?
<JomerDev[m]> Yes, I figured I'd use a delay, since I know the clock rates
<whitequark[cis]> if OE and Dn change simultaneously at the MC68020, your OE goes through a demultiplexer first, which will add some dely
<whitequark[cis]> okay
<whitequark[cis]> that's sketchy in concept but definitely doable practically
<JomerDev[m]> That's pretty much this entire project, yes :D
<whitequark[cis]> if you use an FPGA, this means it would be asynchronously clocked, and sample the address/data buses on that clock
<whitequark[cis]> this introduces a 2-cycle delay in the data path for the 2FF synchronizer you will need to avoid metastability issues
<whitequark[cis]> you can probably afford it just fine, you should be able to run your logic off a 64 MHz clock (x4 oversampling) and the 2-cycle latency only matters for the address phase since the data phase has a known fixed latency
<JomerDev[m]> That sounds fine, yes
<whitequark[cis]> the pin situation is also not too bad with only 8 data bits
<whitequark[cis]> oh, you have 16 data bits on the bigger device
<JomerDev[m]> I do
<JomerDev[m]> And even worse, both 8 bit and 16 bit reads and writes are possible
<whitequark[cis]> were you to use iCE40UP5K, you could skip the external SRAM and use the built-in SPRAM just fine
<whitequark[cis]> the biggest iCE40UP5K package has 39 pins; in this case 33 pins (one for level shifter OE) would be used for the interface, and the remaining 6 are free to talk to the RP2350
<zyp[m]> and if that's not enough, i'd have a serious look at LIFCL-17
<whitequark[cis]> you would need to time the bus direction changes correctly to avoid contention but that's definitely doable
<whitequark[cis]> iCE40UP5K does limit you to 128K max of firmware
<whitequark[cis]> with LIFCL-17 you could have more firmware but you'd need some horrifying bank switching abomination to make it fit into 16 address bits
<JomerDev[m]> The firmware should be tinier than the original firmware, the Motorola processor will mostly be the connection to all the input and output peripherals
<whitequark[cis]> zyp: hey, cursed thought: compile a firmware as position-independent code, limit the jump range using linker shenanigans, and have the FPGA supply instructions on the fly without treating the address itself as a fixed reference to the code
<whitequark[cis]> basically, whenever the FPGA sees a jump up to 32K forward it increments its internal address by the relative change in address, and the same for backward jumps
<zyp[m]> sounds fun :)
<JomerDev[m]> I'll need to do something similar but much smaller. When the FPGA is fully started up I'll need the first read to always be a reset, doesn't matter which address, so the processor starts from the proper place
<whitequark[cis]> yeah that's easy enough
<JomerDev[m]> I figured
<whitequark[cis]> I would probably implement the entire thing as one large state machine since the FPGA is likely more than fast enough for this
<whitequark[cis]> sample An, start an SPRAM read, set or clear !OE, wait a preset amount of cycles, sample or set Dn, do a FIFO operation if requested
<whitequark[cis]> you could quite easily practice this in the Amaranth simulator, which supports asynchronous operation (i.e. you can write a model of the mc68020 in Python and have it talk to the FPGA which runs off a clock, and the simulation will be fairly realistic)
<whitequark[cis]> * in Python that uses delays for everything, and have
<JomerDev[m]> In case of the breakout board I linked earlier, would the same be possible with the SRAM used there? I originally wanted to connect the FPGA to the RP2350 via the RP2350B's second QSPI connection, meaning the FPGA would pose as PSRAM to the RP2350, since I figured using the internal flash communication build into the RP2350 would be faster than anything I could write in code myself (since every line of code I write needs to be
<JomerDev[m]> loaded from the first flash in turn)
<whitequark[cis]> I would strongly recommend not doing that
<whitequark[cis]> implementing a QSPI peripheral in an FPGA is a complicated and finicky process
<whitequark[cis]> it will result in several times the complexity of the project without it
<JomerDev[m]> I already have an example for a QSPI peripheral in verilog. But yes, without me knowing much about FPGA programming it would have been very hard
<whitequark[cis]> integrating that peripheral with the rest of your project is where much of the complexity lies
<zyp[m]> memory mapped QSPI tends to have caching/buffering that assumes it's connected to a regular memory, so it's often not suitable for MMIO
<whitequark[cis]> also that
<JomerDev[m]> I've already checked that I can disable that on the RP2350 :D
<whitequark[cis]> but to answer your question: yes, it would be possible
<JomerDev[m]> Thats good. The PIO does much better when it doesn't have to change the direction of it's GPIOs constantly
<whitequark[cis]> you could use fixed direction for IOs if that's the problem
<JomerDev[m]> Yes, but that's much easier if I have more than 6 GPIOs for the RP2350 communication available
<whitequark[cis]> right, I see
<whitequark[cis]> using the external SRAM vs the built-in SPRAM is mostly a question of timings
<whitequark[cis]> I think you are probably fine timing-wise from what I've seen so far
<JomerDev[m]> Well, I guess for the breakout board I would have to pass the address the FPGA gets along to the external SRAM and pass the result back through the FPGA. Since I don't think the SRAM is connected to anything other than the FPGA there. But for my own PCB that could be different
jjsuperpower has quit [Remote host closed the connection]
<whitequark[cis]> the reason I asked for all these details is to validate a key assumption, which I think was wrong
<whitequark[cis]> consider the case of the initial writes to the SRAM. if the SRAM is connected directly to the memory bus, and so is the FPGA/RP2350, and the MC68020 is free-running, then you're going to have logical contention when you are trying to write to the SRAM
<JomerDev[m]> Yes
jjsuperpower has joined #amaranth-lang
<whitequark[cis]> in this case, and in light of the fact that it's actually a 5.3 MHz bus, not a 16 MHz bus, it probably makes more sense to pass everything through the FPGA
<whitequark[cis]> 180 ns is a much nicer timing budget than 60 ns
<JomerDev[m]> 😁 So most of my idea/plan for the FPGA is probably working out. Sure, I'll have to use the SRAM and not read the required byte from the flash the FPGA boots from, nor should I use QSPI to communicate with the RP2350 but the rest holds up
<whitequark[cis]> yes pretty much
<JomerDev[m]> I assume to load data into the SRAM I would either have to read it from the same flash the fpga boots from or have it be passed along from the RP2350?
<whitequark[cis]> I don't think ice40hx8k lets you access the configuration flash, though I may be wrong
<whitequark[cis]> it's probably easiest to pass it from the RP2350
<JomerDev[m]> I thought the pins turn into normal GPIOs after, but that could be wrong as well
<whitequark[cis]> I thought that's only true on iCE40UP, let me check
<whitequark[cis]> > After the additional SPI_CLK cycles, the SPI interface pins then become available to the user application loaded in
<whitequark[cis]> FPGA. In the iCE40-1KLP SWG16 package, the CDONE pin can be used as a user output.
<whitequark[cis]> okay I see, I misremembered and it only applied to CDONE pin in one specific package
<whitequark[cis]> yeah, you could do either
<whitequark[cis]> it's not too difficult to access the FPGA bitstream flash, but it might be more convenient to load it from RP2350
<JomerDev[m]> Fair enough. Though the RP2350 would load it via QSPI, so I'd think it'd probably be faster to not have the RP2350 in the middle
<whitequark[cis]> well the RP2350 has USB and stuff while the FPGA doesn't
<whitequark[cis]> I'm just thinking of how the development process for the firmware goes
<whitequark[cis]> if you're grabbing the firmware from QSPI and putting it into the FPGA via a multi-pin PIO-driven interface you should be able to saturate both of them fairly easily depending on the relative clock rats
<whitequark[cis]> s/rats/rates/
<whitequark[cis]> since you're not contending on the QSPI controller of the RP2350
<JomerDev[m]> Ah, true. For development, ease of flashing I thought about using a CH347 IC that does SPI as well as JTAG/SWD. I could use it to debug the RP2350 and flash the FPGAs Flash
<whitequark[cis]> that would work, just make sure you reset the FPGA whenever you access its SPI flash
<JomerDev[m]> Though another possibility would be to download a new firmware (through an ESP32 connected to the RP2350, not to the FPGA) and then have the RP2350 write it to the FPGAs flash. Or let the RP2350 send it to the FPGA to write it to the FPGAs flash so the RP2350 doesn't have to be connected to that
<whitequark[cis]> that's so many logic ICs...
<JomerDev[m]> whitequark[cis]: Yes, it afaik also has GPIOs to do that
<JomerDev[m]> With the ESP as well you mean? It's supposed to be a ESP-C6 mini, mostly to host a web interface
<JomerDev[m]> But yes, one ESP core, two RP2350 cores plus the FPGA and the Motorola processor
<whitequark[cis]> the amount of possible race conditions would terrify me
<JomerDev[m]> Well, hopefully none of them will ever get knocked loose inside the target to be able to race against each other /s
<whitequark[cis]> if you used a LIFCL-17 you could fit your entire system (including Hazard3, the RISC-V core on the RP2350, and memory) on the FPGA itself
<JomerDev[m]> Sure. My hope is that I get everything connected in a way that the RP2350 is the main controller and everything else is just feeding information to or from it
<whitequark[cis]> although doing this with no FPGA experience would be a bit challenging
<JomerDev[m]> That and probably the missing Rust support for the RISC_V core inside the FPGA
<whitequark[cis]> is it missing? I didn't realize
<whitequark[cis]> Hazard3 is an RV32IMAC with Zcsr and a bunch of bitmanip extensions, that seems like it'd be well-supported?
<JomerDev[m]> Afaik yes. RISC-V is supported by itself, but I doubt it would be easy to make it play well with the rest of the FPGA
<zyp[m]> the CPU core itself doesn't need much particular support from Rust, you're probably thinking of any custom peripherals
<JomerDev[m]> Yes, that is closer to what I mean
<whitequark[cis]> you could do what https://github.com/apfaudio/tiliqua does and have the SVD and PAC be automatically generated from your SoC hardware description
<whitequark[cis]> so whenever you define a register and rebuild, it appears in your PAC all by itself
<whitequark[cis]> really, this is just me liking it when everything lives in the FPGA and (often) can run off the same clock even
<JomerDev[m]> I know of that but didn't realize it used an rp2040 as well as rust in some places
<whitequark[cis]> yeah, many bitstreams include a risc-v core and the firmware for that uses rust
<JomerDev[m]> Interesting. Could be very cool, but as you've said, without any FPGA experience it would be even more difficult than the current setup is for me
<whitequark[cis]> it's also a more expensive FPGA
<JomerDev[m]> Sure, but less parts to be placed by JLC/Whoever
<whitequark[cis]> and less board space yeah
<JomerDev[m]> Anyway, I really need to go to bed now, thank you both very much for all the help! I'll definitely be back soon with more questions
<whitequark[cis]> night
duskwuff[m] has joined #amaranth-lang
<duskwuff[m]> I guess I'm coming in a little late but: do you have access to _DTACK on the 68k system? because if so, you can stretch the memory access cycle if needed
<duskwuff[m]> it's certainly ideal if you can respond to memory accesses within a single cycle ("DTACK grounded") but the CPU can support slower memories
lf_ has joined #amaranth-lang
lf has quit [Ping timeout: 268 seconds]