八位全加器

代码

1
2
3
4
5
6
7
module adder8(cout, sum, a, b, cin);
output cout;
output[7:0] sum;
input[7:0] a, b;
input cin;
assign {cout,sum}=a+b+cin;
endmodule

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
`timescale 1ns/10ps
module adder8_tb;
reg[7:0] aa, bb;
reg ccin;
wire[7:0] ssum;
wire ccout;
adder8 adder8(.cout(ccout), .sum(ssum), .a(aa), .b(bb), .cin(ccin));
initial begin
aa<=8'b1110_0101;bb<=8'b0100_1001;ccin<=0;
#10 aa<=8'b0010_0100;bb<=8'b1100_1101;ccin<=~ccin;
#10 aa<=8'b0110_1100;bb<=8'b1101_0001;ccin<=~ccin;
#10 aa<=8'b0011_0110;bb<=8'b0000_0101;ccin<=~ccin;
#10 $stop;
end
endmodule

仿八位计数器

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module counter8(out,cout,data,load,cin,clk);
output[7:0] out;
output cout;
input[7:0] data;
input load,cin,clk;
reg[7:0] out;
always @(posedge clk)
begin
if(load)
out<=data;
else
out<=out+1+cin;
end
assign cout= & out & cin;
endmodule

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
`timescale 1ns/10ps
module tb_counter8;

// 定义与counter8模块相同的接口
reg [7:0] data;
reg load;
reg cin;
reg clk;
wire [7:0] out;
wire cout;

// 实例化counter8模块
counter8 uut (
.out(out),
.cout(cout),
.data(data),
.load(load),
.cin(cin),
.clk(clk)
);

// 初始化信号
initial begin
// 初始化所有信号为0
data = 0;
load = 0;
cin = 0;
clk = 0;

// 等待10个时间单位以开始测试
#10;

// 测试1: 加载数据并验证
data = 8'hFF; // 加载0xFF到计数器
load = 1;
#10; // 等待一个时钟周期
load = 0; // 释放加载信号

// 验证计数器是否保持加载的值
#10;
if (out !== 8'hFF) $display("Error: Counter did not load value correctly.");

// 测试2: 计数器递增
// 等待几个时钟周期以观察计数器的递增
repeat(10) @(posedge clk);

// 验证计数器是否递增到0x100(注意:cout应该为1)
if (out !== 8'h00 || cout !== 1'b1) $display("Error: Counter increment did not work correctly.");
$finish;
end
initial begin
forever #5 clk = ~clk; // 每5个时间单位翻转一次时钟信号,产生10个时间单位的时钟周期
end
endmodule

仿2位比较器

代码

1
2
3
module compare2(output equal, input [1:0] a, input [1:0] b);   
assign equal = (a == b) ? 1 : 0;
endmodule

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
`timescale 1ns/10ps

module compare2_tb;

reg [1:0] a;
reg [1:0] b;
wire equal;

// 实例化待测试的模块
compare2 compare2 (
.equal(equal),
.a(a),
.b(b)
);

initial begin

// 测试1:a和b相等
a = 2'b00; b = 2'b00; #10; // 设置a和b的值,等待10个时间单位
a = 2'b01; b = 2'b01; #10;
a = 2'b10; b = 2'b10; #10;
a = 2'b11; b = 2'b11; #10;

// 测试2:a和b不相等
a = 2'b00; b = 2'b01; #10;
a = 2'b01; b = 2'b10; #10;
a = 2'b10; b = 2'b11; #10;
a = 2'b11; b = 2'b00; #10;

// 结束仿真(可选)
$stop;
end

endmodule

仿真三态驱动器

代码

1
2
3
4
5
module trist2(out,in,enable);
output out;
input in,enable;
bufif1 mybuf(out,in,enable);
endmodule

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
`timescale 1ns/10ps

module trist2_tb;

// Declare inputs and output for the trist2 module
reg in;
reg enable;
wire out;

// Instantiate the trist2 module
trist2 uut (
.out(out),
.in(in),
.enable(enable)
);

// Test sequence
initial begin

in = 0;
enable = 0;

// Wait for a short time to observe initial state
#10;

// Test case 1: enable high, in changes
enable = 1;
#10 in = 1; #10 in = 0; #10 in = 1;

// Test case 2: enable low, in changes (output should be high-Z)
#10 enable = 0;
#10 in = 0; #10 in = 1; // Output should remain high-Z

// Finish the simulation (optional, depending on the simulation tool)
$finish;
end

endmodule

用reg型变量生成触发器

代码

1
2
3
4
5
6
7
8
9
10
11
module rw2(clk,d,out1,out2);
input clk,d;
output out1,out2;
reg out1;
wire out2;
assign out2 = d & ~out1;
always @(posedge clk)
begin
out1<=d;
end
endmodule

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
`timescale 1ns/10ps

module rw2_tb;

// Declare inputs and outputs for the rw2 module
reg clk;
reg d;
wire out1;
wire out2;

// Instantiate the rw2 module
rw2 uut (
.clk(clk),
.d(d),
.out1(out1),
.out2(out2)
);

// Clock generation
initial begin
clk = 0;
forever #5 clk = ~clk; // 10 time units period (5 high, 5 low)
end

// Test sequence
initial begin
// Monitor the outputs
$monitor("Time = %0t, clk = %b, d = %b, out1 = %b, out2 = %b", $time, clk, d, out1, out2);

// Initialize inputs
d = 0;

// Wait for the clock to stabilize
#10;

// Test case 1: Change d at clock edges
d = 1; #10; // At t=10, d=1, out1 should be 0 (not yet captured by clock), out2 should be 0
d = 0; #10; // At t=20, d=0, out1 should be 1 (captured at t=10), out2 should be 0
d = 1; #10; // At t=30, d=1, out1 should be 0 (captured at t=20), out2 should be 1
d = 0; #10; // At t=40, d=0, out1 should be 1 (captured at t=30), out2 should be 0

// Additional test cases can be added here

// Finish the simulation after a sufficient number of clock cycles
#50 $finish; // End simulation at t=90 (10 clock cycles of 10 time units each)
end

endmodule

仿真除法和求模运算

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
module arithmetic(  
input clk,
input [3:0] a,
input [3:0] b,
output reg [3:0] c, // 商
output reg [3:0] d // 余数
);

// 临时整数变量用于存储中间结果
integer temp_a, temp_b, temp_c, temp_d;

always @(posedge clk) begin
// 检查除零情况
if (b == 0) begin
// 处理除零错误(这里只是简单地将输出设置为一个错误指示值)
c <= 4'bx; // 'x' 表示未知值,也可以使用其他错误指示值
d <= 4'bx;
end else begin
// 将位向量转换为整数(这里假设a和b都是无符号的)
temp_a = a;
temp_b = b;

// 执行整数除法和取余操作
temp_c = temp_a / temp_b;
temp_d = temp_a % temp_b;

// 将结果转换回位向量(这里假设结果不会超过4位)
// 注意:如果a或b的值很大,以至于结果可能超过4位,则需要添加额外的范围检查
c <= temp_c[3:0]; // 只取低4位作为输出(实际上,由于我们知道结果是有界的,所以这里不需要位切片)
d <= temp_d[3:0]; // 同上
end
end

endmodule

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
`timescale 1ns/10ps
module arithmetic_tb;

// 时钟信号
reg clk;
// 输入信号
reg [3:0] a;
reg [3:0] b;
// 输出信号(通过wire连接到arithmetic模块的输出)
wire [3:0] c;
wire [3:0] d;

// 实例化arithmetic模块
arithmetic uut (
.clk(clk),
.a(a),
.b(b),
.c(c),
.d(d)
);

// 时钟生成器
initial begin
clk = 0;
forever #5 clk = ~clk; // 每5个时间单位翻转一次时钟信号
end

// 测试序列
initial begin
// 初始化输入和输出
a = 0; b = 0;
// 等待时钟稳定
#10;

// 测试案例1:正常除法
a = 8; b = 2;
#10;
// 检查输出
if (c != 4) $display("Error: c should be 4, but is %b", c);
if (d != 0) $display("Error: d should be 0, but is %b", d);

// 测试案例2:余数不为零
a = 9; b = 4;
#10;
// 检查输出
if (c != 2) $display("Error: c should be 2, but is %b", c);
if (d != 1) $display("Error: d should be 1, but is %b", d);

// 测试案例3:除数为零(应该触发错误处理)
a = 8; b = 0;
#10;
// 检查输出(假设错误处理将输出设置为'x')
if (c != 4'bx) $display("Error: c should be 'x' (undefined), but is %b", c);
if (d != 4'bx) $display("Error: d should be 'x' (undefined), but is %b", d);

// 你可以添加更多的测试案例来覆盖所有可能的输入组合

// 结束测试
$finish;
end

endmodule

仿真8位二进制乘法器

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
module mult_repeat(outcome,a,b);
parameter size=8;
output[2*size:1] outcome;
input[size:1] a,b;
reg[2*size:1] outcome;
reg[2*size:1] temp_a;
reg[size:1] temp_b;
always@(a or b)
begin
outcome=0;
temp_a=a;
temp_b=b;
repeat(size)
begin
if(temp_b[1])
outcome = outcome+temp_a;
temp_a =temp_a<<1;
temp_b =temp_b>>1;
end
end
endmodule

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
`timescale 1ns/10ps

module mult_repeat_tb;
// 定义与 mult_repeat 模块相同的参数和端口
parameter size = 8;
reg [size:1] a, b;
wire [2*size:1] outcome;

// 实例化 mult_repeat 模块
mult_repeat uut (
.outcome(outcome),
.a(a),
.b(b)
);

// 初始化信号
initial begin
// 监视信号变化
$monitor("Time = %0t, a = %d, b = %d, outcome = %d", $time, a, b, outcome);

// 测试用例
a = 8'd3; // 3 in binary is 00000011
b = 8'd5; // 5 in binary is 00000101
#10; // 等待10个时间单位

a = 8'd10; // 10 in binary is 00001010
b = 8'd15; // 15 in binary is 00001111
#10; // 等待10个时间单位

a = 8'd2; // 2 in binary is 00000010
b = 8'd2; // 2 in binary is 00000010
#10; // 等待10个时间单位

// 结束仿真
$finish;
end
endmodule

仿真计数器对8位二进制数中值为1的位进行计数

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
module count(count,rega);
output[3:0] count;
input[7:0] rega;
reg[3:0] count;
always @(rega)
begin :block
integer i;
count =0;
for(i=0;i<=7;i=i+1)
if(rega[i]==1)
count=count+1;
end
endmodule

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
`timescale 1ns/10ps
module count_tb;
// 定义与 count 模块相同的端口
reg [7:0] rega;
wire [3:0] count;

// 实例化 count 模块
count uut (
.count(count),
.rega(rega)
);

// 初始化信号
initial begin
// 监视信号变化
$monitor("Time = %0t, rega = %b, count = %d", $time, rega, count);

// 测试用例
rega = 8'b00000001; // 1 in binary
#10; // 等待10个时间单位

rega = 8'b00000110; // 6 in binary (00000110)
#10; // 等待10个时间单位

rega = 8'b11111111; // 255 in binary (all bits set)
#10; // 等待10个时间单位

rega = 8'b01010101; // 85 in binary (01010101)
#10; // 等待10个时间单位

// 结束仿真
$finish;
end
endmodule

仿真4选1数据选择器

代码

1
2
3
4
5
6
7
8
9
10
11
12
module mymux(out,in1,in2,in3,in4,cntrl1,cntrl2);
output out;
input in1,in2,in3,in4,cntrl1,cntrl2;
wire notcrtl1,notcrtl2,w,x,y,z;
not(notcrtl1,cntrl1);
not(notcrtl2,cntrl2);
and(w,in1,notcrtl1,notcrtl2);
and(x,in2,notcrtl1,cntrl2);
and(y,in3,cntrl1,notcrtl2);
and(z,in4,cntrl1,cntrl2);
or(out,w,x,y,z);
endmodule

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
`timescale 1ns/10ps
module tb_mymux;

// 定义与 mymux 模块相同的接口(但只使用 wire 类型)
wire out_wire; // 实际的输出线
reg in1, in2, in3, in4, cntrl1, cntrl2;

// 实例化 mymux 模块
mymux uut (
.out(out_wire),
.in1(in1),
.in2(in2),
.in3(in3),
.in4(in4),
.cntrl1(cntrl1),
.cntrl2(cntrl2)
);

// 使用 $monitor 系统任务来持续观察输出
initial begin
// 初始化输入信号
in1 = 0; in2 = 0; in3 = 0; in4 = 0; cntrl1 = 0; cntrl2 = 0;

// 应用测试向量并观察输出
$monitor("Time = %0t, cntrl1 = %b, cntrl2 = %b, in1 = %b, in2 = %b, in3 = %b, in4 = %b, out = %b", $time, cntrl1, cntrl2, in1, in2, in3, in4, out_wire);

#10 in1 = 1; cntrl1 = 0; cntrl2 = 0; // 00 -> 选择 in1,期望 out = 1
#10 in1 = 0; in2 = 1; cntrl1 = 0; cntrl2 = 1; // 01 -> 选择 in2,期望 out = 1
#10 in2 = 0; in3 = 1; cntrl1 = 1; cntrl2 = 0; // 10 -> 选择 in3,期望 out = 1
#10 in3 = 0; in4 = 1; cntrl1 = 1; cntrl2 = 1; // 11 -> 选择 in4,期望 out = 1

#10 in4 = 0; cntrl1 = 0; cntrl2 = 0; // 复位测试,所有输入为0,期望 out = 0

#10 $finish; // 结束仿真
end

endmodule

仿真阶乘运算

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
module tryfunct(  
output reg [31:0] result,
input clk,
input reset,
input [3:0] n
);


function [31:0] factorial;
input [3:0] op;
integer i;
begin
factorial = 1; // 阶乘的初始值为 1
for (i = 1; i <= op; i = i + 1) begin
factorial = factorial * i;
end
end
endfunction

always @(posedge clk or posedge reset) begin
if (reset) begin
result <= 0; // 当复位信号为高时,将结果重置为 0
end else begin
result <= factorial(n); // 否则,计算阶乘并更新结果
end
end

endmodule

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
`timescale 1ns/10ps

module tryfunct_tb;

// 定义与 tryfunct 模块相同的接口
reg clk;
reg reset;
reg [3:0] n;
wire [31:0] result;

// 实例化 tryfunct 模块
tryfunct uut (
.result(result),
.clk(clk),
.reset(reset),
.n(n)
);

// 时钟生成器:每 10 个时间单位翻转一次 clk
initial begin
clk = 0;
forever #5 clk = ~clk; // 10 个时间单位周期(5 上升,5 下降)
end

// 测试序列
initial begin
// 初始化信号
reset = 1;
n = 0;

// 等待时钟稳定
#10;

// 释放复位信号
reset = 0;

// 测试不同的 n 值
// 注意:由于阶乘增长迅速,对于较大的 n 值,result 将溢出
n = 3; // 3! = 6
#20; // 等待足够的时间让结果稳定(至少一个时钟周期)
$display("n = %d, result = %d", n, result);

n = 4; // 4! = 24
#20;
$display("n = %d, result = %d", n, result);

n = 5; // 5! = 120
#20;
$display("n = %d, result = %d", n, result);

$finish;
end

endmodule

通过任务调用完成4个4位二进制输入数据的冒泡排序

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
module sort4(ra,rb,rc,rd,a,b,c,d);
output [3:0] ra,rb,rc,rd;
input [3:0] a,b,c,d;
reg[3:0] ra,rb,rc,rd;
reg[3:0] va,vb,vc,vd;

task sort2;
input[3:0] x,y;
reg[3:0] temp;
if(x>y)
begin
temp=x;
x=y;
y=temp;
end
endtask
always @(a or b or c or d)
begin
va=a;
vb=b;
vc=c;
vd=d;
sort2(va,vc);
sort2(vb,vd);
sort2(va,vb);
sort2(vc,vd);
sort2(vb,vc);
ra=va;
rb=vb;
rc=vc;
rd=vd;

end

endmodule

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
`timescale 1ns/10ps
module tb_sort4;
// 输入和输出信号
reg [3:0] a, b, c, d;
wire [3:0] ra, rb, rc, rd;

// 实例化sort4模块
sort4 uut (
.ra(ra),
.rb(rb),
.rc(rc),
.rd(rd),
.a(a),
.b(b),
.c(c),
.d(d)
);

// 初始化块
initial begin
// 打印标题
$display("Test for sort4 module");

// 提供测试向量
// 每个测试向量包括四个输入值及其预期排序输出
a = 4'b1010; b = 4'b0101; c = 4'b1100; d = 4'b0011;
#10; // 等待10个时间单位
$display("Input: a=%b, b=%b, c=%b, d=%b -> Output: ra=%b, rb=%b, rc=%b, rd=%b", a, b, c, d, ra, rb, rc, rd);

a = 4'b0001; b = 4'b0011; c = 4'b0111; d = 4'b1111;
#10;
$display("Input: a=%b, b=%b, c=%b, d=%b -> Output: ra=%b, rb=%b, rc=%b, rd=%b", a, b, c, d, ra, rb, rc, rd);

a = 4'b1001; b = 4'b0110; c = 4'b0011; d = 4'b1100;
#10;
$display("Input: a=%b, b=%b, c=%b, d=%b -> Output: ra=%b, rb=%b, rc=%b, rd=%b", a, b, c, d, ra, rb, rc, rd);

// 结束仿真
$stop;
end
endmodule

仿真模为60的BCD码加法计数器

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
module count60(  
output reg [7:0] qout, // 8位输出计数器
output cout, // 进位输出
input [7:0] data, // 8位输入数据
input load, cin, reset, // 控制输入:加载、进位、复位
input clk // 时钟输入
);

// 进位输出逻辑
assign cout = ((qout == 8'h59) & cin) ? 1'b1 : 1'b0;

// 计数器逻辑
always @(posedge clk) begin
if (reset) begin
qout <= 8'h00; // 复位时,计数器清零
end else if (load) begin
qout <= data; // 加载时,计数器设置为输入数据
end else begin
if (cin && qout[3:0] == 4'h9) begin
// 如果有进位且秒为9,则秒归零,分钟加1(如果分钟为5,则归零)
qout[3:0] <= 4'h00;
if (qout[7:4] == 4'h05) begin
qout[7:4] <= 4'h00;
end else begin
qout[7:4] <= qout[7:4] + 1;
end
end else if (cin) begin
// 如果有进位但秒不为9,则仅秒加1
qout[3:0] <= qout[3:0] + 1;
end else if (qout[3:0] == 4'h9) begin
// 如果没有进位但秒为9,则秒归零,分钟保持不变(这里可以优化,因为分钟已经在cin的逻辑中处理了)
qout[3:0] <= 4'h00;
// 注意:这里的分钟处理逻辑其实已经在cin的分支中处理了,所以这里不会执行到分钟加1的逻辑(除非去掉cin的分支处理)
// 但为了保持代码的完整性,这里暂时保留这个条件判断(尽管它是多余的)
end else begin
// 如果秒不为9,则秒加1
qout[3:0] <= qout[3:0] + 1;
end
// 注意:上面的逻辑可以简化,因为当cin为高时,秒的处理逻辑已经包含了秒为9和秒不为9的情况
// 所以,非cin的分支其实只需要处理秒不为9且没有进位到分钟的情况(即qout[3:0] < 4'h9)
// 但由于我们保留了原有的逻辑结构以展示修正过程,所以这里没有进行进一步的简化
end
end

endmodule

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
`timescale 1ns/10ps

module count60_tb;

// 定义与count60模块相同的接口
reg [7:0] data;
reg load, cin, reset, clk;
wire [7:0] qout;
wire cout;

// 实例化count60模块
count60 uut (
.qout(qout),
.cout(cout),
.data(data),
.load(load),
.cin(cin),
.reset(reset),
.clk(clk)
);

// 时钟生成器
initial begin
clk = 0;
forever #5 clk = ~clk; // 10个时间单位的时钟周期(假设1个时间单位是1ns,则频率为50MHz)
end

// 测试序列
initial begin
// 初始化信号
data = 0;
load = 0;
cin = 0;
reset = 1;

// 等待一段时间以确保复位信号被捕获
#10;

// 释放复位信号
reset = 0;

// 测试加载功能
#10;
data = 8'h3C; // 十六进制60(十进制)
load = 1;
#10;
load = 0;

// 等待一段时间以观察计数器递增
#50; // 5个时钟周期

// 测试进位功能(从59到00,并检查cout)
// 首先,我们需要将计数器设置为59
data = 8'h59;
load = 1;
#10;
load = 0;

// 触发一个进位信号(cin)
#10;
cin = 1;
#10;
cin = 0;

// 等待一段时间以观察计数器是否重置为00并检查cout
#20; // 2个时钟周期

// 停止仿真(可选,取决于您的仿真环境)
$finish;
end

// 监控输出(可选,用于调试)
initial begin
$monitor("At time %0t, qout = %0h, cout = %b", $time, qout, cout);
end

endmodule