55from enum import IntEnum
66from amaranth import *
77from amaranth .lib import io , data , cdc , wiring , enum
8+ from amaranth .lib import wiring , stream , io
9+ from amaranth .lib .wiring import In , Out
810
9- from ... import *
11+
12+ # from ... import *
13+ from ... import GlasgowAppletV2
1014
1115"""
1216GPIB / IEEE-488 is a 16 line bus, with a single controller (in this case, the
@@ -109,12 +113,15 @@ class GPIBStatus(enum.Enum, shape=8):
109113 Error = 16
110114
111115
112- class GPIBSubtarget (Elaboratable ):
113- def __init__ (self , ports , in_fifo , out_fifo , status ):
116+ class GPIBComponent (wiring .Component ):
117+ i_stream : In (stream .Signature (8 ))
118+ o_stream : Out (stream .Signature (8 ))
119+
120+ def __init__ (self , ports ):
114121 self .ports = ports
115- self .in_fifo = in_fifo
116- self . out_fifo = out_fifo
117- self .status = status
122+ # self.status = status
123+
124+ self .status = Signal ( 8 )
118125
119126 self .dio_i = Signal (8 ) # Data Lines Listen
120127 self .dio_o = Signal (8 ) # Talk
@@ -134,18 +141,20 @@ def __init__(self, ports, in_fifo, out_fifo, status):
134141 self .talking = Signal ()
135142 self .listening = Signal ()
136143
144+ super ().__init__ ()
145+
137146 def elaborate (self , platform ):
138147 m = Module ()
139148
140- m .submodules .dio_buffer = dio_buffer = io .Buffer ("io" , ~ self .ports .dio )
141- m .submodules .eoi_buffer = eoi_buffer = io .Buffer ("io" , ~ self .ports .eoi )
142- m .submodules .dav_buffer = dav_buffer = io .Buffer ("io" , ~ self .ports .dav )
143- m .submodules .nrfd_buffer = nrfd_buffer = io .Buffer ("io" , ~ self .ports .nrfd )
144- m .submodules .ndac_buffer = ndac_buffer = io .Buffer ("io" , ~ self .ports .ndac )
145- m .submodules .srq_buffer = srq_buffer = io .Buffer ("i" , ~ self .ports .srq )
146- m .submodules .ifc_buffer = ifc_buffer = io .Buffer ("o" , ~ self .ports .ifc )
147- m .submodules .atn_buffer = atn_buffer = io .Buffer ("o" , ~ self .ports .atn )
148- m .submodules .ren_buffer = ren_buffer = io .Buffer ("o" , ~ self .ports .ren )
149+ m .submodules .dio_buffer = dio_buffer = io .Buffer ("io" , self .ports .dio )
150+ m .submodules .eoi_buffer = eoi_buffer = io .Buffer ("io" , self .ports .eoi )
151+ m .submodules .dav_buffer = dav_buffer = io .Buffer ("io" , self .ports .dav )
152+ m .submodules .nrfd_buffer = nrfd_buffer = io .Buffer ("io" , self .ports .nrfd )
153+ m .submodules .ndac_buffer = ndac_buffer = io .Buffer ("io" , self .ports .ndac )
154+ m .submodules .srq_buffer = srq_buffer = io .Buffer ("i" , self .ports .srq )
155+ m .submodules .ifc_buffer = ifc_buffer = io .Buffer ("o" , self .ports .ifc )
156+ m .submodules .atn_buffer = atn_buffer = io .Buffer ("o" , self .ports .atn )
157+ m .submodules .ren_buffer = ren_buffer = io .Buffer ("o" , self .ports .ren )
149158
150159 m .submodules += [
151160 cdc .FFSynchronizer (dio_buffer .i , self .dio_i ),
@@ -177,16 +186,17 @@ def elaborate(self, platform):
177186 ren_buffer .o .eq (self .ren_o ),
178187 ]
179188
180- settle_delay = math .ceil (platform .default_clk_frequency * 1e-6 )
189+ # settle_delay = math.ceil(platform.default_clk_frequency * 1e-6)
190+ settle_delay = 1000
181191 timer = Signal (range (1 + settle_delay ))
182192
183- m .d .comb += [
184- platform .request ("led" , 0 ).o .eq (self .status == 0 ),
185- platform .request ("led" , 1 ).o .eq (self .status == 1 ),
186- platform .request ("led" , 2 ).o .eq (self .status == 2 ),
187- platform .request ("led" , 3 ).o .eq (self .status == 4 ),
188- platform .request ("led" , 4 ).o .eq (self .status == 8 ),
189- ]
193+ # m.d.comb += [
194+ # platform.request("led", 0).o.eq(self.status == 0),
195+ # platform.request("led", 1).o.eq(self.status == 1),
196+ # platform.request("led", 2).o.eq(self.status == 2),
197+ # platform.request("led", 3).o.eq(self.status == 4),
198+ # platform.request("led", 4).o.eq(self.status == 8),
199+ # ]
190200
191201 l_control = Signal (data .StructLayout ({
192202 "tx" : 1 ,
@@ -203,9 +213,9 @@ def elaborate(self, platform):
203213 with m .FSM ():
204214 with m .State ("Control: Begin" ):
205215 m .d .sync += self .status .eq (GPIBStatus .Idle )
206- m .d .comb += self .out_fifo . r_en .eq (1 )
207- with m .If (self .out_fifo . r_rdy ):
208- m .d .sync += l_control .eq (self .out_fifo . r_data )
216+ m .d .comb += self .i_stream . ready .eq (1 )
217+ with m .If (self .i_stream . valid ):
218+ m .d .sync += l_control .eq (self .i_stream . payload )
209219 m .next = "Control: Read data"
210220
211221 with m .State ("Control: Read data" ):
@@ -216,9 +226,9 @@ def elaborate(self, platform):
216226 m .next = "Control: Parse"
217227 with m .Else ():
218228 m .d .sync += self .status .eq (GPIBStatus .Control )
219- m .d .comb += self .out_fifo . r_en .eq (1 )
220- with m .If (self .out_fifo . r_rdy ):
221- m .d .sync += l_data .eq (self .out_fifo . r_data )
229+ m .d .comb += self .i_stream . ready .eq (1 )
230+ with m .If (self .i_stream . valid ):
231+ m .d .sync += l_data .eq (self .i_stream . payload )
222232 m .next = "Control: Parse"
223233
224234 with m .State ("Control: Parse" ):
@@ -248,10 +258,10 @@ def elaborate(self, platform):
248258 # resistor configuration from changing
249259 # mid-transaction.
250260 m .d .comb += [
251- self .in_fifo . w_en .eq (1 ),
252- self .in_fifo . w_data .eq (GPIBMessage ._Acknowledge ),
261+ self .o_stream . valid .eq (1 ),
262+ self .o_stream . payload .eq (GPIBMessage ._Acknowledge ),
253263 ]
254- with m .If (self .in_fifo . w_rdy ):
264+ with m .If (self .o_stream . ready ):
255265 m .next = "Control: Begin"
256266
257267 with m .State ("Talk: Begin" ):
@@ -297,18 +307,18 @@ def elaborate(self, platform):
297307
298308 with m .State ("Listen: Management lines" ):
299309 m .d .comb += [
300- self .in_fifo . w_en .eq (1 ),
301- self .in_fifo . w_data .eq (Cat (1 , self .eoi_i ))
310+ self .o_stream . valid .eq (1 ),
311+ self .o_stream . payload .eq (Cat (1 , self .eoi_i )),
302312 ]
303- with m .If (self .in_fifo . w_rdy ):
313+ with m .If (self .o_stream . ready ):
304314 m .next = "Listen: DIO lines"
305315
306316 with m .State ("Listen: DIO lines" ):
307317 m .d .comb += [
308- self .in_fifo . w_en .eq (1 ),
309- self .in_fifo . w_data .eq (self .dio_i ),
318+ self .o_stream . valid .eq (1 ),
319+ self .o_stream . payload .eq (self .dio_i ),
310320 ]
311- with m .If (self .in_fifo . w_rdy ):
321+ with m .If (self .o_stream . ready ):
312322 m .d .sync += self .nrfd_o .eq (0 )
313323 m .next = "Listen: DAV unassert"
314324
@@ -321,35 +331,59 @@ def elaborate(self, platform):
321331
322332
323333class GPIBControllerInterface :
324- def __init__ (self , interface , logger , port_spec , listen_pull_high , talk_pull_high ):
325- self .interface = interface
334+ def __init__ (self , logger , assembly , * , dio , eoi , dav , nrfd , ndac , srq , ifc , atn , ren ):
326335 self .logger = logger
336+ self .assembly = assembly
337+
338+ # These are used for pull ups, so we need them later.
339+ self ._dio = dio
340+ self ._eoi = eoi
341+ self ._dav = dav
342+ self ._nrfd = nrfd
343+ self ._ndac = ndac
344+ self ._srq = srq
345+
346+ ports = assembly .add_port_group (dio = dio , eoi = eoi , dav = dav , nrfd = nrfd ,
347+ ndac = ndac , srq = srq , ifc = ifc , atn = atn , ren = ren )
348+ component = assembly .add_submodule (GPIBComponent (ports ))
349+ self ._pipe = assembly .add_inout_pipe (component .o_stream , component .i_stream )
350+
351+ self ._sys_clk_period = assembly .sys_clk_period
327352
328- self .port_spec = port_spec
329- self .listen_pull_high = listen_pull_high
330- self .talk_pull_high = talk_pull_high
331353
332354 async def write (self , message : GPIBMessage , data = bytes ([0 ])):
333- await self .interface .device .set_pulls (self .port_spec , high = {pin .number for pin in self .talk_pull_high })
355+ self .assembly .use_pulls ({
356+ self ._dio : "high" ,
357+ self ._eoi : "high" ,
358+ self ._dav : "high" ,
359+
360+ })
361+ await self .assembly .configure_ports ()
334362
335363 for b in data :
336- await self .interface . write (bytes ([message .value ]))
337- await self .interface . write (bytes ([b ]))
338- ack = (await self .interface . read (1 ))[0 ]
364+ await self ._pipe . send (bytes ([message .value ]))
365+ await self ._pipe . send (bytes ([b ]))
366+ ack = (await self ._pipe . recv (1 ))[0 ]
339367 assert GPIBMessage (ack ) == GPIBMessage ._Acknowledge
340368
341369 async def read (self , * , to_eoi = True ):
342- await self .interface .device .set_pulls (self .port_spec , high = {pin .number for pin in self .listen_pull_high })
370+ self .assembly .use_pulls ({
371+
372+ self ._nrfd : "high" ,
373+ self ._ndac : "high" ,
374+ self ._srq : "high" ,
375+ })
376+ await self .assembly .configure_ports ()
343377
344378 eoi = False
345379 while not eoi :
346- await self .interface . write (bytes ([GPIBMessage .Listen .value ]))
380+ await self ._pipe . send (bytes ([GPIBMessage .Listen .value ]))
347381
348- eoi = bool ((await self .interface . read (1 ))[0 ] & 2 )
382+ eoi = bool ((await self ._pipe . recv (1 ))[0 ] & 2 )
349383 if not to_eoi :
350384 eoi = True
351385
352- yield (await self .interface .read (1 ))
386+ yield (await self .interface .recv (1 ))
353387
354388 async def send_to (self , address , data ):
355389 await self .cmd_talk (address )
@@ -360,13 +394,13 @@ async def send_to(self, address, data):
360394 async def read_from (self , address , * , to_eoi = True ):
361395 await self .cmd_listen (address )
362396 all = bytes ([])
363- async for data in self .read (to_eoi = to_eoi ):
397+ async for data in self .recv (to_eoi = to_eoi ):
364398 all += data
365399 return all
366400
367401 async def iter_from (self , address , * , to_eoi = True ):
368402 await self .cmd_listen (address )
369- async for data in self .read (to_eoi = to_eoi ):
403+ async for data in self .recv (to_eoi = to_eoi ):
370404 yield data
371405
372406 async def cmd_talk (self , address ):
@@ -400,7 +434,7 @@ async def ifc(self):
400434 await self .write (GPIBMessage .InterfaceClear )
401435
402436
403- class GPIBControllerApplet (GlasgowApplet ):
437+ class GPIBControllerApplet (GlasgowAppletV2 ):
404438 logger = logging .getLogger (__name__ )
405439 help = "talk to a gpib device"
406440 description = """
@@ -412,56 +446,29 @@ class GPIBControllerApplet(GlasgowApplet):
412446 def add_build_arguments (cls , parser , access ):
413447 super ().add_build_arguments (parser , access )
414448
415- access .add_pin_set_argument (parser , "dio" , width = range (0 , 8 ), default = (0 ,1 ,2 ,3 ,15 ,14 ,13 ,12 ))
416- access .add_pin_argument (parser , "eoi" , default = 4 )
417- access .add_pin_argument (parser , "dav" , default = 5 )
418- access .add_pin_argument (parser , "nrfd" , default = 6 )
419- access .add_pin_argument (parser , "ndac" , default = 7 )
420- access .add_pin_argument (parser , "srq" , default = 9 )
421- access .add_pin_argument (parser , "ifc" , default = 10 )
422- access .add_pin_argument (parser , "atn" , default = 8 )
423- access .add_pin_argument (parser , "ren" , default = 11 )
424-
425- def build (self , target , args ):
426- status , self .__addr_status = target .registers .add_ro (8 )
427-
428- self .mux_interface = iface = target .multiplexer .claim_interface (self , args )
429- subtarget = iface .add_subtarget (GPIBSubtarget (
430- ports = iface .get_port_group (
431- dio = args .pin_set_dio ,
432- eoi = args .pin_eoi ,
433- dav = args .pin_dav ,
434- nrfd = args .pin_nrfd ,
435- ndac = args .pin_ndac ,
436- srq = args .pin_srq ,
437- ifc = args .pin_ifc ,
438- atn = args .pin_atn ,
439- ren = args .pin_ren ,
440- ),
441- in_fifo = iface .get_in_fifo (),
442- out_fifo = iface .get_out_fifo (),
443- status = status
444- ))
445-
446- self ._sample_freq = target .sys_clk_freq
449+ access .add_pins_argument (parser , "dio" , width = 8 , default = "A0,A1,A2,A3,B7,B6,B5,B4" )
450+ access .add_pins_argument (parser , "eoi" , default = "A4" )
451+ access .add_pins_argument (parser , "dav" , default = "A5" )
452+ access .add_pins_argument (parser , "nrfd" , default = "A6" )
453+ access .add_pins_argument (parser , "ndac" , default = "A7" )
454+ access .add_pins_argument (parser , "srq" , default = "B1" )
455+ access .add_pins_argument (parser , "ifc" , default = "B2" )
456+ access .add_pins_argument (parser , "atn" , default = "B0" )
457+ access .add_pins_argument (parser , "ren" , default = "B3" )
458+
459+ def build (self , args ):
460+ with self .assembly .add_applet (self ):
461+ self .assembly .use_voltage (args .voltage )
462+ self .gpib_iface = GPIBControllerInterface (self .logger , self .assembly ,
463+ dio = args .dio , eoi = args .eoi , dav = args .dav , nrfd = args .nrfd , ndac = args .ndac ,
464+ srq = args .srq , ifc = args .ifc , atn = args .atn , ren = args .ren )
447465
448466 @classmethod
449- def add_run_arguments (cls , parser , access ):
450- super ().add_run_arguments (parser , access )
451-
452- async def run (self , device , args ):
453- iface = await device .demultiplexer .claim_interface (self , self .mux_interface , args )
454- gpib_interface = GPIBControllerInterface (
455- interface = iface ,
456- logger = self .logger ,
457- port_spec = args .port_spec ,
458- listen_pull_high = {* args .pin_set_dio , args .pin_eoi , args .pin_dav },
459- talk_pull_high = {args .pin_nrfd , args .pin_ndac , args .pin_srq }
460- )
461- return gpib_interface
467+ def add_run_arguments (cls , parser ):
468+ super ().add_run_arguments (parser )
462469
463470 @classmethod
464- def add_interact_arguments (cls , parser ):
471+ def add_setup_arguments (cls , parser ):
465472 def check_address (value ):
466473 address = int (value )
467474 if address < 0 or address > 30 :
@@ -478,12 +485,12 @@ def check_address(value):
478485 "--read-eoi" , action = "store_true" ,
479486 help = "read until EOI, omit if no response expected" )
480487
481- async def interact (self , device , args , iface ):
488+ async def run (self , args ):
482489 if args .command :
483- await iface .send_to (args .address , args .command .encode ("ascii" ))
490+ await self . gpib_iface .send_to (args .address , args .command .encode ("ascii" ))
484491
485492 if args .read_eoi :
486- async for data in iface .iter_from (args .address , to_eoi = True ):
493+ async for data in self . gpib_iface .iter_from (args .address , to_eoi = True ):
487494 sys .stdout .buffer .write (data )
488495 sys .stdout .buffer .flush ()
489496
0 commit comments