Bluespec SystemVerilog does not have always blocks like Verilog does. Instead, rules are used to describe how data is moved from state to state.
Rules are made up of two components:
A primary feature of rules in Bluespec is that they are atomic, meaning the rules are indivisible and a state transition is described completely by the actions within a rule. Each enabled rule can be considered individually to understand how it maintains or transforms state. The functional correctness of a design can then be determined by looking at each of the rules in isolation, without considering the actions of other rules. The one-rule-at-a-time semantics greatly simplifies the process of determining the functional correctness of a design. The actual behavior in the hardware will execute multiple rules concurrently. The Bluespec compiler ensures the actual behavior is consistent with the logical behavior, thus preserving functional correctness while achieving performance goals.
What does atomic really mean?
When writing rules, the above concepts must be considered. Multiple actions may have to be combined into a single rule, or actions split into separate rules, to achieve the desired functional correctness.
There are times when two or more actions will conflict. One way to handle conflicts is to put the actions in different rules, and make sure the rule conditions preclude the rules from being enabled at the same time.
A rule body can contain multiple actions. Any actions which should be executed in the same clock cycle should be put in a single rule. There is no sequencing within a rule body - all actions happen in parallel. This is a difference from many programming languages, where a sequence of statements are processed sequentially. You cannot put conflicting actions in the body of a rule. If you try to put conflicting actions in the same rule, the compiler will flag it as an error. If you put them in separate rules, the scheduler will add control logic to prevent both rules from firing in the same cycle.
This rule is not allowed, because the register x cannot be written to different values at the same time. This rule could be broken into two separate rules. Either the conditions are written so they are never enabled at the same time, or the the scheduler will add control logic to ensure that they are never executed in the same clock cycle.
One way to determine whether or not actions conflict is to ask whether changing the order of execution would change the result. Given the following actions:
x <= y + 1;
Remember, reads are performed before writes in the clock cycle. Since y is read at the beginning of the clock cycle, it doesn't matter which line is executed first. These two actions could be put in the same rule if they should be executed together, or in separate rules. In either case, they could be executed in the same clock cycle.
In the following example, the order of execution will determine the result.
x <= y + 1;
In this case, the actions can not be put in the same rule. If put into different rules, the rules would conflict and scheduling logic would be added to prevent them from firing in the same clock cycle (unless the conditions were written to prevent it).
Another type of conflict is a resource conflict, as seen in the following example:
In this case, there is only one enq<tt> port, but both actions are trying to access it. These actions could not be put into the same rule.
Because the actions in a rule are simultaneous, as opposed to sequential, you can swap register values within the body of a single rule.
For more detail on how rules really work, and scheduling of rules see Rules Of Rules
Learning BSV >