Verilog Notes
Verilog Notes
{i1,i2}- concatination opertator - contatinates the input i1 and i2 and assigns them to result[3:2]
In verilog the lsb to sg goes from right to left (ie)
[msb:lsb]
2) Behavioral modelling
Used in sequential logic (flip flops)
Use of always block
1. To model repetitive activity in a digital design. Ex. clock generation.
From <https://vlsiverify.com/verilog/behavioral-modeling/>
always @(<sensitivity_list>)
<single statement>
From <https://vlsiverify.com/verilog/behavioral-modeling/>
3) Structural Modelling
In this type we instantiate blocks (those blocks can be made up of behavioral or dataflow modelling )
Instantiation
Example
CIRCUIT DIAGRAM
Gate declaration ex
Xor xor1(op,a,b);
Circ dig
5) 1 can represent
Logic one
Strong one
true - if statements
If(s) executes when s-1
Else-executes when s=0
High state
6) X- unknown
We don’t know what the op will be
Conflict- there are multiple values (ie the fin might be floating so we don’t know if it’s a one or zero )
Metastability - the clock and the input change at the same time so there might be a uncertainity in the output -(no proper setup and hold time )
Uninitialized- lets take a d flip flop with positve edge rising ( what is the value of the flip flop b4 the rising edge of the clock)
From <https://www.chipverify.com/verilog/verilog-syntax>
3'b010; // size is 3, base format is binary ('b), and the number is 010 (indicates value 2 in binary)
3'd2; // size is 3, base format is decimal ('d) and the number is 2 (specified in decimals)
8'h70; // size is 8, base format is hexadecimal ('h) and the number is 0x70 (in hex) to represent decimal 112
9'h1FA; // size is 9, base format is hexadecimal ('h) and the number is 0x1FA (in hex) to represent decimal 506
4'hA = 4'd10 = 4'b1010 = 4'o12 // Decimal 10 can be represented in any of the four formats
8'd234 = 8'D234 // Legal to use either lower case or upper case for base format
32'hFACE_47B2; // Underscore (_) can be used to separate 16 bit numbers for readability
From <https://www.chipverify.com/verilog/verilog-syntax>
From <https://www.chipverify.com/verilog/verilog-syntax>
The negative numbers are converted into 2s complement and then they are stored
Eg:
x=-6'd3;// the 2's complement of 3 is calculated and then stored in X
If the last digit is one (1) you need to extend the sign bit to how much ever value you need to preserve the sign
For example, here is an eight-bit two's complement representation of some integer:
1001 0110
and here is the 16-bit two's complement representation of the same integer:
1111 1111 1001 0110
From <https://chortle.ccsu.edu/assemblytutorial/zAppendixH/appH_12.html>
Even though u are extending the bit you need to preserve the sign (1)
❗ ! vs ~ in Verilog
Operator Meaning Works On Result
! Logical NOT 1-bit value 1-bit (0 or 1)
~ Bitwise NOT Bit-vector (or int) Bitwise inverted
But if you want to XOR two 4-bit values as if they are booleans (i.e., non-zero = true), you can reduce them down to 1-bit:
Example: 4-bit logical XOR behavior
But if you want to XOR two 4-bit values as if they are booleans (i.e., non-zero = true), you can reduce them down to 1-bit:
Example: 4-bit logical XOR behavior
Arithmetic operators
1) + it is used to add any 2 numbers and store the result
a=3'b101;
b=3'b110;
c=a+b;
Note that c must be 3 bits to store the value of a+b;
Also if a extra term results becasuse of the carry operator, like if the sum of the last 2 terms turns out to be one then,the re will be an extra bit, that bit will get truncated
unless c is a 4 bit term
2) Subraction operator
Subracts numbers and stores the result
Eg: (same values frm b4)
c=a-b(takes the 2c complement of b and it is added with A and stored in C
3) Multiplication operator
c=a*b;
The multiplied value is stored in x
4) Division operator
c=a/b;
Forms a barrel shifter hardware
Eg
y=27/8 8=2^3
27=11011;
After division 27 becomes
00011; you shift means u remove the last 3 terms and then put the remaining terms in there;
And replace the terms with zero
REPEAT Statement:
You're on the right track! Let's break everything down step-by-step to clarify repeat, the bit-widths, and why a and b have 16 values while cin only has 2.
repeat(n) in Verilog
Think of Verilog's repeat(n) as:
repeat(n) begin
// code block
end
This simply repeats the code block n times, no automatic variable increment like a for loop. It is not the same as a Python for i in range(n) in terms of variable scope — it just repeats, nothing more.
So if you want to increment something like a = a + 1, you must explicitly write it inside the block, as you see in your image.
✅ Summary Notes
Concept Explanation
repeat(n) Executes the block exactly n times (like a loop, but without automatic index variable)
a and b Are 4-bit variables → 2⁴ = 16 values each (0 to 15)
cin Is 1-bit → only 2 values (0 and 1)
Total Cases 16 × 16 × 2 = 512
~cin Bitwise NOT (flips 0↔1)
$monitor(...) Prints variables every time one of them changes
If you'd like, I can also help you write this same nested loop structure using a for loop style in Verilog for better control. Would you like that?
From <https://chatgpt.com/c/68503ce8-5f54-8011-90de-5ec992bbb38b>
Absolutely! Let’s break down case statements in Verilog in a very simple and clear way — with examples, notes, and common pitfalls.
Syntax
case (expression)
value1: statement1;
value2: statement2;
...
default: default_statement;
endcase
✅ Basic Example
Let’s say we want to design a 2-to-1 multiplexer:
always @(*) begin
case (sel)
2'b00: y = a;
2'b01: y = b;
default: y = 1'b0; // optional
endcase
end
Case vs If-Else
if-else case
Good for range comparisons Good for checking exact values
Can be less readable with many cases Very readable for fixed choices
Supports inequalities (>, <, etc) Only equality matching
1. default case
• Always add a default case to avoid latch inference (especially in combinational logic).
• Example:
default: y = 8'b00000000;
2. Full coverage
• If you don’t handle all possible input values, Verilog might create unexpected hardware (like latches).
3. Expression width
• Make sure the case expression width matches the value widths.
case (sel) // sel is 2 bits
2'b00: ... // good
2: ... // also OK (2 == 2'b10)
endcase
Common Mistakes
Mistake Fix
Missing endcase Always end your case block with endcase.
No default case Add one even if it's a dummy assignment.
Using = in procedural blocks without reg type Declare outputs as reg.
Not using always @(*) for combinational logic Use @(*) to cover all input sensitivities.
✨ Summary
Component Purpose
case Multi-way selection based on exact value
sel Selector input (expression in case)
default Optional fallback (important for safety)
endcase Required to close the block
Use in always @(*) or always @(posedge clk)
Would you like to try a quiz or exercise using case to test your understanding?
From <https://chatgpt.com/c/68503ce8-5f54-8011-90de-5ec992bbb38b>
1
begin/end keywords are mandatory when you have multiple statements within an always block.
In your 1st always block, you don't need begin/end since the case statement is considered a single statement.
However, in your 2nd always block, you have 3 top-level if statements, which means you need to group them together inside begin/end. Here is the code with different whitespace to clearly show the separate
statements:
always@(posedge clock or state) begin
// Statement 1
if(!state) outstate <= 4'd0;
// Statement 2
if(state == 2'd1)
if(outstate != 4'd9)
outstate <= outstate +4'd1;
else
outstate <= 4'd0;
// Statement 3
if(state == 2'd2) outstate <= outstate;
end
Since this code compiles without syntax errors, it demonstrates a couple things:
1. The begin/end keywords shown are mandatory
2. No other begin/end keywords are needed
However, other begin/end keywords are optional. You may decide to use them in every if statement. Here is another way to write the code:
always@(posedge clock or state) begin
if (!state) begin
outstate <= 4'd0;
end
if (state == 2'd1) begin
if (outstate != 4'd9) begin
outstate <= outstate +4'd1;
end else begin
outstate <= 4'd0;
end
end
if (state == 2'd2) begin
outstate <= outstate;
end
end
The same rules apply for initial and final procedural blocks, just like they do for always blocks.
From <https://stackoverflow.com/questions/70344979/usage-of-begin-end-in-design-modules/70350101#70350101>
This type of code assigns priority to the inputs ie the zeros gets executed first and fastest (00)
And then 11 is given the next priority and so on
Absolutely! Here's a clear and concise set of notes on reduction operators in Verilog, with detailed explanations and examples.
&a → R duc i A D
• Meaning: Are all bits 1?
• a = 1101 → 1 & 1 & 0 & 1 = 0
assign y = &a; // y = 0
|a → R duc i OR
^a → R duc i XOR
• Meaning: XOR all bits → true if odd number of 1's
• a = 1101 → 1 ^ 1 ^ 0 ^ 1 = 1
assign y = ^a; // y = 1 (since three 1's)
~&a → R duc i A D
• Equivalent to: ~(&a)
• a = 1101 → &a = 0 → ~0 = 1
assign y = ~&a; // y = 1
~|a → R duc i OR
• Equivalent to: ~(|a)
• a = 1101 → |a = 1 → ~1 = 0
assign y = ~|a; // y = 0
Key Observations:
• Reduction operators convert a vector into a single logic value.
• They are often used in control logic, comparisons, zero-checks, and priority logic.
✅ Use Cases
1. Zero check:
assign is_zero = ~|data; // true if all bits in data are 0
1. All-ones check:
assign is_full = &data; // true if all bits are 1
1. Odd parity check:
assign odd_parity = ^data;
1. Even parity check:
assign even_parity = ~^data;
Summary Table:
| Input Bits | &a | |a | ^a | ~&a | ~|a | ~^a |
|-----------------|----|----|----|------|------|------|
| 0000 | 0 | 0 | 0 | 1 | 1 | 1 |
| 1111 | 1 | 1 | 0 | 0 | 0 | 1 |
| 1010 (2 ones) | 0 | 1 | 0 | 1 | 0 | 1 |
| 1101 (3 ones) | 0 | 1 | 1 | 1 | 0 | 0 |
Let me know if you'd like this as a PDF, or want visual waveforms for simulation!
From <https://chatgpt.com/c/6852dd67-aa7c-8011-b100-bea6388d1c95>
Let's deeply break down the Verilog expression from your image:
Original Code:
assign Y = ~|S ? I[0] : (&S ? I[3] : (S[0] ? I[1] : I[2]));
Syntax:
condition ? value_if_true : value_if_false
From <https://www.google.com/search?
q=ternary+operator&oq=tenary+&gs_lcrp=EgZjaHJvbWUqDAgBEAAYChixAxiABDIGCAAQRRg5MgwIARAAGAoYsQMYgAQyDAgCEAAYChixAxiABDIJCAMQABg KGIAEMg8IBBAAGAoYgwEYsQMYgAQyCQgFEAAYChiABDIJCAYQABgKGIAEMgkIBxAAGAoYgAQyCQgIEAAYChiABDIJCAkQABgKGIAE0gEIMzYzMWowajeoAgCwAgA& sourceid=chrome&ie=UTF-8>
Step-by-Step Evaluation:
Let’s go through the ternary conditions in priority order:
✅ 1. ~|S ? I[0]
• This checks if all bits of S are 0.
• If true → output Y = I[0]
❌ Else → Ch ck &S ? [3]
• Checks if all bits of S are 1.
• If true → output Y = I[3]
❌ Else → Ch ck S[0] ? [1] : [2]
• If S[0] is 1 → Y = I[1]
• Else → Y = I[2]
C d C i :
assign Y = ~|S ? I[0] : // if all S bits are 0 → I[0]
(&S ? I[3] : // else if all S bits are 1 → I[3]
(S[0] ? I[1] : // else if S[0] is 1 → I[1]
I[2])); // else → I[2]
Summary:
• This is a compact and clever way of implementing conditional selection based on multiple conditions using reduction operators .
• Very common in FSMs or MUX logic where the control signal (S) is a few bits wide.
Let me know if you want a waveform example or how to convert this to a case statement or always block!
From <https://chatgpt.com/c/6852dd67-aa7c-8011-b100-bea6388d1c95>
Absolutely — let's walk through the syntax of how nested ternary operators (? :) work in Verilog, especially when implementing something like a 4:1 multiplexer using them.
Syntax Tips:
• You can nest ternary operators as deeply as needed, but use parentheses or formatting to keep it readable.
• Think of it like a decision tree: top condition gets checked first, then fallbacks go deeper.
• Verilog evaluates right to left for nested ternaries.
Let me know if you’d like the always block version or a case version too!
From <https://chatgpt.com/c/6852dd67-aa7c-8011-b100-bea6388d1c95>
Case statement: Has no priority and makes the selection based on a particular case line or a selection
The Synthesis ignores the display statement so its only used in simulation
Also in this case all of them have equal priority
module top_module (
input clk,
input [7:0] d,
input [1:0] sel,
output reg [7:0] q // <- make q a reg
);
wire [7:0] w1, w2, w3;
endmodule
In verilog if we don’t give/specify the size of the bits the operator will assume it’s the complete size
In Verilog, the concatenation operator {} combines multiple signals (wires, regs, constants, etc.) into a single vector, and the order matters very specifically in terms of bit positions.
Rule of Thumb:
Left to right = Most Significant Bit (MSB) to Least Significant Bit (LSB)
In other words:
• Leftmost element inside the {} becomes the upper bits.
• Rightmost element becomes the lower bits.
Example:
verilog
Key Clarification:
"The code for one module is not written inside another module's body"
≠
"You cannot instantiate a module inside another module."
They're saying:
✅ You can instantiate a module inside another module.
❌ You cannot write the full definition of one module inside another.
verilog
CopyEdit
module top_module(input a, input b, output out);
mod_a instance1(a, b, out); // This is an instantiation — 100% correct!
endmodule
verilog
CopyEdit
module top_module(input a, input b, output out);
module mod_a(input in1, input in2, output out); // ❌ You CANNOT define a module here
// Illegal nested definition
endmodule
endmodule
This is invalid because you're trying to define a module inside another module, which Verilog does not allow.
.module_port_name(signal_in_current_scope)
module_port_name (the one after the dot .):
This is the port name inside the module you are instantiating.
Note that in the dataflow statement we use the concatination operator for Y (see the truth table and figure it out)
So if you want to like use the same output for multiple case statements you can just add a comma in the end and combine all o f them into one output
In our case when the enable is one the outputs get executed (each of them are assigned to a output) but when enable is zero t hey are all assigned to a single output(0001)
Also since you are using case statements the hardware will behave like a multiplexer (this hardware is a bit bulky then our d ataflow statement tho)
So,the bit Y[1] will be active if either the bits I[1] or I[0]= is one
And the bit y[0] will be one if the other bits 2 and 3 are one
The expression V is the or (bitwise) of all the bits and will only be zero if all the inputs (I[0] TO I[3] are zero)
Yes, the valid bit is a logical OR, but since we're using 1-bit values, logical OR and bitwise OR give the same result.
• All I[i]s are 1-bit (either 0 or 1)
• valid = I[0] | I[1] | I[2] | I[3] — This is a bitwise OR of 1-bit values, and it works like a logical OR here
4'd2
This means:
verilog
Copy
Edit
4'd2: {V,Y} = 3'b101;
What it means:
If the input I = 4'b0010 → only I[1] is 1 (this is the second input, zero-indexed)
Then:
Valid bit V = 1
{V,Y} = 3'b101
Full Breakdown:
Decimal I[3:0] Active Input Y (binary index) V {V,Y}
4'd1 0001 I[0] 00 1 100
4'd2 0010 I[1] 01 1 101
4'd4 0100 I[2] 10 1 110
4'd8 1000 I[3] 11 1 111
Final Takeaway
This is not BCD. This is basic binary encoding of the index of the high bit in the input.
So {V,Y} = 3'b100 just means:
• V = 1 (valid input)
• Y = 2'b00 (input 0 is high → index 0 → binary = 00)
Let me know if you want me to draw or simulate this with a truth table or diagram!
From <https://chatgpt.com/c/685d562b-8540-8011-a738-5f6475179771>
Because under the hood, all numbers in Verilog are stored and manipulated in binary.
So even though you're writing 2'd1 (which is clearly a decimal 1), Verilog converts and stores that number in binary using the specified number of bits.
ch : u c
Be careful if your value is too large for the bit-width:
verilog
CopyEdit
2'd4 // ERROR or truncates to 2'b00 because 4 doesn't fit in 2 bits (max = 3)