数字电路(第三部分: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块
当括号内的表达式的值改变时,就会执行一遍块内语句。(一般用于时序逻辑)
always @(...)
begin
// 过程赋值
// if语句
// case语句
end
posedge与negedge关键字:事件由时钟边沿触发,分别表示信号的上升沿和下降沿。如:
always @(posedge clk) // 表示时钟信号clk的上升沿
always @(negedge clk) // 表示时钟信号clk的下降沿
always块内是按照指定的顺序执行的;两个或更多个always块之间、always块与assign语句之间,是同时执行(并行执行)的。
设计举例
4位全加器
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译码器
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、同步预置二进制计数器
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、同步预置二进制计数器(注意这里异步清零的方法)
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、同步预置十进制计数器
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、同步预置十进制计数器
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,左移)
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数据选择器
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,同步预置)
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