#!/usr/bin/env python # coding: utf-8 # # Example: Hysteresis with simple FSM # In[1]: from cyhdl import * # We create a little state machine with three states as shown below. Note: Upon reset, the `@always_seq` logic implicitely resets `state` variable to `NEUTRAL` state. # In[2]: @block def hysteresis( clk : ClkSignal, reset : ResetSignal, a : Signal, q0 : Signal.Output, q1 : Signal.Output, *, LOWER : int = 0, UPPER : int = 255 ): t_state = enum('NEUTRAL', 'OVER', 'UNDER', name='t_state') state = Signal(t_state.NEUTRAL) @always_seq(clk.posedge, reset) def worker(): if state == t_state.OVER: if a < LOWER: state.next = t_state.UNDER elif state == t_state.UNDER: if a > UPPER: state.next = t_state.OVER else: if a < LOWER: state.next = t_state.UNDER elif a > UPPER: state.next = t_state.OVER @always_comb def assign(): if state == t_state.OVER: q0.next = False q1.next = True elif state == t_state.UNDER: q0.next = True q1.next = False else: q0.next = False q1.next = False return instances() # Then we create a test bench with a bit of ramping stimulus: # In[3]: from myirl.test.common_test import run_ghdl, gen_osc @block def testbench_hyst(SIZE = 6): clk = ClkSignal() rst = ResetSignal(0, 1, isasync = False) val = Signal(intbv()[SIZE:]) lo, hi = [ Signal(bool()) for i in range(2) ] inst = hysteresis(clk = clk, reset = rst, a = val, q0 = lo, q1 = hi, LOWER = 4, UPPER = 16) cg = gen_osc(clk, CYCLE = 1) N = 2 ** SIZE @instance def stim(): val.next = 8 rst.next = True yield delay(10) rst.next = False for i in range(8, N): val.next = i yield delay(2) for i in range(N-1, -1, -1): val.next = i yield delay(2) val.next = 8 rst.next = True yield delay(10) rst.next = False for i in range(8, -1, -1): val.next = i yield delay(5) for i in range(0, N): val.next = i yield delay(2) return instances() # In[4]: def test(): tb = testbench_hyst() files = tb.elab(targets.VHDL, elab_all = True) run_ghdl(files, tb, vcdfile='hyst.vcd', debug=True) return files # In[5]: f = test() # As a result, the wave trace (download [hyst.vcd](hyst.vcd)) displays as follows in GTKwave: # ![Wave trace](wave.png) # In[6]: get_ipython().system('cat {f[1]}') # In[ ]: