VHDL conversion - missing constant


#1

I’m finding my way around MyHDL. I’m well-versed in VHDL and experienced with Python, but as another post mentioned recently, there’s an open-source toolchain for Lattice FPGAs but it only supports Verilog, so I’m looking at using MyHDL for my authoritative code base and then converting to Verilog for synthesis, and VHDL for sanity-checking and maybe extra debugging. The ability to write Python unit tests with MyHDL is the major drawcard for me.

I’ve read through most (but not all) of the MyHDL docs in the main documentation area, and I feel like I understand most of what is going on, but I’m still learning the ropes. In particular, the code below successfully generates VHDL, but there’s no definition of the signal pattern generated, so I don’t think this will synthesise.

from myhdl import block, always, always_comb, Signal, intbv, modbv

PATTERN_SOS = intbv("101010001110111011100010101")

@block
def Blink(clk, clk_en, led):
    pattern = PATTERN_SOS
    counter = Signal(modbv(0, min=0, max=32))

    @always(clk.posedge)
    def counter_inc():
        if clk_en == 1:
            counter.next = counter + 1

    @always_comb
    def output():
        led.next = pattern[counter]

    return counter_inc, output

if __name__ == "__main__":
    inst = Blink(Signal(bool(0)), Signal(bool(0)), Signal(bool(0)))
    inst.convert(hdl="VHDL")

This generates:

-- File: Blink.vhd
-- Generated by MyHDL 0.10
-- Date: Sun Jul 29 17:59:49 2018


library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use std.textio.all;

use work.pck_myhdl_010.all;

entity Blink is
    port (
        clk: in std_logic;
        clk_en: in std_logic;
        led: out std_logic
    );
end entity Blink;


architecture MyHDL of Blink is


signal counter: unsigned(4 downto 0);

begin




BLINK_COUNTER_INC: process (clk) is
begin
    if rising_edge(clk) then
        if (clk_en = '1') then
            counter <= (counter + 1);
        end if;
    end if;
end process BLINK_COUNTER_INC;


led <= pattern(to_integer(counter));

end architecture MyHDL;

Is there some special treatment I need to make to PATTERN_SOS to have it convert successfully? Is it possible to declare it a constant array or somesuch?

Incidentally, this simple change (using PATTERN_SOS directly rather than via an alias) doesn’t convert:

@block
def Blink(clk, clk_en, led):
    counter = Signal(modbv(0, min=0, max=32))

    @always(clk.posedge)
    def counter_inc():
        if clk_en == 1:
            counter.next = counter + 1

    @always_comb
    def output():
        led.next = PATTERN_SOS[counter]

    return counter_inc, output

Results in:

Traceback (most recent call last):
  File "blink.py", line 58, in <module>
    inst.convert(hdl="VHDL")
  ...
myhdl.ConversionError: in file blink.py, line 51:
    Object type is not supported in this context: PATTERN_SOS, <class 'myhdl._intbv.intbv'>

In Python there should be absolutely no difference in behaviour between an alias and the aliased object, but in this case there seems to be a distinction made. Can anyone shed light on this please? It’s unexpected to me.


#2

I don’t think initial values are enabled by default, you have to set it. Some of the conversion arguments haven’t been fully documented in the move from toV* to inst.convert(initial_values=True).


#3

Ah, I’ll try this - thank you.


#4

@meowsqueak
Basically, MyHDL “runs” the code when simulating but “interpret” it when converting. Also, there is a converter for VHDL and a converter for VERILOG.

This means you can simulate code than can’t be converted.
For example, a FIFO can be modelled with a simple list. You can simulate your design with this model but you can’t convert it.
This is cool because you can simulate everything you want, but you have to be careful when designing “convertible” modules.

Your assumption that you will convert to verilog and VHDL to check conversion is not good. As I said, verilog converter and VHDL converter are separate. There might be a bug in one converter that is not present in the other. There might be functionalities supported in one converter that are not supported in the other. On my side I have enhanced the VHDL converter to suit my needs but not the verilog one since I don’t use it and I don’t have enough verilog knowledge.

There is no “Constant” type in MyHDL for now. It has been discussed to add this functionality but it is not implemented yet.

One workaround is :

def Constant(data_type):
    """ Pseudo constant (a signal is writable) """
    const = Signal(data_type)
    const.driven = True         # Remove warning
    return const


PATTERN_SOS = intbv("101010001110111011100010101") 

@block def Blink(clk, clk_en, led): 
    pattern = Constant(PATTERN_SOS)
    counter = Signal(modbv(0, min=0, max=32))
...

VHDL constant value overflow