Boolean pitfalls

In classic myHDL you can do this:

In [1]:
from myhdl import *
In [2]:
@block
def unit():
    a, b, c, d = [ Signal(bool()) for _ in range(4) ]
    clk = Signal(bool(0))
    
    @always(clk.posedge)
    def worker():
        if ((a == True) and b == False and (c == True)):
            d.next = (a == True) and b == False and (c == True)
    
    return instances()
In [3]:
u = unit()
u.convert('vhdl')
/home/testing/.local/lib/python3.9/site-packages/myhdl/conversion/_toVHDL.py:500: ToVHDLWarning: Signal is not driven: clk
  warnings.warn("%s: %s" % (_error.UndrivenSignal, s._name),
/home/testing/.local/lib/python3.9/site-packages/myhdl/conversion/_toVHDL.py:500: ToVHDLWarning: Signal is not driven: a
  warnings.warn("%s: %s" % (_error.UndrivenSignal, s._name),
/home/testing/.local/lib/python3.9/site-packages/myhdl/conversion/_toVHDL.py:500: ToVHDLWarning: Signal is not driven: b
  warnings.warn("%s: %s" % (_error.UndrivenSignal, s._name),
/home/testing/.local/lib/python3.9/site-packages/myhdl/conversion/_toVHDL.py:500: ToVHDLWarning: Signal is not driven: c
  warnings.warn("%s: %s" % (_error.UndrivenSignal, s._name),
/home/testing/.local/lib/python3.9/site-packages/myhdl/conversion/_toVHDL.py:467: ToVHDLWarning: Signal is driven but not read: d
  warnings.warn("%s: %s" % (_error.UnreadSignal, s._name),
Out[3]:
<myhdl._block._Block at 0x7f73bc0e9ac0>
In [4]:
!grep -A 5 WORKER  unit.vhd
UNIT_WORKER: process (clk) is
begin
    if rising_edge(clk) then
        if ((a = '1') and (b = '0') and (c = '1')) then
            d <= stdl((a = '1') and (b = '0') and (c = '1'));
        end if;
--
end process UNIT_WORKER;

end architecture MyHDL;

However, when you change the and to &, the precedence will fool you:

In [5]:
@block
def unit2():
    a, b, c, d = [ Signal(bool()) for _ in range(4) ]
    clk = Signal(bool(0))
    
    @always(clk.posedge)
    def worker():
        if ((a == True) & b == False & (c == True)):
            d.next = (a == True) & b == False & (c == True)
    
    return instances()
In [6]:
u = unit2()
u.convert('vhdl')
Out[6]:
<myhdl._block._Block at 0x7f73bc0e9dc0>
In [7]:
! diff unit2.vhd unit.vhd | grep -A 6 WORKER
< UNIT2_WORKER: process (clk) is
---
> UNIT_WORKER: process (clk) is
39,40c39,40
<         if ((stdl(a = '1') and b) = ('0' and stdl(c = '1'))) then
<             d <= stdl((stdl(a = '1') and b) = ('0' and stdl(c = '1')));
---
>         if ((a = '1') and (b = '0') and (c = '1')) then
>             d <= stdl((a = '1') and (b = '0') and (c = '1'));
--
< end process UNIT2_WORKER;
---
> end process UNIT_WORKER;

Bool adding

In [8]:
@block
def unit3(clk):
    b, c, d = [ Signal(bool()) for _ in range(3) ]
    a = Signal(intbv()[3:])
    
    @always(clk.posedge)
    def worker():
        a.next = b + c
        d.next = b + c
        
    @instance
    def run():
        b.next = True
        print("WOW")
        yield delay(3)
        print("D:", a)
        # raise StopSimulation
    
    return instances()
In [9]:
@block
def tb():
    clk = Signal(bool(0))

    @always(delay(1))
    def clkgen():
        clk.next = not clk
        
    uut = unit3(clk)
    
    return instances()
In [10]:
u = tb()
u.config_sim(trace=True)
u.run_sim(4)
print("QUIT")
u.quit_sim()
WOW
D: 1
QUIT
<class 'myhdl._SuspendSimulation'>: Simulated 4 timesteps
In [11]:
clk = Signal(bool(0))
u = unit3(clk)
u.convert('vhdl')
Out[11]:
<myhdl._block._Block at 0x7f73ad761f70>
In [12]:
!cat -n unit3.vhd
     1	-- File: unit3.vhd
     2	-- Generated by MyHDL 0.11
     3	-- Date: Sun Feb 13 08:09:25 2022
     4	
     5	
     6	library IEEE;
     7	use IEEE.std_logic_1164.all;
     8	use IEEE.numeric_std.all;
     9	use std.textio.all;
    10	
    11	use work.pck_myhdl_011.all;
    12	
    13	entity unit3 is
    14	    port (
    15	        clk: in std_logic
    16	    );
    17	end entity unit3;
    18	
    19	
    20	architecture MyHDL of unit3 is
    21	
    22	
    23	
    24	signal a: unsigned(2 downto 0);
    25	signal b: std_logic;
    26	signal c: std_logic;
    27	signal d: std_logic;
    28	
    29	begin
    30	
    31	
    32	c <= '0';
    33	
    34	
    35	UNIT3_WORKER: process (clk) is
    36	begin
    37	    if rising_edge(clk) then
    38	        a <= (to_unsigned(b, 3) + to_unsigned(c, 1));
    39	        d <= (to_unsigned(b, 1) + to_unsigned(c, 1));
    40	    end if;
    41	end process UNIT3_WORKER;
    42	
    43	UNIT3_RUN: process is
    44	    variable L: line;
    45	begin
    46	    b <= '1';
    47	    write(L, string'("WOW"));
    48	    writeline(output, L);
    49	    wait for 3 * 1 ns;
    50	    write(L, string'("D:"));
    51	    write(L, string'(" "));
    52	    write(L, to_hstring(a));
    53	    writeline(output, L);
    54	    wait;
    55	end process UNIT3_RUN;
    56	
    57	end architecture MyHDL;
In [13]:
! ghdl -i --std=08 unit3.vhd pck_myhdl_011.vhd
In [14]:
! ghdl -m  --std=08 unit3
unit3.vhd:39:33:error: no function declarations for operator "+"
In [ ]: