Lab 5: Hardware types
Até agora estamos usando mal os recursos do MyHDL, o componente adder
anterior poderia ser muito mais simples se:
- Pudéssemos tratar sinais como
inteiros
- Não precisássemos implementar o
adder
(x + y)
Para isso o MyHDL possui outros dois tipos de dados além do bool
: o intbv
e o modbv
.
Hardware design involves dealing with bits and bit-oriented operations. The standard Python type int has most of the desired features, but lacks support for indexing and slicing. For this reason, MyHDL provides the intbv class. The name was chosen to suggest an integer with bit vector flavor.
Do mamual: http://docs.myhdl.org/en/stable/manual/hwtypes.html
modbv
Info
A principal diferença entre o modbv
e o intbv
é que o sinal do tipo modbv
trunca o valor da variável para o seu máximo e mínimo, já o intbv
lança um erro quando isso acontecer. Na implementação do hardware não existe diferença nenhuma. Apenas na execução do módulo a nível de simulação.
O modbv possibilita trabalharmos com um vetor de bits como se fosse um único bloco de dados, diferente do bool
na qual os bits não possuem relação entre si. Agora conseguimos trabalhar com valores inteiros (signed
e unsigned
) muito similar ao que já estamos acostumados no python:
>>> a = modbv(24)
>>> b = modbv(2)
>>> print(a)
24
>>> print(a + b)
26
>>> print(a == 12)
False
>>> a = b
>>> a
2
Notem que conseguimos:
- somar dois vetores de bits
a+b
- atribuir um vetor a outro
a=b
O modbv
não limita a quantidade de bits que será utilizado, isso funciona muito bem na simulação, mas quando formos gerar um hardware temos que definir o tamanho do vetor caso contrário teremos erro na conversão.
O exemplo a seguir indica como criarmos um sinal cnt
com 32 bits:
# cnt com 32 bits do tipo modbv
>>> cnt = Signal(modbv(0)[32:])
>>> cnt.max
4294967296
>>> cnt.min
0
Outra opcão é definir o tamanho do vetor com base nos valores máximos e mínimos:
a = modbv(12, min=0, max=16)
bits
O modbv
possibilita acessarmos bits individualmente, assim como fazíamos com o vetor de bits:
>>> from myhdl import bin
>>> a = modbv(24)
>>> bin(a)
'11000'
# Bit indexing
>>> int(a[0])
0
>>> int(a[3])
1
>>> b = modbv(-23)
>>> bin(b)
'101001'
>>> int(b[0])
1
>>> int(b[3])
1
>>> int(b[4])
0
'11000'
# Bit slicing
>>> a[4:1]
modbv(4)
>>> bin(a[4:1])
'100'
>>> a[4:1] = 0b001
>>> bin(a)
'10010'
>>> a
modbv(18)
Add
Usando esse novo tipo, podemos reimplementar o adder
assumindo que as entradas x
e y
e a saída soma
são vetores, e que carry
é um bool
:
@block
def adderIntbv(x, y, soma, carry):
@always_comb
def comb():
sum = x + y
soma.next = sum
if sum > x.max - 1:
carry.next = 1
else:
carry.next = 0
return comb
Note que para o carry
utilizamos o valor máximo que x
pode assumir e que isso é dinâmico, de acordo com o tamanho de x
. Como no exemplo a seguir:
@block
def runAdder():
x = Signal(modbv()[2:])
y = Signal(modbv()[2:])
s = Signal(modbv()[2:])
c = Signal(bool())
dut = adderIntbv(x, y, s, c)
Exercise
Exercise