一.组合电路设计
(1)数字加法器
a. 利用连续赋值语句实现
module add(a,b,sum,c_in,c_out);
output sum,c_out;
input a,b,c_in;
assign sum=(a^b)^c_in;
assign c_out=(a&b)|((a^b)&c_in);
endmodule
b.利用行为描述方式实现
module add(sum,a,b,c_in,c_out);
output c_out,sum;
input c_in,a,b;
assign {c_out,sum}=a+b+c_in;
endmodule
c.2输入8 bit加法器(行为描述方式)
module add(sum,a,b,c_in,c_out);
output c_out;
output [7:0]sum;
input [7:0]a,b;
input c_in;
assign {c_out,sum}=a+b+c_in;
endmodule
(2)数据比较器
例1:4位数据比较器
module comp(a,b,c,out);
input [3:0]a,b;
input c;
output [2:0]out;
reg [2:0]out;
always@ (a or b or c)
if(a>b)
out=3'b100;
else if(a<b)
out=3'b001;
else
out=c;
endmodule
(3).数据选择器
例1: 8选1数据选择器。
module select_8to1(sel,out,data_in);
input[7:0]data_in;
output out;
input[2:0]sel;
reg out;
always@(*)
case(sel)
3'b000:out=data_in[0];
3'b001:out=data_in[1];
3'b010:out=data_in[2];
3'b011:out=data_in[3];
3'b100:out=data_in[4];
3'b101:out=data_in[5];
3'b110:out=data_in[6];
3'b111:out=data_in[7];
default:out=1'bx;
endcase
endmodule
(4). 数字编码器
(有几个输入值,输入就为几位)
例1:二进制转化十进制8421BCD编码器,将十进制数0、1、2、3、4、5、6、7、8、9这10个信号编成二进制代码的电路叫做二进制转化十进制编码器。
module BCD8421(din,dout);
input [9:0]din;
output [3:0]dout;
reg [3:0] dout;
always@(din)
case(din)
10'b0000000001:dout=4'b0000;
10'b0000000010:dout=4'b0001;
10'b0000000100:dout=4'b0010;
10'b0000001000:dout=4'b0011;
10'b0000010000:dout=4'b0100;
10'b0000100000:dout=4'b0101;
10'b0001000000:dout=4'b0110;
10'b0010000000:dout=4'b0111;
10'b0100000000:dout=4'b1000;
10'b1000000000:dout=4'b1001;
default:dout=4'bx;
endcase
endmodule
(5).数字译码器
译码是编码的逆过程;
输出有几种可能,输出就为几位;
例1:2线—4线译码器
module _2to4(e,din,dout);
input e;//使能,低电平有效
input [1:0] din;
output [3:0]dout;
reg [3:0]dout;
always@(din or e)
case({din,e})
3'b??1:dout=4'b1111;
3'b000:dout=4'b1110;//0
3'b010:dout=4'b1101;//1
3'b100:dout=4'b1011;//2
3'b110:dout=4'b0111;//3
default:dout=4'bx;
endcase
endmodule
(6)奇偶校验器
module checker(fod,fev,a);
input[7:0]a;
output fod,fev; //fod为奇校验
assign fod=^a;
assign fev=~fod;
endmodule
二.时序电路设计
(1)触发器
例1:实现同步清0、置数和异步清0、置数共同在一个触发器上的复杂D触发器。
代码:
module dff(din,clk,clr,clr1,dout);
output dout;
input din,clk,clr,clr1;
reg dout;
//同步
always @(posedge clk)
begin
if(clr==0)
dout<=0;
else dout<=din;
end
always@(posedge clk or clr1)
//begin
if(!clr1)
dout<=0;
else dout<=din;
//end
endmodule
测试代码:
module dff_tb;
wire dout;
reg din,clk,clr,clr1;
dff uua(din,clk,clr,clr1,dout);
always #10 clk=~clk;
always #20 din=~din;
initial
begin
clk=1;
din=0;
clr=0;
clr1=0;
#20 clr=1;
#40 clr1=1;
end
endmodule
注意:
当clr,与clr1任何一个为零时,输出都为零
输出波形:
(2)计数器
例2:采用反馈清零法设计的十一进制计数器
module comp_11(clk,clr,dout);
output [3:0]dout;
input clk,clr;
reg [3:0]dout;
always @(posedge clk)
if(clr)
dout<=4'b0000;
else if(dout==4'b1010)
dout<=4'b0000;
else dout<=dout+1;
endmodule
(3)移位寄存器
例3:N位环型寄存器由N个移位寄存器组成,它可以实现环型移位。
module shift(clr,clk,dout);
parameter width=4,data=4'b0000;
output[width-1:0] dout;
input clr,clk;
reg [width-1:0] dout;
always@(posedge clk)
if(!clr)
dout<=data;
else
dout<={dout[width-2:0],dout[width-1]};
endmodule
三.有限同步状态机
(1)基础概念
a.摩尔型:输出仅与当前状态有关(看C2模块)
b.米利型:与当前状态和输入共同决定
c.三段式
d.两段式
(2)用Verilog HDL设计一个“111”序列检测器,当输入三个或三个以上的“1”时,电路输出为1,否则为0。
a.摩尔型
第一步:先画出状态转移图(摩尔:四种状态)
三段式代码:
module moore(din,clk,clr,dout);
input din,clr,clk;
output dout;
reg dout;
parameter s0=2'b00,s1=2'b01,s2=2'b11,s3=2'b10;
reg [1:0]present_state,next_state;
//状态寄存器
always@(posedge clk or posedge clr)
begin
if(clr==1)
present_state<=s0;//此处为当前状态输出
else
present_state<=next_state;
end
//C1模块,为组合逻辑用=
always@(*)
begin
case(present_state)
s0:if(din==0) next_state=s0;
else next_state=s1;
s1:if(din==0) next_state=s0;
else next_state=s2;
s2:if(din==0) next_state=s0;
else next_state=s3;
s3:if(din==0) next_state=s0;
else next_state=s3;
default:next_state=s0;
endcase
end
//C2模块
always@(*)
begin
if(present_state==s3)
dout=1;
else dout=0;
end
endmodule
测试代码:
module moore_tb;
reg din,clr,clk;
wire dout;
moore uua(din,clk,clr,dout);
always #10 clk=~clk;
initial
begin
clr=0;
clk=0;din=1;
#20 din=0;
#20 din=1;
#40 din=1;
#10 din=0;
#20 din=1;
#10 din=1;
#20 din=1;
end
endmodule
运行结果:
b.米利型
状态转移图:
二段式代码:
module mealy_(din,dout,clk,clr);
input clk,clr,din;
output dout;
reg [1:0]present_state,next_state;
reg dout;
parameter s0=2'b00,s1=2'b01,s2=2'b11;
//状态寄存器
always@(posedge clk or posedge clr)
begin
if(clr==1)
present_state<=s0;
else
present_state<=next_state;
end
always@(*)
begin
case(present_state)
s0:if(din==1) begin next_state=s1;dout=0;end
else begin next_state=s0;dout=0;end
s1:if(din==1)begin next_state=s2;dout=0;end
else begin next_state=s0;dout=0;end
s2:if(din==1)begin next_state=s2;dout=1;end
else begin next_state=s0;dout=0;end
default next_state=s0;
endcase
end
endmodule
测试代码:
module mealy__tb;
reg clk,clr,din;
wire dout;
mealy_ uut(din,dout,clk,clr);
always #10 clk=~clk;
initial
begin
clk=0;clr=0;din=0;
#10 din=1;
#20 din=1;
#40 din=0;
#20 din=1;
#10 din=0;
#60 din=1;
#10 din=0;
#20 din=1;
end
endmodule
运行结果:
四.存储器
(1)设计位宽为8bit,深度为8的ROM
其端口有四个为:输出,时钟,片选,地址线
rom代码:
module rom(out,clk,cs,addr);
input clk,cs;
input [2:0]addr;
output [7:0]out;
reg [7:0]rom [7:0]; //注意不要忘记
reg [7:0]out;
initial
begin
rom[0]=8'b0000_0000;
rom[1]=8'b0000_0001;
rom[2]=8'b0000_0010;
rom[3]=8'b0000_0011;
rom[4]=8'b0000_0100;
rom[5]=8'b0000_0101;
rom[6]=8'b0000_0110;
rom[7]=8'b0000_0111;
end
always@(posedge clk) //不要忘记写@
begin
if(cs)
out<=8'bzzzz_zzzz;
else
out<=rom[addr];
end
endmodule
测试代码:
module rom_tb;
reg clk,cs;
reg [2:0]addr;
wire [7:0]out; //注意输出为wire型,输入引脚为reg
rom uut(out,clk,cs,addr);
initial
begin
cs=1;
addr=0;
clk=0;
#20 cs=0;
end
always #10 clk=~clk;
//repeat只能写在过程语句内
initial
repeat(7)
#20 addr=addr+1;
endmodule
实验结果:
(2)设计位宽为8bit,深度为8的RAM
其端口有:输入端口,输出端口,片选端口,读写选择端口,时钟,地址线
代码:
module ram(din,dout,we,cs,clk,addr);
input clk,cs,we;
input[2:0]addr;
input [7:0]din;
output [7:0]dout;
reg[7:0]ram[7:0]; //前[7:0]代表8位,后[7:0]代表深度为8
reg [7:0]dout;
always@(posedge clk) //注意写always而不是initial
begin
if(cs) //低电平有效
dout<=8'bzzzz_zzzz;
else
if(we) //低电平有效
dout<=ram[addr];
else ram[addr]<=din;
end
endmodule
测试代码:
注意
- 前160单位时间写入数据,之后读出数据;
- 重复7次,是因为刚开始的时候,din=0;addr=0;
- 在重复第一次的时候,#20 addr=addr+1; din=din+1;则20单位的时候,addr为1,din为1;重复7次刚好到7;
module ram_tb;
reg clk,cs,we;
reg [2:0]addr;
reg [7:0]din;
wire [7:0]dout;
ram uut(din,dout,we,cs,clk,addr);
initial
begin
clk=0;
addr=0;
cs=0;
we=0;
din=0;
#160 we=1;
end
always #10 clk=~clk;
initial
begin
repeat(7)
begin
#20 addr=addr+1;
din=din+1;
end
#40 repeat(7)
#20 addr=addr-1;
end
endmodule
写入的仿真图:
输出的仿真图: