0% found this document useful (0 votes)
1 views12 pages

Lab 7

The document contains Verilog code for various hardware modules including a 4-bit counter, a 32-bit counter, a 7-segment LED display driver, and a 32-bit ROM with testbenches for each module. It demonstrates the functionality of these modules through simulation, including clock generation, reset conditions, and counting behavior. Additionally, it includes alternative implementations and comprehensive testbenches for thorough verification of the designs.

Uploaded by

cracial11011
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1 views12 pages

Lab 7

The document contains Verilog code for various hardware modules including a 4-bit counter, a 32-bit counter, a 7-segment LED display driver, and a 32-bit ROM with testbenches for each module. It demonstrates the functionality of these modules through simulation, including clock generation, reset conditions, and counting behavior. Additionally, it includes alternative implementations and comprehensive testbenches for thorough verification of the designs.

Uploaded by

cracial11011
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 12

module counter(

input wire clk,


input wire en,
input wire rst,
output reg [3:0] count);

always @(posedge clk)begin


if(rst)begin
count <= 4'b0;
end
else begin
if(en)
count <= count+4'b1;
else
count <=count;
end
end
endmodule

`timescal 1ns/1ps
module counter_tb();
reg clk_tb;
reg rst_tb;
reg en_tb;
wire [3:0] count_tb;

counter DUT(
.clk(clk_tb),
.rst(rst_tb),
.en(en_tb),
.count(count_tb)
);
//initial signal
initial begin
clk_tb <=1'b0;
rst_tb <= 1'b1;
en_tb <=1'b0;
end
//clock gen
parameter CLOCK_PERIOD =10;
always begin
#((CLOCK_PERIOD)/2) clk_tb <= ~clk_tb;
end
initial begin
#10 rst_tb <= 1'b0;
#20 en_tb <= 1'b1;
#100 rst_tb <= 1'b1;
#10 rst_tb <= 1'b0;
#100 en_tb <= 1'b0;
#50 $stop;
end endmodule
///câu 1
module led_7_segment(
input wire [3:0] SW,
output reg [0:6] HEX0
);

always @(*) begin


case (SW)
4'h0: HEX0 = 7'b0000001; // 0
4'h1: HEX0 = 7'b1001111; // 1
4'h2: HEX0 = 7'b0010010; // 2
4'h3: HEX0 = 7'b0000110; // 3
4'h4: HEX0 = 7'b1001100; // 4
4'h5: HEX0 = 7'b0100100; // 5
4'h6: HEX0 = 7'b0100000; // 6
4'h7: HEX0 = 7'b0001111; // 7
4'h8: HEX0 = 7'b0000000; // 8
4'h9: HEX0 = 7'b0000100; // 9
4'hA: HEX0 = 7'b0001000; // A
4'hB: HEX0 = 7'b1100000; // b
4'hC: HEX0 = 7'b0110001; // C
4'hD: HEX0 = 7'b1000010; // d
4'hE: HEX0 = 7'b0110000; // E
4'hF: HEX0 = 7'b0111000; // F
default: HEX0 = 7'b1111111; // blank or invalid
endcase
end

endmodule

///testbench
`timescalse 1ns / 1ps
module led_7_segment_tb(
reg [3:0]SW_tb,
wire [0:6]HEX0_tb);

led_7_segment DUT(
.SW(SW_tb),
.HEX0(HEX0_tb));
//initial signal
integer i;
initial begin
for(i=0, i<16,i+=1)begin
SW_tb=i[3:0]
#10
end
$stop;
end
endmodule
//////câu 2
// ====================================================================
// 32-bit Counter Module
// ====================================================================
module counter_32bit (
input wire clk, // Clock signal
input wire reset, // Reset signal (active high)
input wire enable, // Enable signal (active high)
output reg [31:0] count // 32-bit counter output
);

// Synchronous reset counter


always @(posedge clk) begin
if (reset) begin
count <= 32'b0; // Reset counter to 0
end else if (enable) begin
count <= count + 1; // Increment when enabled
end
// When enable is low, count holds its current value
end

endmodule

// ====================================================================
// Testbench for 32-bit Counter
// ====================================================================
`timescale 1ns/1ps

module tb_counter_32bit;

// Test signals
reg clk;
reg reset;
reg enable;
wire [31:0] count;

// Instantiate the counter


counter_32bit uut (
.clk(clk),
.reset(reset),
.enable(enable),
.count(count)
);

// Clock generation - 10ns period (100MHz)


initial begin
clk = 0;
forever #5 clk = ~clk; // Toggle every 5ns -> 10ns period
end

// Test sequence
initial begin
// Initialize signals
reset = 0;
enable = 0;

// Display header

$display("====================================================================");
$display("32-bit Counter Testbench - ModelSim Simulation");
$display("Clock Period: 10ns");

$display("====================================================================");
$display("Time(ns) | Reset | Enable | Count");
$display("---------+-------+--------+----------");

// Monitor signal changes


$monitor("%8t | %5b | %6b | %8d", $time, reset, enable, count);

// Test Case 1: Initial Reset


$display("\n=== Test Case 1: Initial Reset ===");
reset = 1;
#20; // Hold reset for 2 clock cycles
reset = 0;
#10; // Wait 1 clock cycle

// Test Case 2: Enable counting


$display("\n=== Test Case 2: Enable Counting ===");
enable = 1;
#100; // Count for 10 clock cycles

// Test Case 3: Disable counting (clock still running)


$display("\n=== Test Case 3: Disable Counting ===");
enable = 0;
#50; // Wait 5 clock cycles with enable low

// Test Case 4: Re-enable counting


$display("\n=== Test Case 4: Re-enable Counting ===");
enable = 1;
#80; // Count for 8 more clock cycles

// Test Case 5: Reset while counting (enable active, clock running)


$display("\n=== Test Case 5: Reset While Counting (Enable Active) ===");
reset = 1;
#20; // Hold reset for 2 clock cycles
reset = 0;
#60; // Continue counting for 6 clock cycles

// Test Case 6: Reset while stopped (enable inactive, clock running)


$display("\n=== Test Case 6: Disable Then Reset ===");
enable = 0; // Stop counting
#30; // Wait 3 clock cycles
reset = 1; // Reset while stopped
#20; // Hold reset for 2 clock cycles
reset = 0;
#30; // Wait with enable still low

// Test Case 7: Final counting test


$display("\n=== Test Case 7: Final Counting Test ===");
enable = 1;
#100; // Count for 10 more clock cycles

// Test Case 8: Test counter overflow behavior (Optional)


$display("\n=== Test Case 8: Test Large Count Values ===");
// Force counter to near maximum value to test overflow
force uut.count = 32'hFFFFFFFD; // Set to -3 in 2's complement
#10;
release uut.count;
#50; // Let it count and overflow

// End simulation
$display("\n=== Simulation Complete ===");
$display("Total simulation time: %0t ns", $time);
#50;
$finish;
end

// Additional monitoring for specific events


always @(posedge clk) begin
if (reset) begin
$display(">>> RESET ACTIVE at time %0t - Count reset to 0", $time);
end else if (enable && !reset) begin
$display(">>> COUNTING at time %0t - Count = %0d", $time + 1, count + 1);
end else if (!enable && !reset) begin
$display(">>> HOLD at time %0t - Count held at %0d", $time, count);
end
end

// Check for counter overflow


always @(count) begin
if (count == 32'hFFFFFFFF) begin
$display(">>> WARNING: Counter at maximum value (4294967295)");
end else if (count == 32'h0 && $time > 0) begin
if (!reset) begin
$display(">>> INFO: Counter overflow occurred at time %0t", $time);
end
end
end

// Generate VCD file for waveform viewing


initial begin
$dumpfile("counter_32bit.vcd");
$dumpvars(0, tb_counter_32bit);
end

endmodule

// ====================================================================
// Alternative Asynchronous Reset Version (Optional)
// ====================================================================
module counter_32bit_async_reset (
input wire clk, // Clock signal
input wire reset, // Asynchronous reset signal (active high)
input wire enable, // Enable signal (active high)
output reg [31:0] count // 32-bit counter output
);

// Asynchronous reset counter


always @(posedge clk or posedge reset) begin
if (reset) begin
count <= 32'b0; // Asynchronous reset
end else if (enable) begin
count <= count + 1; // Increment when enabled
end
// When enable is low, count holds its current value
end

endmodule

// ====================================================================
// Comprehensive Testbench with Both Reset Types
// ====================================================================
module tb_comprehensive_counter;

// Test signals for synchronous version


reg clk;
reg reset_sync;
reg enable_sync;
wire [31:0] count_sync;

// Test signals for asynchronous version


reg reset_async;
reg enable_async;
wire [31:0] count_async;
// Instantiate both counters
counter_32bit sync_counter (
.clk(clk),
.reset(reset_sync),
.enable(enable_sync),
.count(count_sync)
);

counter_32bit_async_reset async_counter (
.clk(clk),
.reset(reset_async),
.enable(enable_async),
.count(count_async)
);

// Clock generation
initial begin
clk = 0;
forever #5 clk = ~clk;
end

// Comprehensive test
initial begin
// Initialize
reset_sync = 0; enable_sync = 0;
reset_async = 0; enable_async = 0;

$display("====================================================================");
$display("Comprehensive Counter Comparison - Sync vs Async Reset");

$display("====================================================================");

// Test synchronous reset


$display("\n=== Testing Synchronous Reset Counter ===");
reset_sync = 1; enable_sync = 1;
#15; // Reset in middle of clock cycle
reset_sync = 0;
#100; // Count for a while

// Test asynchronous reset


$display("\n=== Testing Asynchronous Reset Counter ===");
reset_async = 1; enable_async = 1;
#15; // Reset in middle of clock cycle
reset_async = 0;
#100; // Count for a while

$display("\n=== Simulation Complete ===");


$finish;
end

// Monitoring
always @(*) begin
$display("Time: %0t | Sync: %0d | Async: %0d", $time, count_sync, count_async);
end

endmodule
/////////câu 3
// ====================================================================
// 32-bit ROM Module (Read-Only Memory)
// ====================================================================
module rom_32bit (
input wire clk, // Clock signal
input wire chipselect, // Chip select (active high)
input wire [3:0] address, // 4-bit address (0x0 to 0xF)
output reg [31:0] data // 32-bit data output
);

// ROM content declaration using array


reg [31:0] rom_memory [0:15];

// Initialize ROM content


initial begin
rom_memory[4'h0] = 32'h00001111;
rom_memory[4'h1] = 32'h11112222;
rom_memory[4'h2] = 32'h22223333;
rom_memory[4'h3] = 32'h33334444;
rom_memory[4'h4] = 32'h44445555;
rom_memory[4'h5] = 32'h55556666;
rom_memory[4'h6] = 32'h66667777;
rom_memory[4'h7] = 32'h77778888;
rom_memory[4'h8] = 32'h88889999;
rom_memory[4'h9] = 32'h9999AAAA;
rom_memory[4'hA] = 32'h01234567;
rom_memory[4'hB] = 32'h89ABCDEF;
rom_memory[4'hC] = 32'h24200160; // MSSV: 24200160
rom_memory[4'hD] = 32'hDEADBEEF;
rom_memory[4'hE] = 32'hDEADC0DE;
rom_memory[4'hF] = 32'h00494344;
end

// ROM read operation


always @(posedge clk) begin
if (chipselect) begin
data <= rom_memory[address];
end else begin
data <= 32'h00000000; // Default value when not selected
end
end

endmodule

// ====================================================================
// Alternative ROM Implementation using Case Statement
// ====================================================================
module rom_32bit_case (
input wire clk,
input wire chipselect,
input wire [3:0] address,
output reg [31:0] data
);

// ROM read using case statement


always @(posedge clk) begin
if (chipselect) begin
case (address)
4'h0: data <= 32'h00001111;
4'h1: data <= 32'h11112222;
4'h2: data <= 32'h22223333;
4'h3: data <= 32'h33334444;
4'h4: data <= 32'h44445555;
4'h5: data <= 32'h55556666;
4'h6: data <= 32'h66667777;
4'h7: data <= 32'h77778888;
4'h8: data <= 32'h88889999;
4'h9: data <= 32'h9999AAAA;
4'hA: data <= 32'h01234567;
4'hB: data <= 32'h89ABCDEF;
4'hC: data <= 32'h24200160; // MSSV: 24200160
4'hD: data <= 32'hDEADBEEF;
4'hE: data <= 32'hDEADC0DE;
4'hF: data <= 32'h00494344;
default: data <= 32'h00000000;
endcase
end else begin
data <= 32'hFFFFFFFF; // Different default for chip not selected
end
end

endmodule

// ====================================================================
// Comprehensive Testbench for ROM
// ====================================================================
`timescale 1ns/1ps

module tb_rom_32bit;

// Test signals
reg clk;
reg chipselect;
reg [3:0] address;
wire [31:0] data_array;
wire [31:0] data_case;

// Expected data for verification


reg [31:0] expected_data [0:15];

// Test variables
integer i;
integer error_count;

// Instantiate both ROM implementations


rom_32bit rom_array (
.clk(clk),
.chipselect(chipselect),
.address(address),
.data(data_array)
);

rom_32bit_case rom_case (
.clk(clk),
.chipselect(chipselect),
.address(address),
.data(data_case)
);
// Clock generation - 10ns period
initial begin
clk = 0;
forever #5 clk = ~clk;
end

// Initialize expected data


initial begin
expected_data[4'h0] = 32'h00001111;
expected_data[4'h1] = 32'h11112222;
expected_data[4'h2] = 32'h22223333;
expected_data[4'h3] = 32'h33334444;
expected_data[4'h4] = 32'h44445555;
expected_data[4'h5] = 32'h55556666;
expected_data[4'h6] = 32'h66667777;
expected_data[4'h7] = 32'h77778888;
expected_data[4'h8] = 32'h88889999;
expected_data[4'h9] = 32'h9999AAAA;
expected_data[4'hA] = 32'h01234567;
expected_data[4'hB] = 32'h89ABCDEF;
expected_data[4'hC] = 32'h24200160; // MSSV: 24200160
expected_data[4'hD] = 32'hDEADBEEF;
expected_data[4'hE] = 32'hDEADC0DE;
expected_data[4'hF] = 32'h00494344;
end

// Main test sequence


initial begin
// Initialize signals
chipselect = 0;
address = 4'h0;
error_count = 0;

$display("====================================================================");
$display("32-bit ROM Testbench - ModelSim Simulation");
$display("Testing both Array and Case implementations");

$display("====================================================================");

// Wait for a few clock cycles


#20;

// Test Case 1: Chip not selected


$display("\n=== Test Case 1: Chip Select = 0 (ROM Disabled) ===");
chipselect = 0;
for (i = 0; i < 16; i = i + 1) begin
address = i;
#10; // Wait one clock cycle
$display("Addr: 0x%X | CS=0 | Array: 0x%08X | Case: 0x%08X",
address, data_array, data_case);
end

// Test Case 2: Normal ROM read operation


$display("\n=== Test Case 2: Normal ROM Read (Chip Select = 1) ===");
$display("Addr | Expected | Array Impl | Case Impl | Status");
$display("-----+------------+------------+------------+--------");

chipselect = 1;
#5; // Small delay

for (i = 0; i < 16; i = i + 1) begin


address = i;
#10; // Wait one clock cycle

// Check results
if (data_array == expected_data[i] && data_case == expected_data[i]) begin
$display("0x%X | 0x%08X | 0x%08X | 0x%08X | PASS",
address, expected_data[i], data_array, data_case);
end else begin
$display("0x%X | 0x%08X | 0x%08X | 0x%08X | FAIL",
address, expected_data[i], data_array, data_case);
error_count = error_count + 1;
end
end

// Test Case 3: Rapid address changes


$display("\n=== Test Case 3: Rapid Address Changes ===");
chipselect = 1;
for (i = 0; i < 5; i = i + 1) begin
address = $random % 16;
#10;
$display("Random Addr: 0x%X | Data: 0x%08X", address, data_array);
end

// Test Case 4: Chip select toggling


$display("\n=== Test Case 4: Chip Select Toggling ===");
address = 4'h5; // Fixed address

chipselect = 1;
#10;
$display("CS=1, Addr=0x5 | Data: 0x%08X", data_array);

chipselect = 0;
#10;
$display("CS=0, Addr=0x5 | Data: 0x%08X", data_array);

chipselect = 1;
#10;
$display("CS=1, Addr=0x5 | Data: 0x%08X", data_array);

// Test Case 5: Edge cases and timing


$display("\n=== Test Case 5: Timing and Edge Cases ===");

// Test address change at clock edge


chipselect = 1;
address = 4'hA;
#5; // Half clock cycle
address = 4'hB;
#5; // Complete the clock cycle
$display("Address changed mid-cycle | Final Data: 0x%08X", data_array);

// Test chip select change at clock edge


address = 4'hF;
chipselect = 1;
#5;
chipselect = 0;
#5;
$display("ChipSelect changed mid-cycle | Data: 0x%08X", data_array);

// Summary
$display("\
n====================================================================");
$display("Test Summary:");
$display("Total Errors: %0d", error_count);
if (error_count == 0) begin
$display("*** ALL TESTS PASSED ***");
end else begin
$display("*** %0d TESTS FAILED ***", error_count);
end

$display("====================================================================");

#50;
$finish;
end

// Monitor for debugging


always @(posedge clk) begin
if (chipselect) begin
$display(">> Clock edge: Addr=0x%X, Data_Array=0x%08X, Data_Case=0x%08X",
address, data_array, data_case);
end
end

// Generate VCD file for waveform analysis


initial begin
$dumpfile("rom_32bit.vcd");
$dumpvars(0, tb_rom_32bit);
end

// Additional verification task


task verify_data;
input [3:0] addr;
input [31:0] expected;
input [31:0] actual_array;
input [31:0] actual_case;
begin
if (actual_array !== expected || actual_case !== expected) begin
$display("ERROR at address 0x%X: Expected=0x%08X, Got Array=0x%08X, Case=0x
%08X",
addr, expected, actual_array, actual_case);
error_count = error_count + 1;
end
end
endtask

endmodule

// ====================================================================
// Simple ROM Usage Example
// ====================================================================
module rom_usage_example;

reg clk, cs;


reg [3:0] addr;
wire [31:0] data;
rom_32bit my_rom (
.clk(clk),
.chipselect(cs),
.address(addr),
.data(data)
);

initial begin
clk = 0;
forever #5 clk = ~clk;
end

initial begin
cs = 0; addr = 0;
#10;

cs = 1;
addr = 4'hA; // Read address 0xA
#10;
$display("Reading address 0xA: Data = 0x%08X", data);

addr = 4'hD; // Read address 0xD


#10;
$display("Reading address 0xD: Data = 0x%08X", data);

#20;
$finish;
end

endmodule

You might also like