-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b731bd8
commit 22f6154
Showing
6 changed files
with
617 additions
and
0 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 |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Serialization / Deserialization | ||
|
||
ROHD-HCL implements a `Serializer` and `Deserializer` set of components that enable converting wide structures to a serialized narrow stream of data and vice-versa. | ||
|
||
## Serializer | ||
|
||
The `Serializer` is a module that accepts a wider `LogicArray` `deserialized` for input data and optionally a `Logic` `readyIn` to allow for pausing serialization. While `readyIn` is high, the `Serializer` sequentially outputs chunks of data on the Logic `serialized` output until the entire `LogicArray` `deserialized` has been transferred to the output. At that point the `Serializer` raises Logic `done`. This process will continue until the Logic `readyIn` is lowered, allowing for back-to-back transfers of wide data over the Logic `serialized` stream. The number of serialization steps in the current transfer is available in Logic `count`. Lowering `readyIn` will pause the transfer and raising it will continue from where it paused. | ||
|
||
## Deserializer | ||
|
||
The `Deserializer` is a module that accepts a `Logic` `serialized` stream over a pre-defined `length` number of clocks. It outputs a `LogicArray` `deserialized` of the same length of Logic words that match the width of Logic `serialized`. Deserialization runs while Logic `enable` is high, and Logic `validOut` is emitted when deserialization is complete. This process will continue when Logic `enable` is high, allowing for back-to-back deserialization transfers of a narrow stream of data into wider (`length`) `LogicArray`s during `length` number of serialization steps (clocks while `enable` is high) for each transfer. The number of serialization steps in the current transfer is available in Logic `count`. Lowering `enable` will pause the transfer and raising it will continue from where it paused. |
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,70 @@ | ||
// Copyright (C) 2024 Intel Corporation | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
// | ||
// deserializer.dart | ||
// A deserialization block, deserializing narrow input data onto a wide channel. | ||
// | ||
// 2024 August 27 | ||
// Author: desmond Kirkpatrick <[email protected]> | ||
|
||
import 'package:collection/collection.dart'; | ||
import 'package:rohd/rohd.dart'; | ||
import 'package:rohd_hcl/rohd_hcl.dart'; | ||
|
||
/// [Deserializer] aggregates data from a serialized stream. | ||
class Deserializer extends Module { | ||
/// Aggregated data output. | ||
LogicArray get deserialized => output('deserialized') as LogicArray; | ||
|
||
/// Length of aggregate to deserialize. | ||
final int length; | ||
|
||
/// [done] emitted when the last element is committed to [deserialized]. | ||
/// The timing is that you can latch [deserialized] when [done] is high. | ||
Logic get done => output('done'); | ||
|
||
/// Return the current count of elements that have been serialized out. | ||
Logic get count => output('count'); | ||
|
||
/// Build a Deserializer that takes serialized input [serialized] | ||
/// and aggregates it into one wide output [deserialized] of length [length]. | ||
/// | ||
/// Updates one element per clock while [enable] (if connected) is high, | ||
/// emitting [done] when completing the filling of wide output `LogicArray` | ||
/// [deserialized]. | ||
Deserializer(Logic serialized, this.length, | ||
{required Logic clk, | ||
required Logic reset, | ||
Logic? enable, | ||
super.name = 'deserializer'}) { | ||
clk = addInput('clk', clk); | ||
reset = addInput('reset', reset); | ||
if (enable != null) { | ||
enable = addInput('enable', enable); | ||
} | ||
serialized = (serialized is LogicArray) | ||
? addInputArray('serialized', serialized, | ||
dimensions: serialized.dimensions, | ||
elementWidth: serialized.elementWidth) | ||
: addInput('serialized', serialized, width: serialized.width); | ||
final cnt = Counter.simple( | ||
clk: clk, reset: reset, enable: enable, maxValue: length - 1); | ||
addOutput('count', width: cnt.width) <= cnt.count; | ||
addOutput('done') <= cnt.overflowed; | ||
addOutputArray('deserialized', | ||
dimensions: (serialized is LogicArray) | ||
? ([length, ...serialized.dimensions]) | ||
: [length], | ||
elementWidth: (serialized is LogicArray) | ||
? serialized.elementWidth | ||
: serialized.width) | ||
.elements | ||
.forEachIndexed((i, d) => | ||
d <= | ||
flop( | ||
clk, | ||
reset: reset, | ||
en: (enable ?? Const(1)) & count.eq(i), | ||
serialized)); | ||
} | ||
} |
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,5 @@ | ||
// Copyright (C) 2024 Intel Corporation | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
|
||
export 'deserializer.dart'; | ||
export 'serializer.dart'; |
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,91 @@ | ||
// Copyright (C) 2024 Intel Corporation | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
// | ||
// serializer.dart | ||
// A serialization block, serializing wide input data onto a narrower channel. | ||
// | ||
// 2024 August 27 | ||
// Author: desmond Kirkpatrick <[email protected]> | ||
|
||
import 'package:rohd/rohd.dart'; | ||
import 'package:rohd_hcl/rohd_hcl.dart'; | ||
|
||
/// Serializes wide aggregated data onto a narrower serialization stream. | ||
class Serializer extends Module { | ||
/// Serialized output, one data item per clock. | ||
Logic get serialized => output('serialized'); | ||
|
||
/// Return [done] = true when we have processed `deserialized`completely. | ||
/// [done] is asserted with the final element being serialized so that | ||
/// at the next clock edge, you have [done] with the last element latched at | ||
/// the same time. | ||
Logic get done => output('done'); | ||
|
||
/// The number of current serialization steps completed in the | ||
/// transfer is [count]. | ||
Logic get count => output('count'); | ||
|
||
/// Build a Serializer that takes the array [deserialized] and sequences it | ||
/// onto the [serialized] output. | ||
/// | ||
/// Delivers one element per clock while [enable] | ||
/// is high (if connected). If [flopInput] is true, the | ||
/// [Serializer] is configured to latch the input data and hold it until | ||
/// [done] is asserted after the full `LogicArray` [deserialized] is | ||
/// transferred. This will delay the serialized output by one cycle. | ||
Serializer(LogicArray deserialized, | ||
{required Logic clk, | ||
required Logic reset, | ||
Logic? enable, | ||
bool flopInput = false, | ||
super.name = 'serializer'}) { | ||
clk = addInput('clk', clk); | ||
reset = addInput('reset', reset); | ||
if (enable != null) { | ||
enable = addInput('enable', enable); | ||
} | ||
deserialized = addInputArray('deserialized', deserialized, | ||
dimensions: deserialized.dimensions, | ||
elementWidth: deserialized.elementWidth); | ||
|
||
addOutput('count', width: log2Ceil(deserialized.dimensions[0])); | ||
addOutput('done'); | ||
|
||
final reducedDimensions = List<int>.from(deserialized.dimensions) | ||
..removeAt(0); | ||
if (deserialized.dimensions.length > 1) { | ||
addOutputArray('serialized', | ||
dimensions: reducedDimensions, | ||
elementWidth: deserialized.elementWidth); | ||
} else { | ||
addOutput('serialized', width: deserialized.elementWidth); | ||
} | ||
|
||
final cnt = Counter.simple( | ||
clk: clk, | ||
reset: reset, | ||
enable: enable, | ||
maxValue: deserialized.elements.length - 1); | ||
|
||
final latchInput = (enable ?? Const(1)) & ~cnt.count.or(); | ||
count <= | ||
(flopInput | ||
? flop(clk, reset: reset, en: enable, cnt.count) | ||
: cnt.count); | ||
|
||
final dataOutput = | ||
LogicArray(deserialized.dimensions, deserialized.elementWidth); | ||
for (var i = 0; i < deserialized.elements.length; i++) { | ||
dataOutput.elements[i] <= | ||
(flopInput | ||
? flop( | ||
clk, reset: reset, en: latchInput, deserialized.elements[i]) | ||
: deserialized.elements[i]); | ||
} | ||
serialized <= dataOutput.elements.selectIndex(count); | ||
done <= | ||
(flopInput | ||
? flop(clk, reset: reset, en: enable, cnt.equalsMax) | ||
: cnt.equalsMax); | ||
} | ||
} |
Oops, something went wrong.