数字电路(第三部分:Verilog设计)

语法

  • 模块定义:module 模块名(端口1,端口2,端口3,...);
  • 模块定义结束:endmodule
  • I/O说明:输入 input 端口名1,端口名2,...,端口名N; ,输出 output 端口名1,端口名2,...,端口名N;
  • register型变量(在always块中被赋值的信号)定义:reg 数据名1,数据名2,...,数据名n;。定义8位宽的数据:reg[7:0] data;
  • assign语句:assign 方程式;,一般适合于对组合逻
    进行赋值。
  • 数字:<位宽>'<进制> <数字> 位宽为对应二进制数的宽度;十进制的数可以缺省位宽和进制说明(二进制b,十六进制h);x代表不定值,z代表高阻值。
  • if-else语句、case-endcase语句,要在always块内;如执行的语句为多句时,要用begin-end语句括起来。
  • 位拼接运算符 { }:将两个或多个信号的某些位拼接起来,如{信号1的某几位,信号2的某几位,...,信号n的某几位}

always块

当括号内的表达式的值改变时,就会执行一遍块内语句。(一般用于时序逻辑

1
2
3
4
5
6
always @(...)
begin
// 过程赋值
// if语句
// case语句
end

posedge与negedge关键字:事件由时钟边沿触发,分别表示信号的上升沿和下降沿。如:

1
2
always @(posedge clk)  // 表示时钟信号clk的上升沿
always @(negedge clk) // 表示时钟信号clk的下降沿

always块内是按照指定的顺序执行的;两个或更多个always块之间、always块与assign语句之间,是同时执行(并行执行)的。

设计举例

4位全加器

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

3-8译码器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
module decoder_38(out,in,en);
output [7:0] out;
input [2:0] in;
input en;
reg [7:0] out;
always @(in or en)
begin
if (en) out=8'b11111111;
else
case(in)
3'b000: out=8'b11111110;
3'b001: out=8'b11111101;
3'b010: out=8'b11111011;
3'b011: out=8'b11110111;
3'b100: out=8'b11101111;
3'b101: out=8'b11011111;
3'b110: out=8'b10111111;
3'b111: out=8'b01111111;
endcase
end
endmodule

4位同步清0、同步预置二进制计数器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
module counter4(out, cout, data, load, clr, clk);
output[3:0] out;
output cout;
input[3:0] data;
input load, clr, clk;
reg[3:0] out;
always @(posedge clk)
begin
if (!clr) out=0; // 清零
else if (load) out=data; // 置数
else out=out+1;
end
assign cout=&out; // 进位(各位与运算)
endmodule

4位异步清0、同步预置二进制计数器(注意这里异步清零的方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module counter4(out, cout, data, load, clr, clk);
output[3:0] out;
output cout;
input[3:0] data;
input load, clr, clk;
reg[3:0] out;
always @(posedge clk)
begin
if (load) out=data; // 置数
else out=out+1;
end
always @(clr)
begin
if (!clr) out=0; // 清零
end
assign cout=&out; // 进位(各位与运算)
endmodule

4位同步清0、同步预置十进制计数器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module   counter10(out,cout,data,load,clr,clk);
output[3:0] out;
output cout;
input[3:0] data;
input load, clr, clk;
reg[3:0] out;
always @(posedge clk)
begin
if (!clr) out=0; // 清零
else if (load) out=data; // 置数
else if (out==9) out=0; // 十进制进位
else out=out+1;
end
assign cout = (out==9) ? 1 : 0; // 进位
endmodule

4位异步清0、同步预置十进制计数器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
module   counter10(out,cout,data,load,clr,clk);
output[3:0] out;
output cout;
input[3:0] data;
input load, clr, clk;
reg[3:0] out;
always @(posedge clk)
begin
if (load) out=data; // 置数
else if (out==9) out=0; // 十进制进位
else out=out+1;
end
always @(clr)
begin
if (!clr) out=0; // 清零
end
assign cout = (out==9) ? 1 : 0; // 进位
endmodule

8位移位寄存器(同步清0,左移)

1
2
3
4
5
6
7
8
9
10
11
12
13
module shifter8(dout, din, clk, clr);
output [7:0] dout;
input din, clk, clr;
reg [7:0] dout;
always @(posedge clk)
begin
if (clr) dout=0; // 清零
else begin
dout=dout<<1; // 输出信号左移一位
dout[0]=din; // 输入信号补到输出信号的最低位
end
end
endmodule

▲ 4选1数据选择器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
module mux4_1(out, in0, in1, in2, in3, sel);
output out;
input in0,in1,in2,in3;
input[1:0] sel; // 选择信号
reg out;
always @(in0 or in1 or in2 or in3 or sel)
case(sel)
2'b00: out=in0;
2'b01: out=in1;
2'b10: out=in2;
2'b11: out=in3;
default: out=2'bx;
endcase
endmodule

▲ 可变模k加法/减法计数器(同步清0,同步预置)

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 updown_count(data, clk, clr, load, up_down, out, cout);
input[7:0] data;
input clk, clr, load;
input up_down;
output[7:0] out;
output cout;
reg[7:0] out;
reg cout;
always @(posedge clk)
begin
if (!clr) out = 0; // 同步清0,低电平有效
else if (load) out = data; // 同步预置
else if (up_down) begin // 加法计数
if (out==k-1) begin // 进位
out = 0;
cout = 1;
end
else begin
out = out + 1;
cout = 0;
end
end
else begin // 减法计数
if (out==0) begin // 进位
out = k-1;
cout = 1;
end
else begin
out = out - 1;
cout = 0;
end
end
end
endmodule