EEE4341 - Introduction to FPGA
Design
Lecture 4:
Verilog HDL Modeling Techniques (Part 1)
Zahit Evren Kaya / 2024
Describing Modules in Verilog
• A module in Verilog is the basic building block that
encapsulates functionality, typically representing a Basic Module
hardware component such as a gate, ip- op, or more module and_gate (
complex systems like processors. input wire a,
input wire b,
• Modules can include input and output ports, internal logic, output wire c
and may instantiate other modules to build hierarchical
designs. );
assign c = a & b; // Structural description using
• Modules can describe both behavioral and structural continuous assignment
functionality. endmodule
• A Module has the following constructs:
Hierarchical Design Behavioral Description Example
• Ports: Inputs, outputs, and inouts are de ned within module top_module ( module simple_counter (
the module to interact with external circuits. input wire a, input wire clk,
input wire b, input wire rst,
• Internal Logic: De ned using continuous output wire out output reg [3:0] count
assignments (assign), procedural blocks (always),
); );
or instantiated sub-modules.
wire temp; always @(posedge clk or posedge rst) begin
• Hierarchical Design: Modules can instantiate other and_gate u1 (.a(a), .b(b), .c(temp)); if (rst)
modules, enabling scalable and reusable designs. inverter u2 (.in(temp), .out(out)); count <= 0;
endmodule else
• Begins with module keyword count <= count + 1;
end
• Ends with endmodule keyword endmodule
fi
fl
fi
fl
Basic Verilog Syntax Rules
Verilog Reserved Keywords:
• Verilog is a case-sensitive hardware always and assign automatic
description language that follows a begin
case
buf
casex
bu f0
casez
bu f1
cell*
// Single-line comment
/*
speci c syntax to describe cmos con g* deassign default Multi-line comment
defparam design* disable edge
hardware behavior and structure. else end endcase endcon g*
*/
module example (input wire a, output wire b);
endfunction endgenerate endmodule endprimitive assign b = ~a; // Invert signal
• Keywords: Lowercase reserved
endspecify endtable endtask event
endmodule
for force forever fork
words, such as module, assign, function
highz1
generate
if
genvar
ifnone
highz0
incdir*
always. include* initial inout input
module case_sensitivity_example;
instance* integer join larger
reg signal_A;
liblist* library* localparam macromodule
• Statements: Every statement ends medium
nmos
module
nor
nand
noshow-cancelled*
negedge
not
reg signal_a; // Di erent from signal_A due to case
sensitivity
with a semicolon (;). notif0 notif1 or output
parameter pmos posedge primitive initial begin
signal_A = 1'b1;
• Case Sensitivity: Identi ers are
pull0 pull1 pullup* pulldown*
pulsestyle_ondetect* pulsestyle_onevent* rcmos real signal_a = 1'b0;
case-sensitive (e.g., clk and CLK realtime
rnmos
reg
rpmos
release
rtran
repeat
rtranif0 $display("signal_A = %b", signal_A); // Displays 1
are di erent). rtranif1
small
scalared
specify
show-cancelled*
specpa
signed
strong0
$display("signal_a = %b", signal_a); // Displays 0
end
strong1 supply0 supply1 table endmodule
• Comments: Single-line comments task
tranif1
time
tri
tran
tri0
tranif0
tri1
(//) and multi-line comments (/* triand trior trireg use*
*/) are allowed. vectored
weak1
wait
while
wand
wire
weak0
wor
xnor xor
Source: https://docs.amd.com/r/en-US/ug901-vivado-synthesis/Verilog-Reserved-Keywords
fi
fi
fi
fi
fi
ff
ff
fi
Hierarchical Design
• Verilog allows complex designs to be Example: Simple Hierarchical Design:
created by organizing smaller modules into a module half_adder ( Example: Instantiating Modules Multiple Times:
hierarchy. input wire a,
module ripple_carry_adder_4bit (
input wire b,
• Hierarchical design is the process of output wire sum,
input wire [3:0] a,
instantiating sub-modules within larger output wire carry
input wire [3:0] b,
modules, creating a tree-like structure. );
input wire cin,
output wire [3:0] sum,
assign sum = a ^ b; // XOR for sum
• This method enhances modularity, assign carry = a & b; // AND for carry
output wire cout
scalability, and reusability of code. );
endmodule
wire c1, c2, c3;
• Hierarchical design usually involves module full_adder (
full_adder fa0 (.a(a[0]), .b(b[0]), .cin(cin), .sum(sum[0]), .carry(c1));
following: full_adder fa1 (.a(a[1]), .b(b[1]), .cin(c1), .sum(sum[1]), .carry(c2));
input wire a,
full_adder fa2 (.a(a[2]), .b(b[2]), .cin(c2), .sum(sum[2]), .carry(c3));
input wire b,
• Top Module: Represents the highest input wire cin,
full_adder fa3 (.a(a[3]), .b(b[3]), .cin(c3), .sum(sum[3]), .carry(cout));
level in the design. endmodule
output wire sum,
output wire carry
• Sub-modules: Instantiated inside the );
top module or other sub-modules.
wire sum1, carry1, carry2;
half_adder ha1
• Port Mapping: Communication (.a(a), .b(b), .sum(sum1), .carry(carry1));
between modules is achieved by half_adder ha2
connecting inputs and outputs at (.a(sum1), .b(cin), .sum(sum), .carry(carry2));
di erent levels. assign carry = carry1 | carry2; // OR for carry-out
endmodule
ff
Ordered Connections vs Named Connections
• In Verilog, when instantiating a module, Example: Ordered Connection
connections between module ports and module and_gate (
signals in the parent module can be input wire a,
made using ordered (positional) input wire b,
output wire y
connections or named connections. );
assign y = a & b;
• Ordered connections list signals in the endmodule
same order as the module's port
module top;
declaration, while named connections wire a, b, y;
explicitly associate signals with their and_gate u1 (a, b, y); // Ordered connection (a->a, b->b, y->y)
corresponding ports. endmodule
• Ordered Connections: Signals are
connected in the order they appear in the Example: Named Connection
module declaration. module top;
wire a, b, y;
and_gate u1 (.a(a), .b(b), .y(y)); // Named connection for clarity
• Named Connections: Signals are endmodule
connected by explicitly specifying the
port names for better readability.
Using Libraries
• Libraries allow designers to organize
and reuse code, especially in large
projects.
Example: Using a Library for Reusability
• A library can consist of modules, // File: utilities.v
`ifndef UTILITIES_V
functions, and packages stored in Example: Including an External Library
`de ne UTILITIES_V
separate les. The include directive // File: basic_gates.v function [3:0] add4;
allows importing these external les module and_gate(input wire a, input wire b, output wire input [3:0] a, b;
y); begin
for use in a design. assign y = a & b; add4 = a + b;
endmodule end
• Libraries enhance modularity, endfunction
allowing frequently used code to be // File: top_module.v `endif
`include "basic_gates.v"
reused without rewriting it. // File: top_module.v
module top_module(input wire a, input wire b, output `include "utilities.v"
• Libraries help manage large projects wire y);
and_gate u1 (.a(a), .b(b), .y(y)); module top_module(input wire [3:0] a, input wire [3:0] b,
by organizing them into smaller, endmodule output wire [3:0] result);
manageable units. assign result = add4(a, b); // Using the function from the
included library
endmodule
fi
fi
fi
Verilog Data Types
• Verilog provides various data types that represent
di erent hardware elements.
• These data types allow designers to model wire a, b, out;
circuits in a hardware description language. assign out = a & b; // Wire connects
continuously
• The primary categories are nets, variables and
parameters, each serving a di erent purpose in
describing hardware behavior and structure. reg q;
always @(posedge clk) begin
• Nets: Represent physical connection between q <= d; // 'reg' stores the value of 'd' on the rising edge of 'clk'
objects
end
• wire, tri, wand, wor, trior, trireg, tri1, tri0,
supply0, supply1
• Variables: Represent abstract storage elements
• integer, real, reg, time, realtime
• Parameters: Run-time constants
• parameter, localparam, specparam
• Not all data types are synthesizable!
ff
ff
Verilog Data Types
• Verilog provides various data types that represent
di erent hardware elements. Data Type Synthesizable Description
wire Yes Basic net type used to connect components. Represents physical connections.
• These data types allow designers to model reg Yes Used for variables that store values in sequential logic (e.g., ip- ops).
circuits in a hardware description language. logic Yes General-purpose data type used in SystemVerilog. Can replace both wire and reg.
bit Yes Unsigned single-bit data type in SystemVerilog (1-bit logic).
• The primary categories are nets, variables and byte Yes 8-bit unsigned value.
parameters, each serving a di erent purpose in int Yes 32-bit signed integer in SystemVerilog.
describing hardware behavior and structure. shortint Yes 16-bit signed integer in SystemVerilog.
longint Yes 64-bit signed integer in SystemVerilog.
• Nets: Represent physical connection between enum Yes Enumerated data types. Can be synthesized as registers with symbolic values.
objects array Yes Fixed-size arrays are synthesizable; dynamic arrays are not synthesizable.
Packed structs are synthesizable. Unpacked structs may not be synthesizable
• wire, tri, wand, wor, trior, trireg, tri1, tri0, struct Yes
depending on usage.
supply0, supply1 union Yes Packed unions are synthesizable.
real
No Floating point types like real are not synthesizable directly in hardware.
• Variables: Represent abstract storage elements ( oating
time No Used for simulation purposes, not synthesizable.
• integer, real, reg, time, realtime event No Used for synchronization in simulation, not synthesizable.
string No String data types are not synthesizable.
• Parameters: Run-time constants dynamic
No Dynamic arrays are not synthesizable, as their size can change at runtime.
array
• parameter, localparam, specparam class No Object-oriented constructs like classes are not synthesizable.
chandle No Handle to external data, used in simulation, not synthesizable.
• Not all data types are synthesizable! virtual
No Used in veri cation, not synthesizable.
interface
fl
ff
fi
ff
fl
fl
Net and Register Rules
Feature wire (Net Type) reg (Register Type)
Represents a
Stores a value ( ip- op,
Usage connection between
latch, or memory).
elements.
No, it re ects the value
Yes, holds the value until it
Value storage driven by the connected
is explicitly updated.
driver.
Assigned using
Assigned inside procedural
Assignment continuous
blocks (always, initial).
assignments (assign).
Use in sequential Yes, can be updated on
No
logic clock edges.
Use in Yes, commonly used for Yes, but requires speci c
combinational logic nets and gates. procedural blocks.
fl
fl
fl
fi
Type Connectivity Rules
Type Connectivity Allowed Connections Notes
Input ports represent connections to external signals and cannot store values,
Input Port (input) Can be of type wire, logic, bit
so they cannot be reg.
An output can be a net or register type, depending on whether it stores a value
Output Port (output) Can be wire, reg, logic, bit
or drives a connection.
Bidirectional ports must be of net types (wire or logic) since they represent a
Inout Port (inout) Must be wire, logic
physical connection.
Driven by continuous assignments wire and other net types can only be driven by continuous assignments, gates,
Assigning to wire
(assign) or module outputs.
Assigned inside procedural blocks reg is used to store values and can only be updated inside procedural blocks. It
Assigning to reg
(always, initial) cannot be assigned using assign.
Common for combinational logic; a wire can be connected to another wire
Connecting wire to wire Direct connection allowed
through continuous assignments or direct port connections.
reg can be assigned to wire using a
reg can be connected to a wire, but it requires procedural assignment or
Connecting reg to wire continuous assignment or module
connecting the reg to an output port that is of wiretype.
output
You cannot directly assign a wire to a reg; procedural logic (e.g., always @(*)) is
Connecting wire to reg Direct connection not allowed
required to assign wire values to a reg.
Yes, through continuous assignment
Driving wire from reg A wire can be driven by the value of a reg using continuous assignment.
(assign wire = reg_value)
Yes, using procedural assignment A reg can store a value driven by a wire, but it must happen within a procedural
Driving regfrom wire
inside always block block.
logic can replace both wire and regin In SystemVerilog, logic is a versatile type that can be used as either a net or a
Connecting logic
SystemVerilog register, simplifying connectivity rules.
inout ports represent physical bidirectional connections and must be assigned
Assigning inout Port Requires wire or logic
to a wire or logic type, not reg.
Example: Nets and Registers
Example: Using Nets (Wires)
wire a, b, result;
assign result = a & b; // Continuous assignment: a & b drive result
Example: Using Registers (Regs)
reg q;
always @(posedge clk) begin
q <= d; // Sequential assignment: q stores value of d on clock edge
end
Example: Nets and Registers Together
wire a, b, result;
reg q;
assign result = a & b; // Continuous assignment (net)
always @(posedge clk) begin
q <= result; // Sequential assignment (reg)
end
Using Vectors
• Vectors are used to group multiple bits into a Example: Declaring a Vector
single signal, such as buses or multi-bit data. wire [7:0] data_bus; // 8-bit wide bus Example: Vector Arithmetic
wire [7:0] a, b, sum;
• Vectors are essential when dealing with data assign sum = a + b; // 8-bit addition
larger than 1-bit, such as addresses or data
words in memory. Example: Vector Assignment
reg [3:0] counter;
• Vectors: Declared as [MSB:LSB], representing always @(posedge clk) begin
Example: Vector Assignment
multi-bit signals. reg [3:0] counter;
counter <= counter + 1; // Incrementing a 4-bit counter
always @(posedge clk) begin
• Multi-bit Arithmetic: Operations on vectors end
counter <= counter + 1; // Incrementing a 4-bit counter
behave similarly to binary arithmetic. end
Example: Invalid Bounds
• Bus Modeling: Vectors are frequently used to reg [7:0] data_bus; // Valid, constant bounds (0 to 7)
model buses in digital designs.
wire [15:0] address; // Valid, constant bounds (0 to 15)
• Important notes:
integer variable_size = 8;
• Bounds must be constant expressions reg [variable_size-1:0] dynamic_vector; // Invalid! Bounds must be
constant
• Bounds can be negative, zero or positive
• Range can be ascending or descending Example: Valid Bound Types
reg [0:3] pos_bounds_vector; // Valid, 4-bit vector with positive bounds (0 to 3)
• Individual bits can be selected from a vector reg [-1:-4] neg_bounds_vector; // Valid, 4-bit vector with negative bounds (-1 to -4)
reg [5:0] mixed_vector; // Valid, positive bounds (0 to 5)
Using Vectors
• Vectors are used to group multiple bits into Example: Range Can Be Ascending or Descending
a single signal, such as buses or multi-bit // Descending range (most common)
data. reg [7:0] descending_vector; // 8-bit vector, from bit 7 to bit 0
• Vectors are essential when dealing with data // Ascending range (less common)
larger than 1-bit, such as addresses or data
reg [0:7] ascending_vector; // 8-bit vector, from bit 0 to bit 7
words in memory.
• Vectors: Declared as [MSB:LSB],
representing multi-bit signals. Example: Accessing bits in a descending vector
reg [7:0] data_bus;
• Multi-bit Arithmetic: Operations on vectors assign bit_0 = data_bus[0]; // Access the least signi cant bit
behave similarly to binary arithmetic. assign bit_7 = data_bus[7]; // Access the most signi cant bit
• Bus Modeling: Vectors are frequently used
to model buses in digital designs. Example: Accessing bits in an ascending vector:
Example: Individual Bits Can Be Selected reg [0:7] ascending_bus;
• Important notes: reg [15:0] instruction_word; assign bit_0 = ascending_bus[0]; // Access the least
wire [3:0] opcode; signi cant bit (0)
• Bounds must be constant expressions wire [7:0] immediate_value; assign bit_7 = ascending_bus[7]; // Access the most
signi cant bit (7)
• Range can be ascending or descending // Selecting di erent parts of a vector
• Individual bits can be selected from a assign opcode = instruction_word[15:12];
15 to 12 as opcode
// Select bits
vector
assign immediate_value = instruction_word[7:0]; // Select
bits 7 to 0 as immediate value
fi
fi
ff
fi
fi
Using Vector Ranges
• Verilog allows selecting a range Example: Extracting a Range from a Vector
of bits from a vector using the wire [7:0] data_bus;
notation [MSB:LSB]. wire [3:0] lower_nibble;
• This is useful when you need to assign lower_nibble = data_bus[3:0]; // Extracting the
lower 4 bits
access a speci c part of a Example: Assigning to a Range
multi-bit signal, such as when reg [15:0] data_word;
working with sub elds of a bus. always @(posedge clk) begin
data_word[7:0] <= 8'b10101010; // Assigning value to
lower byte
• Vector Subset: You can access end
and manipulate a subset of bits
Example: Concatenating Vectors
within a vector. wire [7:0] high_byte, low_byte;
wire [15:0] combined_data;
• Flexibility: Allows working with assign combined_data = {high_byte, low_byte}; //
sections of a vector for smaller Concatenating two vectors
•
operations.
fi
fi
Assigning Between Di erent Widths
• When assigning signals of di erent
widths, careful handling is required to Example: Zero Padding to Match Width
avoid loss of data or incorrect wire [3:0] small_bus;
behavior. wire [7:0] large_bus;
assign large_bus = {4'b0000, small_bus}; // Zero-extend small_bus to 8 bits
• Smaller signals can be zero-padded or
sign-extended, while larger signals can
be truncated. Example: Truncation
wire [15:0] wide_bus;
• Zero Padding/Truncation: Extra bits wire [7:0] small_bus;
may be added or removed depending assign small_bus = wide_bus[7:0]; // Truncating wide_bus to lower 8 bits
on the signal sizes.
• Sign Extension: Signed numbers may Example: Sign Extension
need sign extension for correct wire signed [3:0] small_signed;
arithmetic operations. wire signed [7:0] extended_signed;
• Concatenation: Used for manually assign extended_signed = { {4{small_signed[3]}}, small_signed }; // Sign-extend 4-bit to 8-bit
adjusting widths by combining signals.
ff
ff
Literal Values
• Literal values represent constants in binary, Example: Binary Literal
decimal, octal, or hexadecimal format. reg [3:0] binary_value;
initial begin
• Literals can be speci ed with a speci c bit binary_value = 4'b1010; // 4-bit binary value
end
width, and their base can be indicated to
ensure the correct interpretation of values.
Example: Hexadecimal Literal
• Format: size'base_number (e.g., reg [7:0] hex_value;
4'b1010 means 4-bit binary value 1010). initial begin
hex_value = 8'h1A; // 8-bit hexadecimal value
end
• Supported Bases: Binary (b), Decimal (d),
Octal (o), and Hexadecimal (h). Example: Decimal Literal
reg [7:0] decimal_value;
• Bit Width: The speci ed width de nes how initial begin
many bits are used for the literal value. If decimal_value = 8'd42; // 8-bit decimal value
end
fewer bits are provided, padding occurs; if
more bits are given, truncation happens.
fi
fi
fi
fi
Automatic Extension of Unsigned Literals
• When using unsigned literals, if the
literal has fewer bits than the target
Example: Zero Extension Example
signal, the value is automatically zero- reg [7:0] extended_value;
extended to match the target width. initial begin
extended_value = 4'b1010; // 4-bit literal automatically zero-extended to 8 bits: 00001010
• This ensures that smaller unsigned end
numbers can be safely assigned to Example: Truncation of Wider Literal
larger-width signals without reg [3:0] small_value;
initial begin
unexpected behavior. small_value = 8'b10101010; // Only the lower 4 bits are used: 1010
end
• Zero Extension: Unsigned literals are Example: Hexadecimal Zero Extension
automatically padded with zeros when reg [15:0] extended_value;
initial begin
assigned to wider signals. extended_value = 8'h1A; // 8-bit hexadecimal literal is zero-extended to 16 bits: 0000000000011010
end
• Avoiding Over ow: Literal values that
exceed the target width are truncated.
fl
Declaring Nets
Net Default
• Nets behave like physical wires. Type
Description
Value
Use Case Synthesizable
Values are driven onto them. Basic net type, used for
connecting elements. Does
Z (high
Used for simple connections,
wire impedanc Yes
not store values; re ects the such as gate outputs or signals.
e)
• Verilog has several net types. value of drivers.
Tristate wire, similar to wire, Z (high
Used for bidirectional signals with
tri but allows for multiple impedanc Yes
• Most commonly used one is drivers.
Wired-AND net type, used
e)
Z (high
multiple drivers, like buses.
Used for wired-AND logic, when
wire. wand when multiple drivers can impedanc multiple drivers can drive the
Limited** (Tool
dependent)
produce a logical AND result. e) same net.
• Nets are used for simple wor
Wired-OR net type, used
when multiple drivers can
Z (high
impedanc
Used for wired-OR logic, when
multiple drivers can drive the
Limited** (Tool
connections between gates, produce a logical OR result. e) same net.
dependent)
module ports and components. tri0
Tristate wire that defaults to 0 (logic
logic 0 when undriven. low)
Used for bidirectional signals that
default to 0 when not driven.
Yes
Tristate wire that defaults to 1 (logic Used for bidirectional signals that
• Nets cannot store values. They tri1
logic 1 when undriven. high) default to 1 when not driven.
Represents a constant ground
Yes
only pass signals. supply0
Constant net tied to logic 0 0 (logic
connection, used in power No
(ground). low)
supplies or low signal reference.
Represents a constant power
Constant net tied to logic 1 1 (logic
supply1 connection, used in power No
(power). high)
supplies or high signal reference.
Tristate net that retains its Used in designs where signals
Last value
trireg last value when not driven need to retain their values when No
or Z
(similar to a latch). undriven, simulating latches.
fl
Declaring Nets
• Nets behave like physical wires.
Values are driven onto them. Example: Simple Wire Declaration
wire result;
• Verilog has several net types. assign result = a & b; // Wire used for continuous assignment
• Most commonly used one is Example: Declaring a Wire Vector
wire. wire [3:0] bus;
assign bus = {a, b, c, d}; // 4-bit wide wire vector
• Nets are used for simple
connections between gates,
module ports and components. Example: Using a Wire for Module Connections
module top;
• Nets cannot store values. They wire y;
and_gate u1 (.a(a), .b(b), .y(y)); // Wire used to connect module ports
only pass signals. endmodule
Resolving Multiple Drivers of a Net
• When multiple drivers attempt to control the Example: Wired-AND Resolution
same net, a con ict can arise. wand net_and;
assign net_and = a; // Driver 1
assign net_and = b; // Driver 2
• The resolution of multiple drivers depends
on the logic values assigned by each driver. // net_and will be 1 only if both a and b are 1
• The most common resolution mechanism is Example: Wired-OR Resolution
based on wired-logic (e.g., wired-AND or
wor net_or;
wired-OR) assign net_or = a; // Driver 1
assign net_or = b; // Driver 2
• Wired Logic: Verilog provides special net
// net_or will be 1 if either a or b is 1
types (wand, wor) to resolve con icts.
• Wired-AND: All drivers must drive a logic 1 Example: Multiple Drivers Without Resolution
wire net;
for the net to be high. assign net = a; // Driver 1
assign net = b; // Driver 2
• Wired-OR: The net is high if any driver
drives a logic 1. // This causes a multiple driver error without resolution
fl
fl
Combining Net Declaration and Assignment
• You can declare a net (wire)
and assign a value to it in
the same statement. Example: Combined Declaration and Assignment
wire result = a & b; // Wire declaration and assignment in one line
• This shorthand is useful
when de ning simple Example: Combined Declaration for Vectors
wire [7:0] data_bus = 8'hFF; // 8-bit wire with initial assignment
continuous assignments.
Example: Combining Declaration and Assignment for Multiple Nets
• This method is only valid for wire [3:0] sum = a + b, di = a - b; // Declaring and assigning multiple wires
continuous assignments,
not procedural blocks.
fi
ff
Declaring Variables
• Variables in Verilog (such as Example: Declaring a Reg Variable
reg) store values and are reg q;
typically used inside procedural always @(posedge clk) begin
q <= d; // Store value of d in q on clock edge
blocks (always, initial). end
• Unlike nets, which represent Example: Declaring a Variable Vector
reg [7:0] counter;
physical connections, variables always @(posedge clk) begin
hold values that can change counter <= counter + 1; // Increment an 8-bit counter
end
based on conditions or
sequential logic. Example: Initializing Variables in an Initial Block
reg [3:0] count;
initial begin
count = 4'b0000; // Initialize the counter to 0 at the beginning
end
Declaring Arrays of Nets and Variables
• Arrays of nets and variables in Verilog allow you
to declare multiple instances of nets or registers
in a single declaration.
Example: Declaring an Array of Wires
• These arrays are useful when dealing with wire [3:0] data[7:0]; // 8 four-bit wide wires
buses, memories, or large collections of signals
that share common functionality. Example: Declaring an Array of Registers
reg [7:0] memory[0:255]; // 256 eight-bit wide registers, representing a memory array
• Array of Nets: Useful for multi-bit connections
or parallel signal groups.
Example: Declaring an Array of Registers
• Array of Registers: Often used to model reg [7:0] memory[0:255];
memory or a set of sequential elements. always @(posedge clk) begin
•
memory[address] <= data_in; // Write data to a speci c address in the memory array
end
fi
Declaring Module Parameters
Next week…
Local Parameters
Next week…