Skip to content

Conversation

@paller
Copy link

@paller paller commented Feb 28, 2025

Follow the 6 steps to add support for a new target.

Step 1: Locate input and output pins.

Step 2: Add pin constraint file. This covers clock input, LED and UART
output.

Step 3: Create a clock generator. The chip has no internal clock
generator so the external 12 MHz clock is used.

Step 4: Add top level servant_ice40_cm36 which connects the one-wire
output of servant to both the LED and UART pin.

Step 5: Add fileset including the new top level and pin constraints.

Step 6: Add target icesugar-nano.

I would expect this to be it, but the LED is not blinking.

If I add a reset function, something like 5 seconds in reset, 5 seconds run time. No blinking LED.
Setting a ~1 second reset each 10 seconds, still no light.

Debugging with a single LED as output I must say, it's pretty hard. If I drive the LED from the top-level scope or mix my debug signal with the servant's 'q' output, the LED is blinking according to the debug signal just fine, but only driving the LED from the servant output makes no light.

@olofk
Copy link
Owner

olofk commented Mar 1, 2025

I didn't see any obvious issues in the code. Tried building it here and didn't see any issues in the logs either. I don't have the board so can't test it it, but attaching my build tree if you want to try the FPGA configuration produced by my build or compare anything.
icesugar-nano-icestorm.tar.gz

Follow the 6 steps to add support for a new target.

Step 1: Locate input and output pins.

Step 2: Add pin constraint file. This covers clock input, LED and UART
        output.

Step 3: Create a clock generator. The chip has no internal clock
        generator so the external 12 MHz clock is used.

Step 4: Add top level servant_ice40_cm36 which connects the one-wire
        output of servant to both the LED and UART pin.

Step 5: Add fileset including the new top level and pin constraints.

Step 6: Add target icesugar-nano.
@olofk
Copy link
Owner

olofk commented Jan 12, 2026

Did you get it working, @paller ?

@paller
Copy link
Author

paller commented Jan 20, 2026

I'm no expect when it comes to HDLs and my initial printf() style debugging didn't help much. Either the LED is on, off, or blinking, which doesn't say a lot about anything. Any pointers on how to debug this issue would be appreciated.

I had some ideas, some better than others.

1: More blinking LEDs
Get a PMOD full of diodes for more output visualization. I have the PMOD somewhere but it sounds like a terrible idea.

2: Embedded tracer
I don't think the FPGA has an embedded trace module like e.g. GoWin, but then there is Litex LiteScope which I have been told could be used outside a Litex project. If I can get it working it's probably the best idea.

3: Route signals onto output pins
I now got a cheap logic analyzer with 8 or so channels, it's not fast but surely it's better than looking at blinking LEDs.

The question is how to access wires in sub-modules as I don't want to add a lot of debug outputs just to access signals at the top level. If I remember correctly it was possible to do something like

module top (input clk, output debug);

  cpu_module cpu();

  assign debug = cpu.alu.op_code; // <--- this

endmodule

but it required setting default_nettype = wire, which I'm not sure does what I'm expecting, or if it has side-effects.

@paller
Copy link
Author

paller commented Feb 5, 2026

It looks like the CPU is somewhat running.

There is very little space left for anything on the FPGA but it's possible to embed a single Manta IOcore which lets me poke around. Slowing the clock down to track all RAM reads (wb_mem_rdt) I get the following sequence.

0x40000537
0x00100337
0x40000537
0x00550023
0x40000537
0x000073b3
0x40000537
0xfe731ee3
0x40000537
0x00000000 <- looks bad
0xfe731ee3
0x00000000
0xfe731ee3
0x00000000
0xfe731ee3
0x00000000
0xfe731ee3
0x00000000

Comparing that with blinky.hex it's a match.

40000537
00050513
00100337
00000293
00550023
0012C293
000073B3
00138393
FE731EE3
FEDFF06F
00000000

It just doesn't seem right when it reads all zeros.

@paller
Copy link
Author

paller commented Feb 7, 2026

Assuming the CPU is executing the right instructions the next link in the chain is the IO for the GPIO module. Reading the signals q, wb_gpio_we, wb_gpio_stb, wb_gpio_dat and wb_gpio_rdt shows that it toggles between ON and OFF, but one signal is missing.

First state

wb_gpio_we = 1
wb_gpio_stb = 0
wb_gpio_dat = 0
wb_gpio_rdt = 0

Second state

wb_gpio_we = 1
wb_gpio_stb = 0
wb_gpio_dat = 1
wb_gpio_rdt = 0

Updating the GPIO pin is conditionalized on two signals where i_wb_cyc = wb_gpio_stb, but wb_gpio_stb is never high.

module servant_gpio (
...
  always @(posedge i_wb_clk) begin
    o_wb_rdt <= o_gpio;
    if (i_wb_cyc & i_wb_we) o_gpio <= i_wb_dat;
  end

@olofk
Copy link
Owner

olofk commented Feb 9, 2026

I don't have many good ideas but a few comments on your observations. I agree that it looks like the memory has been programmed correctly (nice to see Manta in action also!). I wonder about the traces though. We only care about the value of wb_mem_rdt when wb_mem_ack. At all other times, the value can be just about anything. The same thing goes with wb_gpio_dat which might change value all the time even when no actual GPIO access is being made.

There is one thing I would like you to try though. AFAIK, this is the only target with a memsize that is not a power of two. There might be some issue there. Could you try setting memsize to e.g. 4096 instead and see if that makes a difference?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants