Assignment 3
1. 1010 sequence detector
Testbench
Design
module tb ();
// 1010 detector
reg x, clk, rst_n;
module Seq_det(y,state,x,clk,rst_n);
wire y;
input x,clk,rst_n;
wire [3:0] state;
output reg y;
Seq_det sd(y,state,x,clk,rst_n);
output reg [3:0] state;
always #2 clk = ~clk;
bit [3:0] nextstate;
initial begin
parameter A=1, B=2, C=3, D=4, E=5;
clk = 1;
always @ (posedge clk or negedge rst_n) begin
rst_n = 0;
if (rst_n == 0)
x = 0;
state <= A;
#4 rst_n = 1;
else
$display ("Time = %t, Current State is %d, Output = %d",
state <= nextstate;
$time,state,y);
end
#3 x= 1;
always @ (state or x) begin
$display ("Time = %t, Current State is %d, Output = %d",
case (state)
$time,state,y);
A : begin
#4 x= 1;
nextstate <= x ? B : A;
$display ("Time = %t, Current State is %d, Output = %d",
end
$time,state,y);
B : begin
#4 x= 0;
nextstate <= x ? B : C;
$display ("Time = %t, Current State is %d, Output = %d",
end
$time,state,y);
C : begin
#4 x= 1;
nextstate <= x ? D : A;
$display ("Time = %t, Current State is %d, Output = %d",
end
$time,state,y);
D : begin
#4 x= 0;
nextstate <= x ? B : E;
$display ("Time = %t, Current State is %d, Output = %d",
end
$time,state,y);
E : begin
#4 x= 1;
nextstate <= x ? B : A;
$display ("Time = %t, Current State is %d, Output = %d",
end
$time,state,y);
default nextstate <= A;
#4 x= 0;
endcase
$display ("Time = %t, Current State is %d, Output = %d",
end
$time,state,y);
always @ (state) begin
#4 x= 1;
if (state == E)
$display ("Time = %t, Current State is %d, Output = %d",
y = 1;
$time,state,y);
else
#4 $finish;
y = 0;
end
end
endmodule
initial begin
$dumpfile ("dump.vcd");
$dumpvars;
end
endmodule
2. Vending Machine
Design:
// Vend Machine
module vend_machine(dispanse,state,x,y,clk,rst_n);
input x,y,clk,rst_n;
output reg dispanse;
output reg [2:0] state;
parameter S0 = 2'b00, S1 = 2'b01, S2 = 2'b10, S3 = 2'b11;
bit [2:0] nextstate;
always @ (posedge clk, negedge rst_n) begin
if (rst_n == 0)
state <= S0;
else
state <= nextstate;
end
always @ (state) begin
case (state)
S0: begin
nextstate = x ? S1 : S0;
nextstate = y ? S2 : S0;
end
S1: nextstate = x ? S2 : S0;
S2: nextstate = x ? S3 : S0;
S3: nextstate = S0 ;
default nextstate = S0 ;
endcase
end
always @(state)begin
case(state)
S0: dispanse = 0;
S1: dispanse = 1;
S2: dispanse = 2;
S3: dispanse = 3;
default dispanse = 0;
endcase
end
endmodule
3. Traffic Light
// Traffic Light
module Traffic_Light(light,state,clk);
input clk;
output reg [3:0] light;
output reg [1:0] state;
parameter A=1, B=2, C=3;
parameter RED=3'b000, GREEN=3'b001, YELLOW=3'b010;
//NEXT STATE LOGIC
always @ (posedge clk) begin
case (state)
A : state <= B;
B : state <= C;
C : state <= A;
default state <= A;
endcase
end
//OUTPUT LOGIC
always @ (state) begin
case (state)
A : light = 3'b000;
B : light = 3'b001;
C : light = 3'b010;
default light = 3'b000;
endcase
end
end module
ASSIGNMENT – 4
1. TASK and Function
Functions:
- Functions in Verilog are used to perform computations and return a single value.
- They can only have input arguments and a single return value.
- Functions cannot contain any delays or wait statements.
- Functions are executed sequentially, and the result is returned to the calling statement.
- They can be used within procedural blocks, expressions, or other functions.
E.g. function int factorial(input int n);
if (n <= 1)
factorial = 1;
else
factorial = n * factorial(n - 1);
endfunction
reg [3:0] num;
reg [7:0] result;
initial begin
num = 4;
result = factorial(num);
$display("Factorial of %d is %d", num, result);
End
Tasks:
- Tasks in Verilog are used to encapsulate a block of procedural code that can contain delays, wait statements,
and other control flow constructs.
- They can have input and output arguments, allowing them to modify variables directly.
- Tasks are executed in parallel with other statements in the parent scope.
- They are primarily used for behavioral modeling, testbench development, and organizing simulation code.
E.g task automatic counter(input int count);
reg [7:0] i;
for (i = 0; i < count; i = i + 1) begin
#10; // Delay of 10 time units
$display("Counter value: %d", i);
end
endtask
initial begin
counter(5);
end
2. Begin end vs fork join
begin-end Block:
- The `begin-end` block is used to group multiple statements together and create a sequential block of code.
- Statements within a `begin-end` block are executed sequentially, one after another, in the order they appear.
- Variables declared within a `begin-end` block are local to that block and cannot be accessed outside of it.
- A `begin-end` block is commonly used within procedural blocks, such as `always` or `initial` blocks, to define the
scope of the enclosed statements.
Example-
always @(posedge clk) begin
if (reset)
counter <= 0;
else begin
if (enable)
counter <= counter + 1;
end
end
fork-join Construct:
- The `fork-join` construct is used to create parallel execution blocks in Verilog.
- Statements within a `fork-join` block are executed concurrently or in parallel.
- The `fork` keyword starts the parallel execution, and the `join` keyword indicates the end of the parallel
execution.
- Statements within the `fork-join` block are executed independently and concurrently without waiting for each
other to complete.
- Variables declared within a `fork-join` block are shared among the parallel threads.
Example-
initial begin
fork
$display("Thread 1");
#10;
$display("Thread 2");
join
$display("After join");
end
3. RAM vs ROM
RAM (Random Access Memory):
- RAM is a type of memory that allows both read and write operations.
- It is used for temporary data storage, allowing data to be written and read in any order.
- RAM is volatile, which means it loses its stored data when power is removed.
- It provides random access, meaning that any memory location can be accessed directly.
- In Verilog, RAM can be implemented using either registers or memory arrays.
Example:
module RAM (
input wire clk,
input wire write_enable,
input wire [1:0] address,
input wire [7:0] data_in,
output wire [7:0] data_out
);
reg [7:0] mem [3:0];
always @(posedge clk) begin
if (write_enable)
mem[address] <= data_in;
end
assign data_out = mem[address];
endmodule
ROM (Read-Only Memory):
- ROM is a type of memory that stores data permanently and cannot be modified.
- It is used for storing program instructions and other constant data.
- ROM is non-volatile, meaning that it retains its stored data even when power is removed.
- Data in ROM can only be read and cannot be written or modified.
- In Verilog, ROM can be implemented using a combination of constants and lookup tables.
Example:
module ROM (
input wire [2:0] address,
output wire [7:0] data_out
);
reg [7:0] rom [7:0] = {
8'b00000000, // Address 0
8'b00000001, // Address 1
8'b00000010, // Address 2
8'b00000011, // Address 3
8'b00000100, // Address 4
8'b00000101, // Address 5
8'b00000110, // Address 6
8'b00000111 // Address 7
};
assign data_out = rom[address];
endmodule
Testbench:
module ROM_Testbench;
// Inputs
reg [2:0] address;
// Outputs
wire [7:0] data_out;
// Instantiate ROM module
ROM dut (
.address(address),
.data_out(data_out)
);
// Clock generation
reg clk;
always #5 clk = ~clk;
// Test vectors
initial begin
clk = 0;
// Test case 1: Read from address 0
address = 3'b000;
#10;
$display("Data at address 0: %b", data_out);
// Test case 2: Read from address 3
address = 3'b011;
#10;
$display("Data at address 3: %b", data_out);
// Test case 3: Read from address 7
address = 3'b111;
#10;
$display("Data at address 7: %b", data_out);
// End simulation
$finish;
end
endmodule