In traditional HDLs we can mark an endpoint, or port, of a wire as inout, thereby making this port function as both a source and a drain for the signals flowing over the wire.
Clash has support for 'inout' ports through the implementation of _BiSignal_s. To cleanly map to functions (and thus support software simulation using Haskell), a BiSignal comes in two parts; the in part:
domain is the clock- (and reset-) domain to which the memory elements manipulating these BiSignals belong.
Lastly, ds indicates the default behavior for the BiSignal if nothing is being written (pull-down, pull-up, or undefined).
BiSignalIn is used by Clash to generate the inout ports on a HDL level, while BiSignalOut is only used for simulation purposes and generally discarded by the compiler.
Example
The following describes a system where two circuits, in alternating fashion, read the current value from the /bus/, increment it, and write it on the next cycle.
-- | Alternatively read / increment+write
counter :: (Bool, Int)
-- ^ Internal flip + previous read
-> Int
-- ^ Int from inout
-> ((Bool, Int), Maybe Int)
counter (write, prevread) i = ((write', prevread'), output)
where
output = if write then Just (succ prevread) else Nothing
prevread' = if write then prevread else i
write' = not write
-- | Write on odd cyles
f :: Clock System Source
-> Reset System Asynchronous
-> BiSignalIn Undefined System (BitSize Int)
-> BiSignalOut Undefined System (BitSize Int)
f clk rst s = writeToBiSignal s (mealy clk rst counter (False, 0) (readFromBiSignal s))
-- | Write on even cyles
g :: Clock System Source
-> Reset System Asynchronous
-> BiSignalIn Undefined System (BitSize Int)
-> BiSignalOut Undefined System (BitSize Int)
g clk rst s = writeToBiSignal s (mealy clk rst counter (True, 0) (readFromBiSignal s))
-- | Connect the /f/ and /g/ circuits to the same bus
topEntity :: Clock System Source
-> Reset System Asynchronous
-> Signal System Int
topEntity clk rst = readFromBiSignal bus'
where
bus = mergeBiSignalOuts $ f clk rst bus' :> g clk rst bus' :> Nil
bus' = veryUnsafeToBiSignalIn bus
In traditional HDLs we can mark an endpoint, or port, of a wire as inout, thereby making this port function as both a source and a drain for the signals flowing over the wire.
Clash has support for 'inout' ports through the implementation of _BiSignal_s. To cleanly map to functions (and thus support software simulation using Haskell), a BiSignal comes in two parts; the in part:
and the out part:
Where:
BitVector
BitVector
BiSignalIn
is used by Clash to generate theinout
ports on a HDL level, whileBiSignalOut
is only used for simulation purposes and generally discarded by the compiler.Example
The following describes a system where two circuits, in alternating fashion, read the current value from the /bus/, increment it, and write it on the next cycle.