Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a documentation for CombInit #228

Merged
merged 6 commits into from
Nov 10, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions source/SpinalHDL/Semantic/assignments.rst
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,51 @@ Combinatorial loops

SpinalHDL checks that there are no combinatorial loops (latches) in your design.
If one is detected, it raises an error and SpinalHDL will print the path of the loop.

CombInit
--------

The special ``CombInit`` method can be used to "clone" a combinatorial value for latter modification.
ronan-lashermes marked this conversation as resolved.
Show resolved Hide resolved

.. code-block:: scala

val a = UInt(8 bits)
a := 1

val b = a
when(sel) {
b := 2
//At this point, a and b are evaluated to 2 : they represent the same set of wire
ronan-lashermes marked this conversation as resolved.
Show resolved Hide resolved
}

val c = UInt(8 bits)
c := 1

val d = CombInit(c)
// Here c and d are evaluated to 1
when(sel) {
d := 2
// At this point c === 1 and d === 2.
}

``CombInit`` clones a circuit, and initially drive it with the same input at the cloned value.
ronan-lashermes marked this conversation as resolved.
Show resolved Hide resolved
But you can now update the circuit without impacting the initial value.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could add an example here for one of the major use-cases which is to make helper functions that break the reference to the original signal. That would explain what to use it for, I found it's pretty rare in "normal" HDL code. A dumb example would be:

// note that condition is an elaboration time constant
def invertedIf(b: Bits, condition: Boolean): Bits = if(condition) { ~b } else { CombInit(b) }

where we shouldn't return just b in the false case as that would create weird behavior (if true the return value can't influence the original b, if false it can)
Do you think that makes sense?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your suggestions.
I like your invertedIf example, I was looking for a simple realistic use case : this is it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See 6222df6 for a first try.

If we look at the resulting Verilog, ``b`` is not present :
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is more a statement about references than CombInit - but I have no big issue keeping it if you think it helps a bunch.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, 148 and 149 are a bit redundant with the earlier CombInit description.
151 was there to insist on the differences in the synthesis results, I would like to keep it but add a bit more contextual description.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cf 6222df6.


.. code-block:: verilog

always @(*) begin
a = 8'h01;
if(sel) begin
a = 8'h02;
end
end

assign c = 8'h01;
always @(*) begin
d = c;
if(sel) begin
d = 8'h02;
end
end