1717from amaranth .lib import io , wiring , stream , cdc , enum
1818from amaranth .lib .wiring import In , Out
1919
20- from glasgow .abstract import AbstractAssembly , GlasgowPin
20+ from glasgow .abstract import AbstractAssembly , GlasgowPin , ClockDivisor
2121from glasgow .applet import GlasgowAppletV2 , GlasgowAppletError
2222
2323
@@ -48,9 +48,10 @@ class AUDComponent(wiring.Component):
4848 i_stream : In (stream .Signature (8 ))
4949 o_stream : Out (stream .Signature (8 ))
5050
51- def __init__ (self , ports , period_cyc ):
51+ divisor : In (16 )
52+
53+ def __init__ (self , ports ):
5254 self ._ports = ports
53- self ._period_cyc = period_cyc
5455
5556 super ().__init__ ()
5657
@@ -72,7 +73,7 @@ def elaborate(self, platform):
7273 m .submodules += cdc .FFSynchronizer (audata .i , audata_i )
7374
7475 # FSM related signals
75- timer = Signal ( range ( self ._period_cyc ) )
76+ timer = Signal . like ( self .divisor )
7677 data = Signal (4 )
7778
7879 # Main State Machine
@@ -124,53 +125,53 @@ def elaborate(self, platform):
124125
125126 # Strobe clock
126127 m .d .sync += audck .o .eq (0 )
127- m .d .sync += timer .eq (self . _period_cyc - 1 )
128+ m .d .sync += timer .eq (0 )
128129 m .next = "OUT-CLOCK-0"
129130
130131 # Wait for clock period to pass, then set clock high
131132 with m .State ("OUT-CLOCK-0" ):
132- with m .If (timer == 0 ):
133+ with m .If (timer == self . divisor ):
133134 m .d .sync += audck .o .eq (1 )
134- m .d .sync += timer .eq (self . _period_cyc - 1 )
135+ m .d .sync += timer .eq (0 )
135136 m .next = "OUT-CLOCK-1"
136137 with m .Else ():
137- m .d .sync += timer .eq (timer - 1 )
138+ m .d .sync += timer .eq (timer + 1 )
138139
139140 # Wait for clock period to pass, then return to command reception
140141 with m .State ("OUT-CLOCK-1" ):
141- with m .If (timer == 0 ):
142+ with m .If (timer == self . divisor ):
142143 m .next = "RECV-COMMAND"
143144 with m .Else ():
144- m .d .sync += timer .eq (timer - 1 )
145+ m .d .sync += timer .eq (timer + 1 )
145146
146147 # Strobe clock, then read data on the rising edge. Send to PC
147148 with m .State ("INP" ):
148149 m .d .sync += audata .oe .eq (0 ) # Switch AUDATA pins to input
149150
150151 # Strobe clock
151152 m .d .sync += audck .o .eq (0 )
152- m .d .sync += timer .eq (self . _period_cyc - 1 )
153+ m .d .sync += timer .eq (9 )
153154 m .next = "INP-CLOCK-0"
154155
155156 # Wait for clock period to pass, then sample data and set clock high
156157 with m .State ("INP-CLOCK-0" ):
157- with m .If (timer == 0 ):
158+ with m .If (timer == self . divisor ):
158159 m .d .sync += audck .o .eq (1 )
159- m .d .sync += timer .eq (self . _period_cyc - 1 )
160+ m .d .sync += timer .eq (0 )
160161
161162 # Sample data on rising edge
162163 m .d .sync += data .eq (audata_i )
163164
164165 m .next = "INP-CLOCK-1"
165166 with m .Else ():
166- m .d .sync += timer .eq (timer - 1 )
167+ m .d .sync += timer .eq (timer + 1 )
167168
168169 # Wait for clock period to pass, then send data to PC
169170 with m .State ("INP-CLOCK-1" ):
170- with m .If (timer == 0 ):
171+ with m .If (timer == self . divisor ):
171172 m .next = "SEND-DATA"
172173 with m .Else ():
173- m .d .sync += timer .eq (timer - 1 )
174+ m .d .sync += timer .eq (timer + 1 )
174175
175176 # Send the sampled data to the output stream, return to command reception
176177 with m .State ("SEND-DATA" ):
@@ -192,9 +193,14 @@ def __init__(self, logger: logging.Logger, assembly: AbstractAssembly, *,
192193 ports = assembly .add_port_group (audata = audata , audsync = audsync , audck = audck , audmd = audmd , audrst = audrst )
193194 component = assembly .add_submodule (AUDComponent (
194195 ports ,
195- period_cyc = round (1 / (assembly .sys_clk_period * frequency )),
196196 ))
197197 self ._pipe = assembly .add_inout_pipe (component .o_stream , component .i_stream )
198+ self ._clock = assembly .add_clock_divisor (component .divisor ,
199+ ref_period = assembly .sys_clk_period , name = "audclk" )
200+
201+ @property
202+ def clock (self ) -> ClockDivisor :
203+ return self ._clock
198204
199205 async def _cmd (self , cmd : AUDCommand , val = 0 ):
200206 assert val <= 0xF , "Value must be less than 0xF"
@@ -292,6 +298,8 @@ def add_build_arguments(cls, parser, access):
292298 access .add_pins_argument (parser , "audrst" , required = True )
293299 access .add_pins_argument (parser , "audmd" , required = True )
294300
301+ @classmethod
302+ def add_setup_arguments (cls , parser ):
295303 parser .add_argument (
296304 "-f" , "--frequency" , metavar = "FREQ" , type = int , default = 100 ,
297305 help = "set clock period to FREQ kHz (default: %(default)s)" )
@@ -330,6 +338,8 @@ def length(x):
330338 required = True ,
331339 help = "write memory contents to FILENAME" )
332340
341+ async def setup (self , args ):
342+ await self .aud_iface .clock .set_frequency (args .frequency * 1000 )
333343
334344 def build (self , args ):
335345 with self .assembly .add_applet (self ):
0 commit comments