Gente que sabe de hardware pero no sabe Python (mis cumpas)
Gente que sabe de Python (mucho!) pero no de hardware
Yo, que sólo sé que no sé nada
En una charla de 30 minutos
programar HW != diseñar HW
- Hw con Funcionamiento y prestaciones predefinidas.
- Ejemplo: Arduino se programa sobre un uC que tiene un firmware.
- Desde el diseño el ASM es un lenguaje de "alto nivel"!
Pero... ¿cómo se diseña un micro?
- Con ustedes los HDL (Hardware Description Language)
- Electrónica digital a través software
- VHDL y Verilog son los más típicos
FPGAs : Field Programmable Gates Array
El camaleón mamá, el camaleón, cambia de colores según la ocasión
—Chico Novarro
Originalmente sólo para prototipar.
- Ahora son baratos, se usan en producción!
>> escala, se fabrican chips ASIC (Application-specific integrated circuit)
- con (casi) el mismo HDL!
library ieee ;
use ieee . std logic 1164 . all ;
entity mux is
port (
a, b : in std logic vector (3 downto 0);
s : in std logic ;
o : out std logic vector (3 downto 0));
end mux;
architecture behavior of mux is
begin behavior
o <= a when s = '0' else b;
end behavior
def mux(s, o, a, b):
"""2-channels N-bits multiplexor
a, b: generic bits input channels
o: output vector
s: channel selector"""
@always_comb
def logic():
if s == 0:
o.next = a
else:
o.next = b
return logic
Y cómo echufamos? Signal (a.k.a "cablecitos")
>>> bus = Signal(0)
>>> bus.val
0
>>> bus.next = 1
>>>
Pero el HW tiene límites físicos ¿cuántos bits tiene ese bus?
>>> val = intbv(1, min=0, max=15) >>> len(val) 4 >>> bus = Signal(val)
def testBench():
I0, I1 = [Signal(intbv(random.randint(0, 255))[32:]) for i in range(2)]
O = Signal(intbv(0)[32:])
S = Signal(intbv(0, min=0, max=2))
mux_inst = mux (S, O, I0, I1)
@instance
def stimulus():
header = "%-6s|%-6s|%-6s|%-6s|%-6s" % ('time', 'I0', 'I1', 'S', 'O')
print header + '\n' + '-' * len(header)
while True:
S.next = intbv(random.randint(0, 1))[1:]
I0.next, I1.next = [intbv(random.randint(0, 255))[32:] for i in range(2)]
print "%-6s|%-6s|%-6s|%-6s|%-6s" % (now(), I0, I1, S, O)
yield delay(5)
return mux_inst, stimulus
sim = Simulation(testBench())
sim.run(20)
time |I0 |I1 |S |O
----------------------------------
0 |35 |96 |0 |0
5 |164 |254 |1 |254
10 |132 |60 |0 |132
15 |32 |138 |0 |32
20 |15 |112 |1 |112
<class 'myhdl._SuspendSimulation'>: Simulated 20 timesteps
tb_4_sim = traceSignals(testBench)
sim = Simulation(tb_4_sim)
sim.run(20)
Se pueden leer con GTKWave
class MuxTest(unittest.TestCase):
def setUp(self):
self.channels = [Signal(intbv(random.randint(0, 255))[32:]) for i in range(2)]
self.O = Signal(intbv(0)[32:])
self.S = Signal(intbv(0, min=0, max=2))
self.mux_inst = mux(self.S, self.O, self.channels[0], self.channels[1])
def test_starts_in_channel_0(self):
yield delay(1)
Simulation( self.mux_inst )
self.assertEqual(self.channels[0].val, self.O.val)
def test_channel_1_when_select_is_1(self):
self.S.next = intbv(1)
yield delay(1)
Simulation( self.mux_inst )
self.assertEqual(self.channels[1].val, self.O.val)
mux_inst = toVHDL(mux, S, O, I0, I1)
mux_inst = toVerilog(mux, S, O, I0, I1)
MyHDL es una opción seria
Algoritmia, RTL, simulación y tests: Python FTW!
La inferencia de patrones para conversion es pura magia
Unittests (y TDD) => diseño de hardware ágil y bien
Le debo mi última materia: hice un procesador MIPS en 3 semanas
for p in preguntas:
try:
responder(p)
except NiPutaIdea:
sonreir_y_hacerse_el_gil()