Examples of translating Verilog code to magma

Counter with reset and enable

Verilog

logic read;
logic [9:0] rd_ptr;

always_ff @(posedge clk, negedge rst_n) begin
    if(!rst_n) begin
        rd_ptr <= '0;
    end
    else if(read) begin
        rd_ptr <= rd_ptr + 1;
    end
end

Base magma

# Declare anonymous bit (like a wire)
read = m.Bit()

# Generate/Instance register
rd_ptr = mantle.Register(10, has_async_reset=True, has_ce=True, init=0)

# Wire read to clock enable
rd_ptr.CE <= read

# Increment logic
rd_ptr.I <= m.uint(rd.ptr.O) + 1

Sequential Syntax

(treating read as an input)

@m.circuit.sequential(async_reset=True)
class Circuit:
    def __init__(self):
        self.rd_ptr: m.Bits[10] = m.bits(0, 10)

    def __call__(self, read: m.Bit) -> m.Bits[10]:
        orig_rd_ptr = self.rd_ptr

        # FIXME: Bug in magma sequential means we always have to specify a next
        # value (won't use current value by default)
        self.rd_ptr = orig_rd_ptr

        if read:
            self.rd_ptr = m.uint(self.rd_ptr) + 1
        return orig_rd_ptr

Array of registers

Verilog

logic [1023:0][15:0] register_array

Base magma

register_array = m.join([mantle.Register(1024) for _ in range(15)])

Sequential Syntax

@m.circuit.sequential
class Circuit:
    def __init__(self):
        self.register_array: m.Array[15, m.Bits[1024]] = \
            m.array([m.bits(0, 1024) for _ in range(15)])