Literals & Signals
Literals
Logic
Logic
is three-state (0, 1, and X) and has an arbitrary length. Two bits are used to represent a three-state value: 00
as zero, 10
as one, and both 01
and 11
as the unknown state.
Logic(1,2) # 0...x1
Logic(3) # 0...11
Logic(-1) # 1...1
Logic('xx') # 0...xx
Logic('x1x1') | Logic('1x1x') # 0...1111
For convenience, ==
and !=
between Logic
and other literals return a python bool
.
Logic('11') == 3 # True
Logic('x1') == 3 # False
Logic(0,3) == Logic(3,3) # True
Explicit Logic
literal are usually unnecessary.
BitPat
BitPat
is three-state (0, 1, and don’t care) and has a fixed length. It is only used in comparation.
BitPat('11??') # 4'b11??
strings
Python strings are usually converted into Logic
automatically.
'0011_1100' # 8'b00111100
'4:b111111' # 4'b1111
'8:hab' # 8'hab
'-d3' # 3'b101
'4:-d3' # 4'b1101
'16.x:habc' # 16'hxabc
Signals
PyHGL models digital circuits as a direct graph of Gate
and SignalData
nodes. Writer
is the edge from gate to data, while Reader
is the edge from data to gate.
Signals are
Reader
, which contains aSignalType
and aSignalData
SignalType
indicates signal type and bit width.SignalData
contains the real three-state singal value that is unique for each signal.
Type castings are only allowed for same bit length.
UInt
UInt[w]
is the most basic signal type, similar as logic [w-1:0]
in SystemVerilog. A SignalType
is callable and return a signal instance.
# lines below are the same
UInt[8](1)
UInt[8]('1')
UInt('8:b1')
UInt(1, w=8)
Other
uint8_t = UInt[8] # signal type: 8-bit unsigned integer
sint32_t = SInt[32] # signal type: 32-bit signed integer
vector_t = 4 ** uint8_t # signal type: packed array of 4x8 bits
mem_t = MemArray[1024,8] # signal type: unpacked array of 1024x8 bits
struct_t = Struct(
a = vector_t @ 0, # field 'a' starts from 0
b = sint32_t @ 0, # field 'b' starts from 0
c = UInt[32] @ 32, # field 'c' starts from 32
) # signal type: 64-bit structure
x = struct_t({
'a': [1,2,3,4],
'c': Logic('xxxx1100'),
}) # signal x has an initial value of 64'hxc04030201
y = UInt[64](x) # type casting
Array
Array
is not a hardware type, but a tree-like data struct like awkward-array. Array
is used for vectorized operations and module ports.
Array
can be either a named array likeDict[str, Any]
or a listList[Any]
supports advanced slicing
operators on
Array
are vectorized and broadcastuse function
Bundle
to generate a named array
# 1-d vector
Array([1,2,3,4])
Bundle(1,2,3,4)
# 2-d vector
Array([[1,2],[3,4]], recursive=True)
# named array
Array({'a':1, 'b':2})
Bundle(a=1, b=2)
Useful Functions
Array.zeros(2,3) # Array([[0,0,0],[0,0,0]], recursive=True)
UInt.zeros(2,3) # Array([[UInt(0), UInt(0), UInt(0)],[UInt(0),UInt(0),UInt(0)]], recursive=True)
Logic(-1).to_bin(4) # '1111'
Logic(-1).to_hex(16) # 'ffff'
Logic(-1).to_int(1) # -1