-
Notifications
You must be signed in to change notification settings - Fork 156
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
clash-cores/crc: Init
- Loading branch information
Showing
8 changed files
with
2,811 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,3 +5,4 @@ | |
* Add SPI master and slave cores | ||
* Add Lattice Semi SB_IO primitive | ||
* Add UART core | ||
* Add CRC core |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
{-| | ||
Copyright : (C) 2024, Rowan Goemans <[email protected]> | ||
License : BSD2 (see the file LICENSE) | ||
Maintainer : QBayLogic B.V. <[email protected]> | ||
Utilities for computing cyclic redundancy checks (CRCs) in software and in | ||
hardware. | ||
CRCs are specified using 'CrcParams' type in conjunction with the 'KnownCrc' type class. | ||
'CrcParams' contains settings for CRC width, polynomial, initial value, | ||
input/output reflection, and output XOR. This fully defines a CRC computation. | ||
Many commonly used CRC algorithms are available in the "Clash.Cores.Crc.Catalog" | ||
module, while most other CRC designs can be accommodated by manually constructing | ||
'CrcParams' and writing a 'KnownCrc' instance. | ||
Call the 'mkSoftwareCrc' using a specifc CRC to create an engine to perform software | ||
computations. It's not intended to be used on hardware. | ||
Example usage: | ||
>>> :set -XMultiParamTypeClasses | ||
>>> import Clash.Prelude | ||
>>> import Clash.Sized.Vector (unsafeFromList) | ||
>>> import Data.Char (ord) | ||
>>> import qualified Data.List as List | ||
>>> import Clash.Cores.Crc | ||
>>> import Clash.Cores.Crc.Catalog | ||
First we convert the check characters to @BitVector 8@ for processing. | ||
>>> charToBv = fromIntegral . ord | ||
>>> checkInput = fmap charToBv "123456789" | ||
>>> checkValue = 0xcbf43926 | ||
Here we instantiate a software CRC engine for the 32-bit Ethernet CRC | ||
that can handle @BitVector 8@ input and use it to compute the CRC. | ||
>>> softwareCrc = mkSoftwareCrc Crc32_ethernet d8 | ||
>>> crcFromSoftware = digest $ List.foldl' feed softwareCrc checkInput | ||
>>> crcFromSoftware == checkValue | ||
True | ||
For a hardware implementation the first thing you have to do is use Template Haskell | ||
to derive a 'HardwareCrc' instance using 'Clash.Cores.Crc.deriveHardwareCrc'. | ||
Here you need to provide a concrete @dataWidth@ and @nLanes@. Up to | ||
@dataWidth * nLanes@ of an input can be handled in a single clock cycle in | ||
@dataWidth@ increments. See the type of 'crcEngine' to see what impact it has | ||
on the CRC circuit. | ||
>>> :{ | ||
deriveHardwareCrc Crc32_ethernet d8 d4 | ||
dummy = 1 | ||
:} | ||
>>> crcEngine' = exposeClockResetEnable crcEngine systemClockGen resetGen enableGen | ||
>>> myEngine = crcEngine' Crc32_ethernet | ||
Note how we hinted to @clashi@ that our multi-line command was a list of | ||
declarations by including a dummy declaration @dummy = 1@. Without this trick, | ||
@clashi@ would expect an expression and the Template Haskell emitted by | ||
@deriveHardwareCrc@ would not work. | ||
We can give up to 4 bytes from @checkInput@ to our hardware CRC in the format | ||
of @Maybe (Index 4, Vec 4 (BitVector 8))@. The @Maybe@ indicates whether | ||
we want to run the CRC engine this clock cycle. The @Index@ inside the @Maybe@ | ||
indicates how many @BitVector 8@ are valid inside the @Vec@. 0 means 1 is valid. | ||
3 means 4 are valid. | ||
>>> hwInp0 = Just (True, 3, unsafeFromList $ fmap charToBv "1234" :: Vec 4 (BitVector 8)) | ||
>>> hwInp1 = Just (False, 3, unsafeFromList $ fmap charToBv "5678") | ||
>>> hwInp2 = Just (False, 0, unsafeFromList $ fmap charToBv "9___") | ||
>>> hwInp = [Nothing, hwInp0, hwInp1, hwInp2] | ||
>>> hwOut = myEngine (fromList hwInp) | ||
>>> crcFromHardware = List.last $ sampleN (1 + List.length hwInp) hwOut | ||
>>> crcFromHardware == checkValue | ||
True | ||
Notice that the 'crcEngine' has a latency of one clock cycle. | ||
-} | ||
|
||
module Clash.Cores.Crc | ||
( CrcParams(..) | ||
, KnownCrc(..) | ||
-- ** Software | ||
, SoftwareCrc | ||
, mkSoftwareCrc | ||
, reset | ||
, feed | ||
, digest | ||
, rawResidue | ||
, residue | ||
-- ** Hardware | ||
, HardwareCrc | ||
, deriveHardwareCrc | ||
, crcEngine | ||
, crcValidator | ||
) where | ||
|
||
import Clash.Cores.Crc.Internal |
Oops, something went wrong.