Digital Design Modeling (SystemVerilog + ) Flashcards

1
Q

Hardware Description Languages

A

Specialized language used to describe the structure and behavior of electronic circuits.
Allows you to automate both simulation and synthesis.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Logic Simulation

A

Inputs are applied to a module and the outputs are checked to verify that the model operates correctly. (Basically looking at the timing diagrams and making sure that everything looks as expected)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Logic Synthesis

A

The textual description of a module is transformed into logic gates

HDL synthesizers recognize certain idioms and turn them into specific sequential circuits

Other coding styles may simulate correctly, but synthesize into circuits with blatant or subtle errors

Note: Use the proper idioms to describe registers and latches

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Synthesizable Design

A

Means that the design (as described in the code) can actually be implemented using logic gates within the given parameters

Division and modulus operations are often unsynthesizable

1) Avoid High-Level Constructs: Avoid using constructs that are unsupported by synthesis tools, such as dynamic data types, certain procedural blocks, and high-level features. Dynamic arrays, queues, classes, assertions, initial blocks, and forever loops are typically not synthesizable.
Use Static arrays instead of dynamic arrays.
2) Remove Delays (#): Avoid using # delays or wait statements in synthesizable code. Synthesis tools do not support delays or timing-based constructs, which are useful in simulation but not in actual hardware design.
3) Use Proper Sensitivity Lists: Use always_comb for combinational logic and always_ff for sequential logic with the correct clock and reset signals.
4) Avoid Infinite Loops: Avoid infinite loops (forever, while) in synthesizable code. Such loops are used for simulation purposes but cannot be translated to hardware.
5) Use Fixed-Size Arrays: Use fixed-size arrays instead of dynamic arrays, queues, or associative arrays. Synthesis tools need to know the exact size of the hardware they are generating.
6) Use Blocking and Non-blocking Assignments Appropriately: Use blocking assignments (=) in combinational logic and non-blocking assignments (<=) in sequential logic.
7) Avoid Using System Functions: Avoid using system tasks or functions like $display, $random, $monitor, and assertions (assert). These are simulation-only constructs.
8) Avoid Mixed Edge Sensitivity: Ensure that flip-flops are triggered on a single edge (either rising or falling edge) and do not mix both edges in the same block.
9) Proper Reset Logic: Always include a reset signal to initialize flip-flops, and make sure the reset logic is synchronous or asynchronous depending on design needs.
10) Avoid Full Case and Parallel Case Compiler Directives: Avoid using full_case and parallel_case compiler directives unless you are sure about the implications on synthesis. These can lead to unintended synthesis behavior, such as ignoring default cases or optimizations.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Behavioral Level System Descriptions

A

Describes how the outputs are computed as functions of the inputs

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Structural Level System Descriptions

A

Describes how a module is composed of simpler modules of basic primitives (gates or transistors)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Top-Down Design

A

Starting from the SOI/mission and breaking it down into more granular components (like reverse engineering)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Bottom-Up Design

A

Piecing together smaller systems to build a larger, more relevant SOI

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

History of System Verilog

A
  • Verilog was developed by Phil Moorby at Gateway Design Automation as a proprietary language for logic simulation in 1984
  • Gateway is acquired by Cadence in 1989
  • Made an open standard in 1990 under the control of Open Verilog International
  • Became an IEEE standard in 1995 and Updated in 2001 [IEEE1364-01]
  • In 2005, it was updated again with minor clarifications
  • Then SystemVerilog [IEEE 1800-2009] was introduced in 2009
    -Streamlines many of the annoyances of Verilog and adds high-level programming language features that have proven useful in verification
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Module

A

System Verilog Term.
Refers to a block of hardware with inputs and outputs.
Begins with a listing of the inputs and
outputs.
Continues with statements.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Assign Statement

A

Indicates combinational Logic

“logic” signals such as the inputs and outputs are
Boolean variables (0 or 1); They may also have
floating (z) and undefined values (x)

always ‘concurrent’, unlike variables in other programming languages where they can be re-assigned

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Logic Type in system verilog

A
  • Supersedes the “reg” type, which was a
    perennial source of confusion in Verilog
  • should be used everywhere except on nets with
    multiple drivers

Logic signals such as the inputs and outputs are
Boolean variables (0 or 1); They may also have
floating (z) and undefined values (x)

EXAMPLE:
module sillyfunction(input logic a, b, c,
output logic y);
assign y = ~a & ~b & ~c |
a & ~b & ~c |
a & ~b & c;
endmodule

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Combinational Logic Operators

A

Used to build expressions that relate who ‘operands’ (a, b, x, y, etc). These expressions are needed for statements such as assign

~ indicates NOT
& indicates AND
| indicates OR
^ indicates XOR

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Verilog Comments

A

// indicates a single line comment
/* */ indicated a multi-line comment

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Operands in verilog

A

Represent a particular signal
Can be defined either in the inputs/outputs at the begining of the module
They are case sensitive (‘y’ is a completely different signal from ‘Y’)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Correct Implementation of Assign Statements

A

Syntax: assign [signal operand] = [logical expression]

*logical expressions combine operands using operators

EXAMPLE:
module gates(input logic [3:0] a, b,
output logic [3:0] y1, y2, y3, y4, y5);
/* Five different two-input logic
gates acting on 4 bit busses */
assign y1 = a & b; // AND
assign y2 = a | b; // OR
assign y3 = a ^ b; // XOR
assign y4 = ~(a & b); // NAND
assign y5 = ~(a | b); // NOR
endmodule

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

Correct implementation of conditional operators

A

/* 4-bit mux; selects one of two 4-bit
inputs d0 or d1
Equivalent to this expression:
If s = 1, then y = d1.
If s = 0, then y = d0.*/
module mux2_4 (input logic [3:0] d0, d1,
input logic s, output logic [3:0] y);
assign y = s ? d1 : d0;
endmodule

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

Conditional Operators

A

Syntax: assign [signal operand] = [condition] ? [expression 1] : [expression 2];

If the condition evaluates to TRUE (has a value of 1), the “expression 1” will be assigned to the signal. If the condition evaluates to FALSE (has a value of 0), the “expression 2” will be assigned to the signal.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

Reduction Operators

A

Basically used to ‘demultiplex’ a bunch of signals and perform a logic operation on them at the same time.

Reduction operators imply a multiple-input
gate acting on a single bus
* |, ^, ~&, and ~| reduction operators are
available for OR, XOR, NAND, and NOR

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

Correct Implementation of Reduction Operators

A

module and8 (input logic [7:0] a,
output logic y);
assign y = & a;
// &a is much easier to write than
// assign y = a[7] & a[6] & a[5] & a[4]
// & a[3] & a[2] & a[1] & a[0];
endmodule

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

Correct Implementation of a 32 bit adder in system verilog

A

/* 32-bit adder */
module adder (a, b, y);
input logic [31:0] a;
input logic [31:0] b;
output logic [31:0] y;
assign y = a + b;
endmodule

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

Correct way to have nested conditional operators

A

/* */
module whatami(input logic [3:0] d0, d1, d2, d3,
input logic [1:0] s, output logic [3:0] y);
assign y = s[1] ? (s[0] ? d3 : d2)
: (s[0] ? d1 : d0);
endmodule

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q

“Operator Precedence” in System Verilog

A

It’s like the “order of operations” in Math

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
24
Q

Subtraction in System Verilog

A

There is no operator for it; just use compliment and addition

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
25
Q

“Inexpensive” Operations (in hardware)

A

“Inexpensive” in this case refers to how much resources (space) you need in the silicon.

AND and NOT do not take up too much are in the hardware

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
26
Q

Semi-expensive Operations (in hardware)

A

Multipliers and Shifters take up a fair amount of area on the silicon

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
27
Q

Super Expensive Operations (in hardware)

A

Division and Modulus are so costly that it may not be synthesizable

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
28
Q

How equality comparisons (==) work in System Verilog

A

(N) is the number of comparisons

Step 1) N 2-input XORs to determine equality of each bit
Step 2) An N-input AND to combine all of the bits

“Relative comparison involves a subtraction”

[Revisit]

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
29
Q

Format for declaring constants in System Verilog

A

“N’Bvalue”

  • N is the size in bits
  • B is the base, and
  • Value gives the value

EXAMPLE: 9’h25 indicates a 9-bit hex number (37 decimal or
000100101 in binary)

*If the base is omitted, the base defaults to decimal

*If the size is not given, the number is assumed to have as many bits as the expression in which it is being
used. (Zeros are automatically padded on the front of the number to bring it up to full size)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
30
Q

Floating Values in System Verilog

A

Indicated by the letter z

Useful for describing a tristate buffer; its outputfloats when the enable is 0

A bus can be driven by several tristate buffers, exactly one of which should be enabled

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
31
Q

Tristate Buffer

A

A three-state logic variable

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
32
Q

The type for a tristate buffer in system verilog

A

“Tri”. not “logic”

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
33
Q

tri v. trireg in System Verilog

A
  • Both are types of net declarations that relate to three-state logic (and the behavior of multi-driver nets).
  • Often used when dealing with bus systems or signals that can have more than one driver (including scenarios where a high-impedance (Z) state is possible)
    • One driver is active at a time, and the net takes that value; If no drivers are enabled, the tri net floats (z), while the trireg net retains the previous value

Key Differences:
* tri: Goes to high impedance (Z) when not driven.
* trireg: Retains the last driven value (holds the previous state) when not actively driven.

Practical Use:
* tri: Useful for buses where no value should be retained when the driver is disabled.
* trireg: Useful when you need the last value to persist even after the driver stops driving the signal.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
34
Q

Bit swizzling

A

Refers to the process of rearranging or manipulating the individual bits within a binary word, byte, or larger data structure. It’s often used for optimizing performance, encoding data efficiently, or adjusting data layouts for compatibility between different hardware or software systems

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
35
Q

Invalid Logic Levels in System Verilog (also known as an ‘unknown state’)

A

Indicated by the letter ‘x’

This is often a result of an invalid AND operation

Any AND operation involving a float (z) or an invalid logic value (x)

Flopflops have an initial value of ‘x’

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
36
Q

Main aspects of modeling combinational logic

A

1) Floating Values
2) Invalid Values
3) Bit Swizzling
4) Delays
5) Structural Modeling

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
37
Q

Concatenate Operator

A

Indicated by curly brackets: {}

EXAMPLE: assign y = {c[2:1], {3{d[0]}}, c[0], 3’b101};

  • y is a 9-bit vector
  • If y were wider than 9 bits, zeros
    would be placed in the most
    significant bit positions
  • {3{d[0]}} indicates three copies of d[0]
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
38
Q

“Delays” in System Verilog

A
  • Helpful during simulation
  • Predict how fast a circuit will work (if you specify meaningful delays)
  • Helpful for debugging the cause and effect
  • Delays are ignored during synthesis
  • Delay of a gate produced by the synthesizer depends on its tpd and tcd specifications
  • # symbol is used to indicate the number of units of delay

EXAMPLE:
assign #1 {ab, bb, cb} = ~{a, b, c};
assign #2 n1 = ab & bb & cb;
assign #2 n2 = a & bb & cb;
assign #2 n3 = a & bb & c;
assign #4 y = n1 | n2 | n3;

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
39
Q

“tpd” and “tcd” specifications

A

tpd represents propagation delay
tcd represents contamination delay

Crucial parameters used to evaluate the performance of logic gates, flip-flops, or any combinational logic components. Both values are essential to ensure reliable operation of a digital circuit and help avoid timing violations.

Key Differences:
* tpd (Propagation Delay): The maximum time required for an input change to fully propagate and cause the output to stabilize. This is critical for determining the clock period and maximum speed of a circuit.
* tcd (Contamination Delay): The minimum time it takes for an input change to begin affecting the output. This is important for ensuring hold time violations are avoided, and no glitches occur prematurely at the output.

Practical Use:
1) Timing Analysis:
* Propagation delay (tpd) determines the maximum clock frequency at which a circuit can operate.
* Contamination delay (tcd) is used to check hold time constraints in sequential circuits to prevent premature data changes or glitches.
2) Circuit Design:
* Ensuring that contamination delay doesn’t cause premature transitions or data hazards.
* Balancing the propagation delay to maintain optimal performance without violating timing requirements.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
40
Q

Propagation delay

A
  • Definition: Propagation delay, typically denoted as tpd, is the time it takes for a change at the input of a logic gate to cause a valid change at its output. Specifically, it’s the delay between when an input changes and when the corresponding output stabilizes at the correct value.
  • Formula:
    tpd=t_out_valid−t_in_change

where
t_in_charge is the time at which the input changes.
t_out_valid is the time when the output stabilizes at a valid level

* Importance: This delay is important in determining the maximum operating frequency of a circuit. It limits how fast data can propagate through a series of gates or between flip-flops.

  • Units: Measured in time units (usually nanoseconds, ns, or picoseconds, ps).

Types:
tpLH (Low to High Propagation Delay): The delay from a low (0) to high (1) transition at the output.
tpHL (High to Low Propagation Delay): The delay from a high (1) to low (0) transition at the output.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
41
Q

Contamination Delay

A
  • Definition: Contamination delay, typically denoted as tcd, is the minimum time it takes for a change at the input to propagate to the output, potentially causing the output to start changing. This is the shortest possible time in which an input change may affect the output, even though the output has not fully stabilized yet.
  • Formula:
    tcd=t_out_begin_change-t_in_change

where:
t_in_change is the time when the input changes.
t_out_begin_change is the time when the output starts to change.

  • Importance: The contamination delay is important when evaluating hold time constraints and ensures that data does not propagate too quickly through a circuit and cause timing hazards or glitches at unintended times.
  • Units: Measured in time units (usually nanoseconds or picoseconds)
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
42
Q

Timescales

A

Timescales are used to define the time units and time precision for simulation. They play a crucial role in the design and operation of test benches by controlling how delays are interpreted and how time-based operations are simulated

Syntax: `timescale <time_unit> / <time_precision></time_precision></time_unit>

where,
time_unit: Specifies the units of time used for delays and simulation time (e.g., 1ns, 10ps).
time_precision: Specifies the precision or the smallest time step in the simulation (e.g., 1ps, 0.1ns)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
43
Q

Timescales in testbenches

A

SYNTAX: `timescale <time_unit> / <time_precision></time_precision></time_unit>

Importance of Timescale in Test Benches:
1) Simulation Precision: Test benches need precise timing for simulation results to be accurate, especially for circuits operating at high frequencies or those involving analog/mixed-signal interfaces.
2) Delay Control: Timescales help control delays in assertions, waits, and other timing-dependent operations in the test bench, ensuring that they match the real-world scenario you’re simulating.
3) Alignment with Real-Time Behavior: Choosing appropriate timescales in a test bench allows the simulated time to align with real-world time, making it easier to validate timing and performance characteristics of a design.
4) Consistent Timing Across Modules: When a design is made up of multiple modules, each with its own timescale, it is important to ensure that the timescales are compatible to avoid simulation issues. If modules use different timescales, the simulator will convert delays accordingly, but inconsistent timescales can lead to unexpected results.
5) Timing Checks: Timescales are essential for performing accurate timing checks in test benches, such as setup and hold time checks. By ensuring that the simulation has the proper resolution, you can accurately verify that timing constraints are met.
6) Clock Generation: In test benches, timescales are critical when defining clocks and other periodic signals.
Syntax for : always #10 clk = ~clk;

44
Q

Blocking assignment

A

Indicated by (=)

A group of blocking assignments
inside a begin-end block is evaluated sequentially

Do NOT execute concurrently, these execute top to bottom

EXAMPLE:
p = a ^ b; // blocking
g = a & b; // blocking

45
Q

Best Practices of implementing blocking assignments

A

1) Use blocking assignments (=) for combinational logic and procedural tasks, not for sequential logic.
2) Avoid using blocking assignments in clocked blocks (use non-blocking assignments instead for sequential logic).
3) Make sure combinational signals are fully assigned to prevent latch inference.
4) Keep blocking assignments within their procedural scope and avoid mixing with non-blocking assignments in the same block.
5) Ensure correct signal flow and order of execution to avoid unintended timing issues or race conditions.

46
Q

Nonblocking assignment

A

Indicated by (<=)

A group of non-blocking assignments are evaluated in parallel; all of the statements are evaluated before any of the left sides are updated

Not Recommended

These will execute concurrently

EXAMPLES:
p <= a ^ b; // nonblocking
g <= a & b; // nonblocking

47
Q

Structural Modeling

A

Describe a module in terms of how it is
composed of simpler modules

EXAMPLE: “mux4 out of mux2 modules”
module mux4_4 (input logic [3:0] d0, d1, d2,
d3,
input logic [1:0] s,
output logic [3:0] y);
logic [3:0] mol, moh;
mux2_4 lowmux(d0, d1, s[0], mol);
mux2_4 highmux(d2, d3, s[0], moh);
mux2_4 finalmux(mol, moh, s[1], y);
endmodule

48
Q

Aspects of Sequential Logic in System Verilog

A

1) Registers (w/ enables and resets)
2) Always statement
3) Modeling Flipflops
4) Syncronizer Circuits
5) Latches
6) Counters
7) Shifters
8) Tristate
9) Muxes
10) Case Statements + casez

49
Q

Always statement

A

Used for modeling behavioral Logic
The always statement is used to describe logic that reacts to changes in signals.
It is used for both combinational (always_comb or always @(*)) and sequential logic (always_ff or always @(posedge clk)).
It allows you to create timing-dependent behavior like flip-flops, state machines, combinational circuits, and more.
By defining an appropriate sensitivity list, the always block ensures that the desired hardware functionality is implemented accurately during both synthesis and simulation.

The output depends on both the current inputs and the past history of the system (typically triggered by a clock or reset signal).
This is useful for designing flip-flops, registers, counters, and other clocked elements.
The block is triggered by a clock edge (e.g., posedge clk for positive edge or negedge clk for negative edge).

EXAMPLE:
always @(posedge clk or posedge rst) begin
if (rst)
q <= 0; // Reset logic
else
q <= d; // Sequential logic: flip-flop behavior
end

50
Q

Always statement for synchronous sequential logic

A

In synchronous logic, the always block is triggered by clock edges (posedge or negedge) and is typically used for designing circuits that store data, such as registers, counters, and state machines.
In synchronous designs, the logic inside the block is only evaluated on the specified edge of the clock, ensuring predictable and repeatable timing.

51
Q

Always Statement in asynchronous logic

A

Always blocks can also be triggered by asynchronous signals such as resets. For example, a reset signal may be used to reset a flip-flop independently of the clock.

EXAMPLE:
always @(posedge clk or posedge rst_n) begin
if (rst_n)
q <= 0; // Asynchronous reset logic
else
q <= d; // Sequential logic on clock edge
end

52
Q

always_comb statement

A

A SystemVerilog-specific enhancement to describe combinational logic. The synthesis tool automatically infers the sensitivity list based on the variables used inside the block.
Equivalent to always @(*) but more descriptive and ensures that the block always behaves combinationally.

EXAMPLE:
always_comb begin
y = a & b; // Pure combinational logic
end

53
Q

always_ff statement

A

A SystemVerilog construct specifically for modeling sequential logic. It ensures that the block only contains sequential logic driven by clock or reset signals.
Helps avoid the accidental inclusion of combinational logic in what is meant to be a sequential block.

EXAMPLE:
always_ff @(posedge clk or posedge rst) begin
if (rst)
q <= 0;
else
q <= d;
end

54
Q

always_latch

A

Used for describing latch-based logic. This type of always block is sensitive to signal changes but typically has incomplete assignments inside, which can lead to inferred latches.
Not as common in practice but useful in specific cases where latches are intentional

EXAMPLE:
always_latch begin
if (enable)
q = d; // Latch behavior when enable is high
end

55
Q

Common Uses for Always blocks

A

1) Clocked Logic
2) Finite State Machines
3) Counter Logic
4) Combinational Logic (for outputs)

56
Q

Sensitivity List

A

The sensitivity list defines the conditions under which the always block is triggered:

For combinational logic, typically always_comb is used, meaning the block will be re-evaluated anytime any signal inside the block changes.
For sequential logic, the sensitivity list typically includes posedge clk or negedge clk to indicate that the block is evaluated on the rising or falling edge of the clock.
In some cases, other signals like reset or enable may also be included in the sensitivity list, such as in asynchronous reset designs.

57
Q

Posedge

A

Stands for positive edge or rising edge of a signal. It is used in sensitivity lists to indicate that the block of code should be triggered or executed when the specified signal transitions from a low logic level (0) to a high logic level (1). This is commonly used with clock signals or other control signals in sequential logic circuits.

Posedge (positive edge) refers to the moment when a signal transitions from logic 0 (low) to logic 1 (high).
When posedge is specified in an always block’s sensitivity list, the statements inside the block will execute every time the signal transitions to the rising edge.

58
Q

Modeling synchronous sequential logic

A

Requires “always_ff @(posedge clk)” and
nonblocking assignments

59
Q

Types of always statement

A

always →
always_comb → Same as ‘always’ but specifically for combinational logic
always_ff → Same as ‘always’ but specifically for sequential logic
always_latch →

60
Q

typedef statements

A

define statetype to be a two-bit logic value with one of several possibilities

61
Q

Enumerated encodings

A

Enumerated Encodings allow you to define a set of named values (states) with optional custom encodings.
They improve readability, maintainability, and type safety in your design.
Enumerations are particularly useful for describing finite state machines (FSMs) and other control logic in hardware designs.
Custom encodings can be applied for specific use cases, and synthesis tools map enumerated values to hardware efficiently.

Syntax: enum logic [n-1:0] { <list> } variable_name;
enumerators: The named values or states.
variable_name: The variable that will hold the enumerated value.
logic [n-1:0]: Optional, specifying the bit-width or encoding for the enumerators (if needed).</list>

Benefits:
1) Readability
2) Type Safety
3) Error Detection
4) Automatic Handling of State Machines
5) Simplified Coding

62
Q

Aspects of State Machines in System Verilog

A

1) Finite State Machines
2) Mealy Machines
3) Moore Machines
4) Enumerated encodings
5) Type Idiosyncracies
6) Parameterized Modules
7) Generate Statements
8) Memories
9) Multi-Ported Register Files + ROMs

63
Q

begin statement

A

begin is used to start a block of statements that are executed sequentially.
It is always paired with end to mark the end of the block.
begin-end is required when you have multiple procedural statements in blocks like if, else, always, initial, or case.

Used to group multiple statements into a single block. This is often referred to as a sequential block, where the statements inside the block are executed in the order they are written. The begin statement must be paired with an end statement to mark the end of the block.

The begin statement allows multiple procedural statements to be grouped together, ensuring that they are treated as one sequential unit.
It is particularly useful in situations where only a single statement is expected (like in if-else or case statements), but you want to execute multiple statements.

1) Sequential Execution: The begin-end block ensures that the statements inside it are executed in sequence, one after the other.
2) Grouping of Multiple Statements: Used to group multiple statements where only a single statement is syntactically allowed (like inside if-else or case constructs).
3) Required in Procedural Blocks: In always, initial, and other procedural blocks, the begin-end structure is necessary when more than one statement is present.

64
Q

Moore Machine

A

A type of finite state machine (FSM) in which the output depends only on the current state and not on the inputs. In a Moore machine, outputs are associated with states, and any changes to the output occur only when the state changes. This is in contrast to a Mealy machine, where the output depends on both the current state and the inputs.

In a state diagram of a Moore machine, each state is associated with an output value, and the state transitions are based on input conditions. The outputs are written inside the state, while the transitions between states are shown as arrows with labels based on inputs.

Key Characteristics of a Moore Machine:
State-Based Outputs: The output is determined solely by the current state, meaning that outputs are updated only on state transitions.
Synchronous: In digital design, Moore machines are typically synchronized to a clock signal, meaning the state transitions occur on clock edges (e.g., rising or falling clock edges).
Simpler Output Logic: Since the output depends only on the state, the output logic is generally simpler compared to a Mealy machine, which requires both state and input to determine the output.

EXAMPLE:
module divideby3FSM(input logic clk,
input logic reset,
output logic y);
logic [1:0] state, nextstate;
// State Register
always_ff @(posedge clk)
if (reset) state <= 2’b00;
else state <= nextstate;
// Next State Logic
always_comb
case (state)
2’b00: nextstate = 2’b01;
2’b01: nextstate = 2’b10;
2’b10: nextstate = 2’b00;
default: nextstate = 2’b00;
endcase
// Output Logic
assign y = (state == 2’b10);
endmodule

65
Q

statetype singals

A

Typically, statetype is declared as an enumerated type (enum) that defines various states in a state machine. Enumerations provide a clear, readable way to define named states instead of relying on raw binary encodings or numerical values. This practice improves code readability and maintainability.

Purpose:
statetype is used to represent the states of a finite state machine (FSM).
It helps in making FSM implementations more intuitive by giving meaningful names to different states rather than using numeric or binary values.
It can be used in both Mealy and Moore state machines.

The statetype in the example is defined as an enumerated type with named values RED, GREEN, and YELLOW. Each of these states is mapped to a binary value (in this case, 2-bit values).
The type is declared using typedef enum logic [1:0], where [1:0] defines the bit-width, suitable for holding 3 distinct states.

The current state (current_state) and next state (next_state) are variables of type statetype.
The state transition logic updates the current state based on the rising edge of the clock (posedge clk) or reset signal.
The next state logic determines the next state based on the current state.

Using an enumerated type like statetype makes the FSM much more readable compared to using raw binary or integer values (e.g., 00, 01, 10).
The state names (RED, GREEN, YELLOW) provide clarity in the design.

A default case is typically included in the case statement to handle any undefined states, ensuring that the FSM always transitions to a valid state.

66
Q

Enumerated Encoding for State Machines

A

Enumerated encoding plays a significant role in modeling state machines in SystemVerilog by improving readability, maintainability, and clarity. In the context of state machines, enumerated encoding allows designers to define the states of the machine using meaningful names (symbols), rather than using raw binary values or constants. This makes the design process easier to manage, reduces the likelihood of errors, and ensures that the simulation and synthesis tools can optimize the state machine effectively.

Using enumerated encoding means you can refer to states by their descriptive names instead of manually tracking binary-encoded values. This makes the state machine code much easier to understand and maintain.
Instead of tracking binary numbers like 2’b00, 2’b01, etc., you use state names like IDLE, RUN, STOP, which directly describe the behavior or purpose of that state.

Enumerated types ensure that the state machine can only assume valid, pre-defined states. This prevents accidental assignment of illegal values, which could cause undefined behavior.
The design tools can also issue warnings or errors if any value outside the enumerated set is assigned, helping to detect bugs early.

When changes are needed, modifying an enumerated type is far easier than tracking down and changing binary encodings. For example, adding or removing states can be done simply by updating the enum definition, rather than adjusting hard-coded binary values across the design.
This is especially beneficial in large or complex state machines where multiple states may be used in different parts of the design.

67
Q

Net types

A

Net types represent physical connections between different modules or components in a hardware design. Nets are used to model the interconnections of hardware elements, particularly where one signal can be driven by multiple sources (such as wires or tri-state buses). Unlike variables (like reg or logic), nets represent electrical connections that can have multiple drivers, and their values are usually determined by the values of the signals driving them.

Key Characteristics of Net Types:
1) Driven by Assignments: Nets represent values driven by multiple sources using continuous assignments (e.g., assign statements or module outputs).
2) No Value Storage: Nets do not store their value; they simply reflect the value driven by their drivers.
3) Multi-Driver Capability: Some nets (like wire or tri) allow multiple drivers, and the simulator resolves the final value based on the logic of the drivers.

68
Q

“logic” v. “reg”

A

logic (SystemVerilog Data Type):
Definition: In SystemVerilog, logic is a more flexible, general-purpose data type that can be used to model both combinational and sequential logic.

Usage:
1) logic can be used in both continuous assignments (using assign statements) and procedural blocks (like always blocks). This eliminates the confusion between wire (for combinational logic) and reg (for sequential logic) that existed in Verilog.
2) It is part of the four-state logic system, meaning it can represent values like 0, 1, Z (high-impedance), and X (unknown).

Advantages:
1) Unlike reg, logic can be used in both combinational and sequential logic contexts, making it more versatile.
2) It simplifies code by reducing the need for separate data types like wire and reg to differentiate between different types of assignments.

reg (Verilog Data Type):
Definition: In Verilog, reg is a data type used to represent variables that can hold their value across multiple simulation time steps. It is typically used in procedural blocks like always or initial.

Usage:
1) reg can store a value and is typically used in sequential logic (such as flip-flops) where signals need to be assigned in always blocks using non-blocking assignments (<=).
2) Despite its name, reg does not necessarily correspond to a hardware register. It can represent both combinational and sequential logic in Verilog.

Limitations:
1) Cannot be used with continuous assignments (assign statement). It is restricted to procedural blocks.
2) Single-bit or multi-bit values can be represented, but it doesn’t support the four-state logic system inherent in logic (introduced by SystemVerilog).

69
Q

“wire” v. “tri”

A

wire:
Definition: The wire type is the most basic and commonly used net type in SystemVerilog. It represents a connection that can carry a value driven by one or more sources. A wire does not store a value but simply reflects the value driven by its driver.

Characteristics:
1) A wire can be driven by multiple continuous assignments or outputs of modules.
2) No storage capability: It doesn’t retain or store a value; it always reflects the most recent value driven by its connected source(s).
3) A wire cannot go into a high-impedance state (i.e., Z). It will always have a defined logic level (0, 1, or x).
Commonly used for signals connecting modules or representing combinational logic.

tri:
Definition: The tri type is similar to wire, but it is specifically intended for three-state logic. It allows for multiple drivers and can enter a high-impedance (Z) state when no driver is actively driving the signal. This is particularly useful in bus systems where multiple drivers may need to drive the same signal at different times.

Characteristics:
1) A tri can be driven by multiple sources, and if none of them is driving it, the tri net can take on a high-impedance (Z) state.
2) This is useful for systems like shared buses where a signal might be driven by different components at different times, and when no component is driving the bus, the signal should remain in the Z state.
3) It allows for multiple drivers to share the same signal, with some drivers able to “turn off” by assigning the signal to Z, effectively disconnecting themselves.

70
Q

Parameterized modules

A

Parameterized modules allow you to define modules with customizable behavior or structure.
You can define parameters using the parameter keyword, and these parameters can be overridden during instantiation.
Multiple parameters can be used in a single module, and they help create flexible, scalable, and reusable designs.
Instantiating parameterized modules involves specifying the desired parameter values, or you can use default values.
localparam is used for internal constants that should not be changed by the user.

SYNTAX:
module module_name #(parameter parameter_name = default_value) (…);
// Module internals using the parameter
endmodule

*A parameterized module is defined by declaring one or more parameters inside the module. The parameter keyword is used for this purpose.

71
Q

Generate Statement

A

The generate statement is used to create multiple instances of code, such as module instantiations, logic, or connections, based on certain conditions or loops. This feature is especially useful for replicating code structures like regular hardware arrays, bus systems, or other repetitive components without manually writing out each instance.

There are two types of generate constructs in SystemVerilog:
1) Conditional generate: Use of if or case inside a generate block.
2) Loop generate: Use of for loops to instantiate code multiple times.

Loop-based generate: Used to replicate code structures multiple times, such as instantiating multiple modules or defining repetitive logic.
Conditional generate: Used to include or exclude certain code or instantiate specific modules based on parameter values or conditions.
Case-based generate: Similar to conditional generate but allows more complex selection using case statements.
Genvar and Named Scoping: You can use genvar to control the loop iteration in generate blocks, and each block can have its own scope name for better signal referencing.
Key Points:
1) The generate construct is ideal for repetitive hardware structures like arrays of logic, adders, or bus systems.
Parameters and genvars allow flexible hardware generation, making designs scalable.
2) The generate block is optional in SystemVerilog, but it’s often used to improve readability and structure.

72
Q

read and write busses v. bidirectional bus for memories

A
73
Q

Using Seperate Read/Write Busses in System Verilog

A

Separate Read and Write Buses
Description:
In this approach, there are two separate buses: one for writing data to the memory and another for reading data from the memory. These buses are completely independent of each other and can function simultaneously, allowing concurrent read and write operations if the memory supports it.

Advantages:
1) Simplicity: The design is straightforward, and the logic is simple to implement because the buses for reading and writing are completely independent.
2) Concurrent Operations: Since the read and write operations use different buses, it’s possible to read and write at the same time (if the memory supports it), leading to better performance in applications requiring simultaneous read/write operations.
3) No Tri-State Logic: Tri-state logic can be difficult to simulate and synthesize correctly in modern FPGAs or ASICs. Separate buses avoid this complexity.
4) No Contention: Since the buses are separate, there’s no possibility of bus contention (where two signals drive the same bus simultaneously, potentially causing conflicts).

Disadvantages:
1) Increased Pin/Signal Count: Separate read and write buses mean that you need more signals, which can increase the number of pins in your design. This is a major concern in designs with limited I/O or for systems where the bus width is large.
2) Larger Area: Two buses (one for read and one for write) mean more wires and multiplexers, potentially leading to a larger silicon footprint and higher resource usage in FPGAs or ASICs.
3) Power Consumption: More buses could lead to higher power consumption due to more signals switching.

74
Q

Using a Bidirectional bus in System Verilog

A

Bidirectional Bus
Description:
In the bidirectional bus approach, a single bus is shared for both reading from and writing to the memory. A tri-state buffer or equivalent control mechanism controls when the bus is used for reading or writing. A control signal (usually called read_enable or write_enable) determines whether the bus operates in read mode or write mode.

Advantages:
1) Fewer Signals/Pins: A bidirectional bus reduces the number of I/O pins since the same bus is shared for both read and write operations. This is particularly beneficial in designs with limited I/O or large data buses (e.g., 32-bit, 64-bit data buses).
2) Reduced Area: Since the read and write logic share the same bus, fewer wires are needed, which can lead to a reduction in the physical area of the design.
3) Lower Power Consumption: Fewer signals switching due to the shared bus can lead to reduced power consumption compared to separate buses.

Disadvantages:
1) Timing Complexity: Tri-state buses can introduce timing challenges, particularly if both read and write signals are accidentally enabled at the same time (leading to bus contention). Proper timing and control signals need to be carefully managed.
2) Bus Contention: If the tri-state control signals (read_enable and write_enable) are not correctly managed, two drivers may attempt to drive the bus simultaneously, leading to contention and unpredictable behavior.
3) No Concurrent Read/Write: Since the bus is shared, you cannot read and write simultaneously on the same clock cycle. The operation must alternate between reading and writing.
4) Synthesis Challenges: Some modern FPGAs and ASIC flows may not efficiently handle tri-state logic. Many FPGA fabrics do not natively support tri-state buffers inside the fabric and instead require logic to simulate tri-state behavior, which can lead to inefficient designs.

75
Q

multiported register files

A

A multiported register file is a specialized memory structure that allows multiple read and write ports to access and modify the data in a register file concurrently. This is commonly used in hardware designs such as CPUs, DSPs, or FPGAs where multiple operations need to access registers simultaneously. Multiported register files are typically used in situations where performance and parallelism are important.

In SystemVerilog, implementing a multiported register file involves creating a memory structure (register array) with multiple read and write interfaces, each of which can independently access the memory in a single clock cycle.

Key Features of Multiported Register Files:
1) Multiple Read Ports: Allows reading from multiple registers simultaneously. For example, in a CPU, two read ports are typically used in the instruction execution stage to fetch operands for operations.
2) Multiple Write Ports: Allows writing to multiple registers simultaneously. This can be useful in designs where multiple sources need to update the register file concurrently.
3) Parallel Access: Multiported register files enable parallel access to registers, which is essential in designs like pipelined processors or vector processors, where multiple functional units may need access to the same set of registers.
4) Priority and Arbitration: When implementing multiple write ports, arbitration logic may be necessary to resolve conflicts if multiple writes target the same register at the same time.

76
Q

testbench

A

A testbench in SystemVerilog (or Verilog) is a self-contained environment designed to verify the functionality of a hardware design module (or a system of modules). The testbench provides inputs to the design under test (DUT), monitors outputs, and checks for correctness, often by comparing the output against expected values.

The main role of the testbench is to simulate how the design behaves under various conditions, stimuli, and edge cases, ensuring that it meets its functional requirements before the design is synthesized and implemented in hardware. The testbench is usually not synthesized and exists solely for the purpose of simulation and verification.

A testbench is a critical component in verifying the correctness of a hardware design by simulating the behavior of the design under test (DUT). It provides stimulus to the DUT, observes its outputs, and checks whether the design behaves as expected. Testbenches can range from simple procedural scripts for small designs to highly complex environments with self-checking, assertions, random stimulus generation, and reusable verification components for larger, more complex designs. The goal of a testbench is to catch design errors early in the simulation phase before synthesizing the design into hardware.

Key Components of a Testbench:
Design Under Test (DUT): The hardware module or system you want to verify. The DUT is instantiated in the testbench, and its inputs and outputs are connected to the testbench logic.

Stimulus Generator: The part of the testbench that generates input signals to drive the DUT. This can be simple assignments, waveform generators, or complex stimulus generation like constrained random testing.

Clock and Reset Generation: Most designs require a clock and a reset signal to function. These signals are typically generated by the testbench.

Monitor: Observes the output signals from the DUT. It can be used to check the values of the outputs and report errors or unexpected behavior.

Checker: Compares the DUT outputs with the expected results. If a mismatch is found, the checker typically reports the failure.

Test Cases: These are specific scenarios or sets of inputs that test different behaviors of the DUT. They are often written in procedural blocks (like initial blocks) to test various conditions.

Self-Checking Mechanisms: Many testbenches are designed to be self-checking, meaning they automatically verify whether the outputs of the DUT match expected results without requiring manual checking.

Assertions: SystemVerilog assertions (SVA) can be used to verify specific properties of the design, such as ensuring timing constraints or other conditions are always met during simulation.

77
Q

Types of Testbenches

A

Types of Testbenches:
Basic Testbench: A simple testbench like the one shown above, where the inputs and expected outputs are hardcoded. This type is usually used for small designs and straightforward testing.

Self-Checking Testbench: A testbench that automatically compares the outputs of the DUT to the expected results and reports errors without requiring manual checking.

Constrained Random Testbench: This is part of verification methodologies like UVM (Universal Verification Methodology) or VMM (Verification Methodology Manual), where random inputs are generated within certain constraints, and the DUT’s outputs are verified across a wide range of possible inputs.

Testbench with Assertions: Assertions are used to check for violations of properties during the simulation, such as timing constraints, valid signal transitions, or protocol adherence.

Directed Testbench: Inputs are designed to specifically target certain functionality or corner cases of the DUT. This is useful for functional coverage of critical parts of the design.

Transaction-Level Testbench (TLM): A high-level testbench where transactions are generated rather than individual signal transitions. This is useful for complex systems where working at a higher level of abstraction improves productivity.

78
Q

Testbench Best Practices

A

Thorough Coverage: The testbench should cover all possible scenarios, including corner cases, edge cases, and invalid inputs.
Self-Checking: It should verify whether the DUT’s output matches expected results and automatically report errors.
Parameterized: It should allow parameterization to easily adjust the testbench for different configurations or scenarios.
Reusable: For large projects, testbenches should be modular and reusable to facilitate testing across different designs or modules.
Assertions: It should use assertions to check for properties and protocols dynamically during the simulation.
Scalable: The testbench should support large designs and be adaptable to various complexity levels (e.g., scaling from single-module verification to full-system verification).

79
Q

Device under test (DUT)

A

The hardware module or system you want to verify. The DUT is instantiated in the testbench, and its inputs and outputs are connected to the testbench logic.

80
Q

Stimulus Generator

A

The part of the testbench that generates input signals to drive the DUT. This can be simple assignments, waveform generators, or complex stimulus generation like constrained random testing.

81
Q

Clock and Reset Generation in Test benches

A

Most designs require a clock and a reset signal to function. These signals are typically generated by the testbench.

82
Q

Monitor in Testbenches

A

Observes the output signals from the DUT. It can be used to check the values of the outputs and report errors or unexpected behavior.

83
Q

Checker in Testbenches

A

Compares the DUT outputs with the expected results. If a mismatch is found, the checker typically reports the failure.

84
Q

Test Cases

A

These are specific scenarios or sets of inputs that test different behaviors of the DUT. They are often written in procedural blocks (like initial blocks) to test various conditions.

85
Q

Test Vectors

A

A test vector is a set of inputs and corresponding expected outputs applied to the DUT for verification. Each test vector represents one possible scenario of inputs that the hardware might encounter during operation, and the expected outputs are the correct responses that the DUT should generate based on those inputs.

A test vector consists of:
1) Input values: The set of input signals (e.g., data inputs, control signals) that are applied to the DUT.
2) Expected output values: The correct values the DUT is expected to produce in response to the given inputs.
3) Timing information (optional): In some cases, test vectors may also specify when inputs should change and when outputs should be sampled.

86
Q

Test Vector File

A

A test vector file is a file that contains multiple test vectors, typically in a text format or some standard format, which can be loaded and applied to a DUT during simulation or hardware testing. These files are used to automate the process of applying input stimuli to the DUT and verifying that the outputs match the expected results.

Test vector files are often used in simulation testbenches to provide structured and repeatable sets of inputs for comprehensive testing. They allow engineers to efficiently apply a large number of test cases to the DUT without manually coding each input set.

In some cases, especially for large designs or when testing in a hardware environment, test vector files might be stored in binary format to save space and increase efficiency.

87
Q

Application of test vectors and test vector files

A

1) Simulation: Test vector files are heavily used in simulations to automate the testing of hardware designs. They enable systematic testing of multiple scenarios and edge cases, ensuring the DUT behaves as expected.

2) Hardware Testing: In real hardware verification, test vector files are used to test FPGAs, ASICs, or other hardware components by applying predefined input patterns and comparing the actual hardware output to the expected output.

3) Regression Testing: In automated testing environments, test vector files allow for consistent regression testing, where the same set of inputs is applied to the DUT over multiple iterations (e.g., after design changes) to ensure that the functionality remains correct.

4) Design Validation: Engineers use test vectors to validate that the design meets specifications. By systematically applying test vectors, they can verify correct operation across a wide range of inputs and scenarios.

5) Corner Case Testing: Test vectors are used to test specific corner cases, such as when input values are at their maximum or minimum, or under conditions that could cause potential errors in the DUT.

88
Q

Initial statement

A
89
Q

self-checking test bench

A

Many testbenches are designed to be self-checking, meaning they automatically verify whether the outputs of the DUT match expected results without requiring manual checking.

90
Q

assert statement

A

SystemVerilog assertions (SVA) can be used to verify specific properties of the design, such as ensuring timing constraints or other conditions are always met during simulation.

91
Q

Testbench Integration

A

Test vector files are often used in combination with testbenches to automate verification. The testbench reads each vector from the file, applies the inputs to the DUT, captures the output, and checks whether the actual output matches the expected output. This approach allows for systematic and thorough testing.

92
Q

signal drivers

A

Signal drivers refer to the sources (or entities) that actively drive or assign values to signals or nets in digital hardware designs. In SystemVerilog (and Verilog), nets (such as wire or tri) can be driven by one or more signal drivers, which can come from module outputs, continuous assignments, or procedural assignments. The combination of all the drivers determines the final value of the net based on the driving logic.

A driver is an assignment or source that places a value on a signal or net. The value of the signal is usually determined by the combination of all active drivers, based on certain rules for resolving multiple values (such as logic resolution for conflicting drivers).

Types:
1) Continuous Assignment -These are assignments that continuously drive a value onto a net or signal.
2) Module Outputs -When a module is instantiated, its output ports act as drivers for the connected signals. The output of the module assigns values to the signals (wires or nets) connected to it.
3) Procedural Assignments -Inside procedural blocks (always, initial, etc.), variables like logic or reg can be assigned values. When these procedural assignments occur, they act as drivers for those signals.
4) Bidirectional (Tri-State) Drivers -Bidirectional buses or signals are often driven by tri-state buffers, where the signal can either be driven by a value (0 or 1), or the driver can disengage and leave the signal in a high-impedance (Z) state. This allows multiple sources to potentially drive the same signal, but only one driver can be active at a time.
5) Internal Logic Drivers -Logic gates and other combinational components also act as drivers for the signals they produce. For example, the output of an AND gate is a driver for the signal connected to the output.

*When a signal (particularly a net type like wire or tri) is driven by multiple sources or drivers, the value of the signal is determined by resolution rules. Different logic values or types (such as 1, 0, X, Z) may require a resolution function to compute the final value of the signal. Here’s how different situations are resolved:

93
Q

tri net declaration

A
  • Definition: The tri type is a three-state net that can be driven by multiple drivers or can go into a high-impedance (Z) state when no driver is active.
  • Behavior: When not driven, the tri net can have a high-impedance value (Z). However, the last active driver determines the state of the tri net. When multiple drivers are connected to a tri net, the standard SystemVerilog rules for resolving values apply (e.g., driving a logic 1, logic 0, or high-impedance state).
  • Usage: It is typically used for bus signals where multiple sources may be enabled or disabled dynamically, like data buses.

EXAMPLE:
module tri_example;
tri bus; // Declaring a tri-state bus
assign bus = (enable1) ? signal1 : 1’bz;
assign bus = (enable2) ? signal2 : 1’bz;
endmodule

94
Q

trireg net declaration

A
  • Definition: The trireg type is similar to tri in that it can go to a high-impedance state, but it retains the last driven value when no driver is actively driving it. This means the trireg net holds its value after a driver turns off, rather than immediately going to high impedance.
  • Behavior: When no driver is active, the trireg net keeps its last driven value, and it will only go to the high-impedance state when explicitly set. It’s like a register that maintains its last state when no one is driving it.
  • Usage: This is used in cases where you need a signal to remember the last value, even if the drivers are disconnected, such as in bus hold logic or certain latch-based designs.

EXAMPLE:
module trireg_example;
trireg bus; // Declaring a trireg signal
assign bus = (enable1) ? signal1 : 1’bz;
assign bus = (enable2) ? signal2 : 1’bz;
endmodule

95
Q

Type Safety

A

Type safety in SystemVerilog ensures that variables and signals are used in a consistent and correct manner by enforcing compatibility between data types. It helps prevent common errors such as assigning the wrong type of data to a variable or performing invalid operations on incompatible types. SystemVerilog achieves type safety through compile-time checks, enforcing data type rules, and providing mechanisms like casting to handle conversions between types when necessary. By adhering to type safety, designers can reduce bugs, enhance the maintainability of the code, and ensure more reliable hardware designs.

For Enumerated Types: SystemVerilog allows you to define enumerated types, which represent a set of named values. Enums provide type safety by ensuring that only valid, defined values can be assigned to the variable.

For Operations: Operations in SystemVerilog, like addition, subtraction, or logical comparisons, must involve compatible data types. Type mismatches (e.g., trying to add a string and an integer) can result in errors.

for Implicit Conversions: While SystemVerilog enforces type safety, it also supports implicit conversions between some types. For example, it allows implicit conversion between int and logic types, which can sometimes be convenient but also potentially risky.
For cases where implicit conversion is not appropriate, SystemVerilog allows explicit casting to convert between types safely.

for Type declarations: SystemVerilog requires variables to be declared with specific types, ensuring that only operations appropriate for that type are allowed.

for struct and union: SystemVerilog allows you to define structs and unions for grouping related data. It ensures that only the correct fields are accessed and that they are accessed in a type-safe manner.

for Parameters: SystemVerilog supports parameterized modules and functions. With type safety, it ensures that the parameters passed to modules or functions are of the correct type.

96
Q

High Impedance (Z) state

A

The high-impedance (Z) state represents a condition where a signal is not actively driven by any logic value (0 or 1), essentially disconnecting the signal from the circuit.
It is commonly used in shared buses, I/O pins, and systems with multiple drivers to avoid conflicts and allow controlled sharing of signals.
The high-impedance state is managed using tri-state buffers and is represented by Z or z in SystemVerilog.
Proper handling of tri-state logic is crucial to avoid issues like bus contention and floating signals.
In systems using the Z state, careful control over which drivers are active is necessary to ensure proper functionality and prevent collisions.

EXAMPLE:Here, both cpu_data and peripheral_data share the data_bus. At any given time, only one device (CPU or peripheral) can drive the bus, while the other device must place the bus in a high-impedance state (8’bz).
tri [7:0] data_bus;
assign data_bus = (cpu_enable) ? cpu_data : 8’bz; // CPU drives the bus
assign data_bus = (peripheral_enable) ? peripheral_data : 8’bz; // Peripheral drives the bus

Characteristics of the High Impedance (Z) State:
1) No Active Drive: In the Z state, the signal is not driven by any logic level (neither 0 nor 1). It’s like an “open circuit” where the signal is left floating.
2) Shared Buses: The Z state is commonly used in systems with shared buses or bidirectional buses, where multiple drivers might need to drive a signal at different times. When a particular driver is not in use, it places the signal in the Z state to allow other drivers to take over.
3) Tri-State Buffers: The Z state is managed by tri-state buffers, which can drive a signal as 0, 1, or disconnect (set to Z). The control of these buffers is done through an enable signal that determines whether the buffer drives the bus or leaves it in a high-impedance state.
4) Signal Resolution: If no driver is driving the signal, it remains in the Z state. If a signal is driven by multiple sources, it could cause bus contention unless only one driver is active at any given time.

97
Q

Th Seven Idioms

A

“idioms” refer to common, efficient, and standardized patterns of code that developers use to solve specific problems. These idiomatic patterns simplify the design, make the code more readable, and help avoid common pitfalls. They typically evolve over time as best practices and are frequently employed in design and verification environments.

1) Initialization Idiom -Initialize variables at the time of declaration to avoid undefined behavior
int count = 0;

2) Forever Loop Idiom -Use a forever loop to run a task or logic continuously.
initial begin
forever begin
#10 clk = ~clk;
end
end

3) Clocking block Idiom -Use clocking blocks to synchronize signal sampling and driving.
clocking cb @(posedge clk);
input data_in;
output data_out;
endclocking

4) Blocking vs Non-Blocking Assignment Idiom -Use blocking (=) for combinational logic and non-blocking (<=) for sequential logic.
// Combinational logic
always_comb begin
sum = a + b;
end
// Sequential logic
always_ff @(posedge clk) begin
sum <= a + b;
end

5) Array Initialization Idiom -Initialize dynamic arrays using constructors or by allocating size dynamically.
int dynamic_array[];
initial begin
dynamic_array = new[10]; // Allocate array with 10 elements
end

6) Assertions Idiom -Use assertions for design and verification checks.
assert (signal == 1) else $fatal(“Signal must be high!”);

7) Parameterized Modules Idiom -Use parameters in modules to make reusable, configurable designs.
module adder #(parameter WIDTH = 8) (input logic [WIDTH-1:0] a, b, output logic [WIDTH-1:0] sum);
assign sum = a + b;
endmodule

98
Q

List of unsynthesizable constructs

A

Dynamic arrays, queues, classes, assertions, initial blocks, and forever loops are typically not synthesizable.

DIV and MOD operators are so expensive that they may as well be unsynthesizable as well

99
Q

“hold time constraints”

A

Prevent data from changing too soon after the clock edge. If the data changes too quickly, the flip-flop might latch incorrect or unstable data, leading to logic errors in the circuit.

100
Q

“time precision”

A
  • Definition: Time precision controls how finely time is represented within the simulation. It sets the granularity of time measurement.
  • Purpose: It specifies how many decimal places of time can be resolved.
  • Example: If your time unit is 1ns and time precision is 0.1ns, then simulation events can be scheduled with a precision down to one-tenth of a nanosecond.
101
Q

“time unit”

A
  • Definition: The time unit specifies the smallest unit of time used in your simulation for measuring delays and event scheduling.
  • Purpose: It defines the scale at which delays and timing are interpreted.
  • Example: If you define a time unit as 1ns, all time-related operations (like #10 for delay) will be interpreted in terms of nanoseconds.
102
Q

Hold Time

A

Refers to the minimum amount of time that the data at the input of a flip-flop (or any sequential element) must be stable after the active clock edge (either rising or falling) to ensure the data is correctly latched.

103
Q

Hold Time Violation

A

Occurs when the data changes too soon after the clock edge, violating the hold time constraint. This can cause the flip-flop to capture incorrect data or behave unpredictably.

104
Q

Latch Interference

A

Phenomenon in digital designs, particularly when using level-sensitive latches, where the improper control of signal timing between different stages of a sequential circuit can cause unintended behavior. It primarily happens when data propagates through multiple latches in the same clock cycle due to the overlap of clock phases.
In designs that use two-phase clocking (where two latches are used in series, one latch active on the positive clock phase and another on the negative phase), latch interference can occur when there is an overlap in the clock phases. This overlap allows data to propagate through multiple stages of latches within the same clock cycle, which can result in data corruption.

Causes of Latch Interference:
Clock Skew: If there is a delay or misalignment between the clock signals driving different latches, it can cause the phases of the clock to overlap, allowing data to pass through multiple latches when it should have been held.
Clock Gating Issues: In some designs, clock gating logic may inadvertently cause two consecutive latches to be transparent at the same time.
Setup and Hold Violations: Timing violations can cause unintended data propagation through latches when proper setup or hold times are not maintained.

105
Q

Inferred latches

A

Unintended latches that are automatically generated by synthesis tools during the process of converting high-level hardware description language (HDL) code (like SystemVerilog or Verilog) into gate-level implementations. These latches typically arise when certain conditions in combinational logic are not fully specified.

How Inferred Latches Occur:
Option 1) Incomplete Conditional Statements: The design does not specify what should happen for all possible conditions (i.e., all branches of if, case, or similar statements are not covered).
Option 2) Uninitialized Signals: Signals are not given explicit values for all possible paths through the logic, meaning that under certain conditions, the signal will hold its previous value.
Option 3) Improper Use of Blocking Assignments: When using blocking assignments (=) in combinational always blocks (always_comb), an inferred latch can result if all branches are not accounted for.