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