m-labs / nmigen

A refreshed Python toolbox for building complex digital hardware. See https://gitlab.com/nmigen/nmigen
https://nmigen.org
Other
652 stars 55 forks source link

Index a signal with a slice from another signal #319

Closed rnd2 closed 4 years ago

rnd2 commented 4 years ago

Hi,

I am trying to convert an example from the TinyFPGA-BX repo (source) to nmigen.

// look in pins.pcf for all the pin names on the TinyFPGA BX board
module top (
    input CLK,    // 16MHz clock
    output LED,   // User/boot LED next to power LED
    output USBPU  // USB pull-up resistor
);
    // drive USB pull-up resistor to '0' to disable USB
    assign USBPU = 0;

    ////////
    // make a simple blink circuit
    ////////

    // keep track of time and location in blink_pattern
    reg [25:0] blink_counter;

    // pattern that will be flashed over the LED over time
    wire [31:0] blink_pattern = 32'b101010001110111011100010101;

    // increment the blink_counter every clock
    always @(posedge CLK) begin
        blink_counter <= blink_counter + 1;
    end

    // light up the LED according to the pattern
    assign LED = blink_pattern[blink_counter[25:21]];
endmodule

Here is the nmigen based example:

from nmigen import *
from nmigen_boards.tinyfpga_bx import TinyFPGABXPlatform

class Blinky(Elaboratable):
    def elaborate(self, platform):
        led   = platform.request("led", 0)
        counter = Signal(26)
        pattern = Signal(32, reset=0b101010001110111011100010101)

        m = Module()
        m.d.sync += counter.eq(counter + 1)
        m.d.comb += led.o.eq(pattern[counter[21:25]])
        return m

if __name__ == "__main__":
    platform = TinyFPGABXPlatform()
    platform.build(Blinky(), do_program=True)

The above code produces the following error: TypeError: Cannot index value with (slice (sig counter) 21:25)

I looked into nmigen source code and it seems that slices are not a valid key for other slices. Does that mean is not supported at the moment or in general?

Is it possible for nmigen to generate the following

assign LED = blink_pattern[blink_counter[25:21]];

Is there an alternative declaration (for nmigen) that will achieve the same result?


I did try Array(pattern)[counter[21:25]] which works, but generates a case statement. Also,

m.d.comb += led.eq(pattern.bit_select(counter[21:25],1))

Which seems quite close to the original.

programmerjake commented 4 years ago

Try using Value.part or one of the shift operators.

rnd2 commented 4 years ago

Thanks. So, since Value.part is deprecated, the solution with bit_select on the previous post is one efficient way to do it.