-
Notifications
You must be signed in to change notification settings - Fork 0
AXI-Stream Formal Properties #3
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
Open
rlee287
wants to merge
38
commits into
main
Choose a base branch
from
axi_stream
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
38 commits
Select commit
Hold shift + click to select a range
c70a583
First pass at AXI Stream formal properties
rlee287 ce90a76
Fix README typo
rlee287 b60c3c5
Add the property that TVALID cannot be deasserted until transfer
rlee287 0871812
Add note about lack of requirement for no combinational paths to AXIS
rlee287 985e786
Remove .keep from property_sets now that the directory is populated
rlee287 40c1b6c
Fix some reset related issues with AXIS properties
rlee287 06330b2
Fix missing negation of reset in an AXIS slave property
rlee287 34408c1
Add more checks for past_valid where they are needed
rlee287 f8921ca
Use nonblocking assignment for past_valid value
rlee287 43984c5
Fix reset things and use preprocessor to encourage code reuse
rlee287 cc16378
Check for positive width parameter before assuming/asserting stall st…
rlee287 7692bac
Adjust reset handling in AXI-Stream properties
rlee287 6b40ac0
Create a utility for assuming async resets are synchronously released
rlee287 8579c5c
Allow non-data bytes to vary when stream is stalled
rlee287 8b36055
Add script to compare AXI-Stream properties and ensure they match cor…
rlee287 0c478fa
Add README state for "complete but untested" and update statues
rlee287 ece2d1a
Fix README.md typo
rlee287 e19f039
Label the AXI-Stream properties with the version and issue of the spec
rlee287 bdd5b19
Bypass default input tready value when linting with Verilator
rlee287 674c736
Revert "Allow non-data bytes to vary when stream is stalled"
rlee287 5657264
Move up definition of TX_ASSERT (so that diff reference can be update…
rlee287 b1256c8
Move up Section 3.1.5 note and add keep_width for when byte_width=0
rlee287 22ba3fc
Account for the possibility of byte_width=0 in stall $stable checks
rlee287 870ac0b
Print out the diff output if the check_differences script fails
rlee287 0cebe36
Remove extraneous colon from Optional TREADY comment
rlee287 a4753bf
Add a property to ensure TVALID is raised "in a timely manner"
rlee287 149bcac
Reset handling should be fixed now...
rlee287 55f635a
Update diff file for AXI-Stream
rlee287 dc45ddf
Using not_in_reset requires past_valid
rlee287 447b415
Assert that valid is raised with backpressure only when no reset happens
rlee287 9f3b8f4
Update TODO notes in AXI-Stream properties
rlee287 0eb4261
Update comparison diff for two property sets
rlee287 aafee53
Merge branch 'main' into axi_stream
rlee287 e759e47
Rename clk and resetn to aclk and aresetn
rlee287 9ea22fa
Add TODO note about assuming master readiness in slave properties
rlee287 1bae26b
Allow valid-before-ready check to be disabled by parameters
rlee287 d5cd1e6
Add a .gitignore for SymbiYosys and note naming convention in CONTRIB…
rlee287 bf50f86
Update CONTRIBUTING.md
rlee287 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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,4 @@ | ||
# Output folders from SymbiYosys (by task name convention) | ||
*_bmc/ | ||
*_cover/ | ||
*_prove/ |
This file contains hidden or 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 hidden or 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
Empty file.
This file contains hidden or 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,202 @@ | ||
`default_nettype none | ||
|
||
/* | ||
* A set of formal properties for the master port of AXI-Stream. | ||
* AXI4-Stream, Version 1.0, Issue A | ||
*/ | ||
|
||
/* | ||
* Section 2.1 Signal list | ||
* Section 3.1 Default value signaling | ||
* Notes on defaults for specific signals in port list below | ||
*/ | ||
module axi_stream_master_monitor #( | ||
parameter byte_width = 4, | ||
parameter id_width = 0, | ||
parameter dest_width = 0, | ||
parameter user_width = 0, | ||
// Section 3.1.5 Optional TDATA | ||
// no TDATA -> no TSTRB (but TKEEP can still exist) | ||
// TKEEP width when byte_width=0 | ||
parameter keep_width = 0, | ||
|
||
// TODO: properties untested for multiclock environments | ||
parameter USE_ASYNC_RESET = 1'b0, | ||
// Section 2.2.1 Handshake process | ||
// Master cannot wait on TREADY to signal TVALID | ||
// Cycle count for TREADY to be kept low initially, after which TVALID should be high | ||
// Set to 0 to disable this check | ||
parameter MAX_DELAY_TREADY_NO_TVALID = 16 | ||
) ( | ||
input wire aclk, | ||
input wire aresetn, | ||
|
||
input wire tvalid, | ||
// Section 3.1.1 Optional TREADY | ||
// Having a tready port is recommended | ||
`ifndef VERILATOR | ||
input wire tready = 1'b1, | ||
`else | ||
input wire tready, | ||
`endif | ||
|
||
input wire [(8*byte_width-1):0] tdata, | ||
// Section 3.1.2 Optional TKEEP and TSTRB | ||
// TODO: fix optional value declarations | ||
input wire [(byte_width-1):0] tstrb,// = tkeep, | ||
input wire [(byte_width>0 ? (byte_width-1) : keep_width):0] tkeep,// = {(byte_width-1){1'b1}}, | ||
|
||
// Section 3.1.3 Optional TLAST | ||
// Recommended default TLAST value situation-dependent | ||
input wire tlast, | ||
|
||
// Section 3.1.4 Optional TID, TDEST, and TUSER | ||
// Signals omitted by setting widths to 0 | ||
input wire [(id_width-1):0] tid, | ||
input wire [(dest_width-1):0] tdest, | ||
input wire [(user_width-1):0] tuser | ||
|
||
// TODO add output signals for byte counts, etc. | ||
); | ||
`define TX_ASSERT assert | ||
`define NOT_RESET_FOR_REGISTERED ($past(aresetn) && (!USE_ASYNC_RESET || aresetn)) | ||
|
||
reg past_valid = 1'b0; | ||
always @(posedge aclk) | ||
past_valid <= 1'b1; | ||
|
||
reg not_in_reset; | ||
|
||
/* | ||
* If in async mode, reset is registered by async flip flop | ||
* If in sync mode, reset is registered by sync flip flop | ||
* | ||
* WARNING: Only use this in combinational blocks | ||
* Use in registered blocks makes this incorrect by a clock cycle delay | ||
* Use `NOT_RESET_FOR_REGISTERED for registered blocks | ||
*/ | ||
generate | ||
if (USE_ASYNC_RESET) | ||
always @(posedge aclk or negedge aresetn) | ||
begin | ||
if (!aresetn) | ||
not_in_reset <= 1'b0; | ||
else | ||
not_in_reset <= aresetn; | ||
end | ||
else | ||
always @(posedge aclk) | ||
begin | ||
not_in_reset <= aresetn; | ||
end | ||
endgenerate | ||
// TODO reset signal generation is quite messy right now | ||
|
||
// Section 2.2.1 Handshake process | ||
|
||
// Once TVALID is asserted it must be held until TVALID && TREADY | ||
always @(posedge aclk) | ||
begin | ||
// Write this as (TVALID falls implies previous data transfer or reset) | ||
if (past_valid && $fell(tvalid)) | ||
begin | ||
`TX_ASSERT($past(tvalid && tready) || !`NOT_RESET_FOR_REGISTERED); | ||
end | ||
end | ||
|
||
// Master cannot wait on TREADY to signal TVALID | ||
// Property below modified from @awygle's suggestion | ||
generate | ||
if (MAX_DELAY_TREADY_NO_TVALID < 4096 && MAX_DELAY_TREADY_NO_TVALID > 0) | ||
begin | ||
reg f_ever_ready = 1'b0; | ||
reg [11:0] delay_counter = 0; | ||
always @(posedge aclk) | ||
begin | ||
if (!aresetn) | ||
f_ever_ready <= 1'b0; | ||
else if (tready) | ||
f_ever_ready <= 1'b1; | ||
end | ||
always @(posedge aclk) | ||
begin | ||
// Else if check to prevent weirdness with overflow | ||
// 4096 cycles should be plenty enough though | ||
if (!aresetn) | ||
delay_counter <= 0; | ||
else if (delay_counter < 12'hfff) | ||
delay_counter <= delay_counter + 1; | ||
end | ||
|
||
always @(*) | ||
begin | ||
// Helper assert to justify lack of past_valid for below property | ||
if (delay_counter > 0) | ||
assert(past_valid); | ||
end | ||
|
||
// Check that TVALID has been raised even if TREADY has been held low | ||
// In isolation, this checks the required property | ||
// In a full system (where TREADY may be tied high) a false hypothesis allows the property to pass vacuously | ||
// TODO: optional assumption for slave properties? | ||
always @(*) | ||
begin | ||
if (delay_counter == MAX_DELAY_TREADY_NO_TVALID | ||
&& !f_ever_ready && not_in_reset) | ||
assert(tvalid); | ||
end | ||
end | ||
else if (MAX_DELAY_TREADY_NO_TVALID != 0) | ||
$error("MAX_DELAY_TREADY_NO_TVALID too large"); | ||
endgenerate | ||
|
||
// When TVALID && !TREADY, data signals must be stable | ||
always @(posedge aclk) | ||
begin | ||
if (past_valid && `NOT_RESET_FOR_REGISTERED && $past(tvalid && !tready)) | ||
begin | ||
if (byte_width > 0) | ||
begin | ||
`TX_ASSERT($stable(tdata)); | ||
`TX_ASSERT($stable(tstrb)); | ||
end | ||
if (byte_width > 0 || keep_width > 0) | ||
`TX_ASSERT($stable(tkeep)); | ||
|
||
`TX_ASSERT($stable(tlast)); | ||
|
||
if (id_width > 0) | ||
`TX_ASSERT($stable(tid)); | ||
if (dest_width > 0) | ||
`TX_ASSERT($stable(tdest)); | ||
if (user_width > 0) | ||
`TX_ASSERT($stable(tuser)); | ||
end | ||
end | ||
|
||
// Section 2.7.1 Clock | ||
// Unlike regular AXI there is no requirement for no combinational paths | ||
rlee287 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Section 2.7.2 Reset | ||
// "A master interface must only begin driving TVALID at a rising ACLK edge following a rising edge at which ARESETn is asserted HIGH." | ||
// This timing is handled by the definition of not_in_reset above | ||
always @(*) | ||
rlee287 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
begin | ||
if (past_valid && !not_in_reset) | ||
begin | ||
`TX_ASSERT(!tvalid); | ||
end | ||
end | ||
|
||
// Section 2.4.3 TKEEP and TSTRB combinations | ||
// TSTRB can be asserted only if TKEEP is asserted | ||
always @(*) | ||
begin | ||
if (tvalid) | ||
begin | ||
`TX_ASSERT(!(~tkeep & tstrb)); | ||
end | ||
end | ||
endmodule | ||
rlee287 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
`undef TX_ASSERT | ||
`undef NOT_RESET_FOR_REGISTERED |
This file contains hidden or 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,153 @@ | ||
`default_nettype none | ||
|
||
/* | ||
* A set of formal properties for the slave port of AXI-Stream. | ||
* AXI4-Stream, Version 1.0, Issue A | ||
*/ | ||
|
||
/* | ||
* Section 2.1 Signal list | ||
* Section 3.1 Default value signaling | ||
* Notes on defaults for specific signals in port list below | ||
*/ | ||
module axi_stream_slave_monitor #( | ||
parameter byte_width = 4, | ||
parameter id_width = 0, | ||
parameter dest_width = 0, | ||
parameter user_width = 0, | ||
// Section 3.1.5 Optional TDATA | ||
// no TDATA -> no TSTRB (but TKEEP can still exist) | ||
// TKEEP width when byte_width=0 | ||
parameter keep_width = 0, | ||
|
||
// TODO: properties untested for multiclock environments | ||
parameter USE_ASYNC_RESET = 1'b0 | ||
) ( | ||
input wire aclk, | ||
input wire aresetn, | ||
|
||
input wire tvalid, | ||
// Section 3.1.1 Optional TREADY | ||
// Having a tready port is recommended | ||
`ifndef VERILATOR | ||
input wire tready = 1'b1, | ||
`else | ||
input wire tready, | ||
`endif | ||
|
||
input wire [(8*byte_width-1):0] tdata, | ||
// Section 3.1.2 Optional TKEEP and TSTRB | ||
// TODO: fix optional value declarations | ||
input wire [(byte_width-1):0] tstrb,// = tkeep, | ||
input wire [(byte_width>0 ? (byte_width-1) : keep_width):0] tkeep,// = {(byte_width-1){1'b1}}, | ||
|
||
// Section 3.1.3 Optional TLAST | ||
// Recommended default TLAST value situation-dependent | ||
input wire tlast, | ||
|
||
// Section 3.1.4 Optional TID, TDEST, and TUSER | ||
// Signals omitted by setting widths to 0 | ||
input wire [(id_width-1):0] tid, | ||
input wire [(dest_width-1):0] tdest, | ||
input wire [(user_width-1):0] tuser | ||
|
||
// TODO add output signals for byte counts, etc. | ||
rlee287 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
); | ||
`define TX_ASSERT assume | ||
`define NOT_RESET_FOR_REGISTERED ($past(aresetn) && (!USE_ASYNC_RESET || aresetn)) | ||
|
||
reg past_valid = 1'b0; | ||
always @(posedge aclk) | ||
past_valid <= 1'b1; | ||
|
||
reg not_in_reset; | ||
|
||
/* | ||
* If in async mode, reset is registered by async flip flop | ||
* If in sync mode, reset is registered by sync flip flop | ||
* | ||
* WARNING: Only use this in combinational blocks | ||
* Use in registered blocks makes this incorrect by a clock cycle delay | ||
* Use `NOT_RESET_FOR_REGISTERED for registered blocks | ||
*/ | ||
generate | ||
if (USE_ASYNC_RESET) | ||
always @(posedge aclk or negedge aresetn) | ||
begin | ||
if (!aresetn) | ||
not_in_reset <= 1'b0; | ||
else | ||
not_in_reset <= aresetn; | ||
end | ||
else | ||
always @(posedge aclk) | ||
begin | ||
not_in_reset <= aresetn; | ||
end | ||
endgenerate | ||
// TODO reset signal generation is quite messy right now | ||
|
||
// Section 2.2.1 Handshake process | ||
|
||
// Once TVALID is asserted it must be held until TVALID && TREADY | ||
always @(posedge aclk) | ||
begin | ||
// Write this as (TVALID falls implies previous data transfer or reset) | ||
if (past_valid && $fell(tvalid)) | ||
begin | ||
`TX_ASSERT($past(tvalid && tready) || !`NOT_RESET_FOR_REGISTERED); | ||
end | ||
end | ||
|
||
// Slave can wait on TVALID to signal TREADY | ||
|
||
// When TVALID && !TREADY, data signals must be stable | ||
always @(posedge aclk) | ||
begin | ||
if (past_valid && `NOT_RESET_FOR_REGISTERED && $past(tvalid && !tready)) | ||
begin | ||
if (byte_width > 0) | ||
begin | ||
`TX_ASSERT($stable(tdata)); | ||
`TX_ASSERT($stable(tstrb)); | ||
end | ||
if (byte_width > 0 || keep_width > 0) | ||
`TX_ASSERT($stable(tkeep)); | ||
|
||
`TX_ASSERT($stable(tlast)); | ||
|
||
if (id_width > 0) | ||
`TX_ASSERT($stable(tid)); | ||
if (dest_width > 0) | ||
`TX_ASSERT($stable(tdest)); | ||
if (user_width > 0) | ||
`TX_ASSERT($stable(tuser)); | ||
end | ||
end | ||
|
||
// Section 2.7.1 Clock | ||
// Unlike regular AXI there is no requirement for no combinational paths | ||
|
||
// Section 2.7.2 Reset | ||
// "A master interface must only begin driving TVALID at a rising ACLK edge following a rising edge at which ARESETn is asserted HIGH." | ||
// This timing is handled by the definition of not_in_reset above | ||
always @(*) | ||
begin | ||
if (past_valid && !not_in_reset) | ||
begin | ||
`TX_ASSERT(!tvalid); | ||
end | ||
end | ||
|
||
// Section 2.4.3 TKEEP and TSTRB combinations | ||
// TSTRB can be asserted only if TKEEP is asserted | ||
always @(*) | ||
begin | ||
if (tvalid) | ||
begin | ||
`TX_ASSERT(!(~tkeep & tstrb)); | ||
end | ||
end | ||
endmodule | ||
`undef TX_ASSERT | ||
`undef NOT_RESET_FOR_REGISTERED |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.