EDA常用数字器件硬件描述
前言
在使用了一段时间EDA编程之后,来回顾一下基本的知识,看看如何实现基本的EDA常用数字器件对应的硬件描述
一、组合逻辑器件描述
1. 基本的逻辑门电路
与、或、非(取反)、与非、或非、异或、同或
1.1 与and
module yand(a,b,y);
input a;
input b;
output y;
assign y=a&b;
endmodule
1.1.1测试文件.tv
`timescale 1 ps/ 1 ps
module yand_tb();
reg a;
reg b;
wire y;
yand i1 (
// port map - connection between master ports and signals/registers
.a(a),
.b(b),
.y(y)
);
initial
begin
a=0;
b=1;
end
always #100 a=!a;
always #250 b=!b;
endmodule
1.1.2 仿真结果
1.1.3 试验箱下载验证
引脚不小心分配错误
快速删除分配的引脚
可以参考一下资料
https://doc.embedfire.com/fpga/altera/ep4ce10_mini/zh/latest/fpga/IO_Lock.html
更正引脚分配,重新导入
配置下载
1.2或or
module yor(a,b,y);
input a,b;
output y;
assign y= a|b;
endodule
1.3 非(取反) ~
module ynot(a,y);
input a;
output y;
assign y= ~a;
endodule
1.4 与非
module ynand(a,b,y);
input a;
input b;
output y;
assign y= ~(a&b);
endodule
1.5或非 |
module ynor(a,b,y);
input a;
input b;
output y;
assign y= ~(a|b);
endodule
1.6异或 ^
module yxor(a,b,y);
input a;
input b;
output y;
assign y= a^b;
endodule
1.7同或
module yxnor(a,b,y);
input a;
input b;
output y;
assign y= ~(a^b);
endodule
2. 编码器
74HC148 8-3优先编码器,将8个高低电平变成3位2进制码。
2.1. 条件语句实现
由于输出是否编码过于复杂,简略写只8-3编码
module HC148(en,incode,outcode);
input en;
input[7:0] incode;
output reg[2:0] outcode;
always @(en,incode)
if(!en)
if(!incode[7]) outcode=3'b000;
else if(!incode[6]) outcode=3'b001;
else if(!incode[5]) outcode=3'b010;
else if(!incode[4]) outcode=3'b011;
else if(!incode[3]) outcode=3'b100;
else if(!incode[2]) outcode=3'b101;
else if(!incode[1]) outcode=3'b110;
else if(!incode[0]) outcode=3'b111;
else outcode=3'b111;
else
outcode=3'b111;
endmodule
2.2 分支语句实现
module HC148(en,incode,outcode);
input en;
input[7:0] incode;
output reg[2:0] outcode;
always@(en,incode)
if(!en)
casex(incode)
8'b0???????:outcode=3'b000;
8'b10??????:outcode=3'b001;
8'b110?????:outcode=3'b010;
8'b1110????:outcode=3'b011;
8'b11110???:outcode=3'b100;
8'b111110??:outcode=3'b101;
8'b1111110?:outcode=3'b110;
8'b11111111:outcode=3'b111;
default:outcode=3b'111;
endcase
else
outcode=3b'111;
endmodule
2.3 生成元件
右键.v文件
调用元件
RTL电路 1.2.3步查看
3. 译码器
74HC138 3-8译码器电路,3个二进制,翻译成8个高低电平电路
3.1条件语句实现
在这里插入代码片
3.2 分支语句实现
module HC138a(en1,en2,en3,A_in,Y_out)
input en1,en2,en3;
input[2:0]A_in;
output[7:0]Y_out;
wire en;
assign en= en1 && !en1 &&en3;
always@ (en,A_in)
if(en)
case(A_in)
3'b000: Y_out = 8'b11111110;
3'b001: Y_out = 8'b11111101;
3'b010: Y_out = 8'b11111011;
3'b011: Y_out = 8'b11110111;
3'b100: Y_out = 8'b11101111;
3'b101: Y_out = 8'b11011111;
3'b110: Y_out = 8'b10111111;
3'b111: Y_out = 8'b01111111;
default:Y_out = 8'b01111111;
endcase
else
Y_out = 8'b01111111;
endmodule
RTL图
CD4511 BCD—锁存/7 段译码/驱动器
module CD4511(le,bi,lt,in_bcd,out_a_g);
input le;
input bi;
input lt;
input[3:0] in_bcd;
output[6:0] out_a_g;
always@ (le,bi,lt,in_bcd)
if(!lt)
out_a_g=7'b1111111;
else if(!bi)
out_a_g=7'b0000000;
else if(!le)
case (in_bcd)
4’b0000: out_a_g <=7'b0111111;
4'b0001: out_a_g <=7'b0000110;
4'b0010: out_a_g <=7'b1011011;
4'b0011: out_a_g <=7'b1001111;
4'b0100: out_a_g <=7'b1100110;
4'b0101: out_a_g <=7'b1101101;
4'b0110: out_a_g <=7'b1111100;
4'b0111: out_a_g <=7'b0000111;
4'b1000: out_a_g <=7'b1111111;
4'b1001: out_a_g <=7'b1100111;
default :out_a_g <=7'b0000000;
endcase
endmodule
4.数据选择器
74HC151 ,8选1数据选择器,具有两个互不的输出端
4.1 条件语句实现
4.2分支语句实现 HC151
module HC151(st,A_in,D_in,Y,W);
input st;
input[2:0] A_in;
input[7:0] D_in;
output reg Y;
output wire W;
assign W=~Y;
always@(st,A_in,D_in)
if(!st)
case(A_in)
3'b000: Y=D_in[0];
3'b001: Y=D_in[1];
3'b010: Y=D_in[2];
3'b011: Y=D_in[3];
3'b100: Y=D_in[4];
3'b101: Y=D_in[5];
3'b110: Y=D_in[6];
3'b111: Y=D_in[7];
default: Y=D_in[0];
endcase
else
Y=1'b0;
endmodule
HC151_tb.tv文件
//
`timescale 1 ps/ 1 ps
module HC151_tb();
// constants
// general purpose registers
// test vector input registers
reg [2:0] A_in;
reg [7:0] D_in;
reg st;
// wires
wire W;
wire Y;
// assign statements (if any)
HC151 i1 (
// port map - connection between master ports and signals/registers
.A_in(A_in),
.D_in(D_in),
.W(W),
.Y(Y),
.st(st)
);
initial
begin
#10 D_in=0;
#10 A_in=0;
#10 st=1;
#10 st=0;
end
always #100 A_in=A_in+1;
always #100 D_in=D_in+1;
begin
end
endmodule
4.3 原理图
4.3 RTL图
4.4 仿真图
仿真出现红波形
更正:
二、时序逻辑电路
1.触发器
D触发器
同步触发器
module dff_a(clk,rst,d,q);
input clk,rst,d;
output reg q;
always @(posedge clk)
if(!rst)
q<=1'b0;
else
q<d;
endmodule
异步触发器
module dff_a(clk,rst,d,q);
input clk,rst,d;
output reg q;
always @(posedge clk negedge rst)
if(!rst)
q<=1'b0;
else
q<d;
endmodule
2.寄存器
74HC573,oe使能输出,le使能数据更新。
异步锁存
module HC573(oe,le,Dn,Qn);
input oe,le;
input[7:0] Dn;
output[7:0] Qn;
reg qtmp;
//三态输出描述
assign Qn =(!oe)?qtmp :8'bz;
always @ (le,Dn)
if(le)
qtmp<= Dn;
endmodule
74HC574
同步锁存
带三态控制的8位上升沿触发D型触发器
module HC574(oe,clk,Dn,Qn);
input oe,clk;
input[7:0] Dn;
output[7:0] Qn;
reg qtmp;
//三态输出描述
assign Qn =(!oe)?qtmp :8'bz;
always @ (posedge clk)
qtmp<= Dn;
endmodule
3.计数器
74hc161
元件文件
module hc161(clk,rst,load,ep,et,Pn,Qn,Co);
input clk,rst,load,ep,et;
input[3:0] Pn;
output reg [3:0] Qn;
output Co;
assign Co = (Qn== 4'b1111) & et;
always @(posedge clk or negedge rst)
if(!rst)
Qn <=4'b0000;
else if(!load)
Qn<=Pn;
else if(ep & et)
Qn <= Qn + 1'b1;
endmodule
测试文件
`timescale 1 ps/ 1 ps
module hc161_tb();
// constants
// general purpose registers
// test vector input registers
reg [3:0] Pn;
reg clk;
reg ep;
reg et;
reg load;
reg rst;
// wires
wire Co;
wire [3:0] Qn;
// assign statements (if any)
hc161 i1 (
// port map - connection between master ports and signals/registers
.Co(Co),
.Pn(Pn),
.Qn(Qn),
.clk(clk),
.ep(ep),
.et(et),
.load(load),
.rst(rst)
);
initial
begin
Pn=5;
clk=0;
ep=0;
et=0;
load=0;
rst=0;
#10 rst=1;
#10 load=1;
#10 ep=1;
#10 et=1;
end
always #10 clk=~clk;
endmodule
4.分频器
4.1 什么是分频器
分频器是一种时序逻辑电路,用于降低信号的频率。
fout= =fclk/N
N,为分频系数
N分频器的方法,应用N进制计数器来实现。
4.2 通用N分频器的功能描述
4.2.1参考程序
module fp_N(clk,en,N,M,fp_out);
input clk,en;
input [11:0]N;// 周期
input [11:0]M;//占空比
output fp_out;
reg[11:0]cnt;
assign fp_out=(cnt< M)?1'b0:1'b1; //调整占空比
always @(posedge clk)
if(!en)
cnt<=12'b0;
else if(cnt<N-1)
cnt=cnt+1'b1;
else
cnt <=12'b0;
endmodule
4.2.2 原理图
4.2.3 RTL图
4.2.4测试文件
`timescale 1 ps/ 1 ps
module fp_N_tb();
// constants
reg [11:0] M;
reg [11:0] N;
reg clk;
reg en;
// wires
wire fp_out;
// assign statements (if any)
fp_N i1 (
// port map - connection between master ports and signals/registers
.M(M),
.N(N),
.clk(clk),
.en(en),
.fp_out(fp_out)
);
initial
begin
#10 en=0;
#10 clk=0;
#10 N=12'd100;
#10 M=12'd50;
#10 en=1;
end
always #10 clk=~clk;
// optional sensitivity list
// @(event1 or event2 or .... eventn)
begin
// code executes for every event on sensitivity list
// insert code here --> begin
end
endmodule
4.2.5仿真波形
5.偶数分频器
偶数分频器的分频系数N为偶数。
通用分频器中 M=N/2
5.1 参考程序
module f_even(clk,en,N,fp_out);
input clk,en;
input [11:0]N;
output reg fp_out;
reg[11:0]cnt;
always @(posedge clk)
if(!en)
begin //超过两句需要用 begin end 括号起来
cnt<=0; //非阻塞语句
fp_out<=0;
end
else
if(cnt<(N/2-1))
cnt <=cnt+1;
else
begin
cnt <=0;
fp_out <= ~fp_out;
end
endmodule
注意事项:
a<=b; //非阻塞语句
a=b;//阻塞语句
测试文件
`timescale 1 ps/ 1 ps
module f_even_tb();
// test vector input registers
reg [11:0] N;
reg clk;
reg en;
// wires
wire fp_out;
// assign statements (if any)
f_even i1 (
// port map - connection between master ports and signals/registers
.N(N),
.clk(clk),
.en(en),
.fp_out(fp_out)
);
initial
begin
#10 N=12'd100;
#10 clk=10;
#10 en=0;
#100 en=1;
end
always #10 clk=~clk;
begin
end
endmodule
5.2 原理图
5.3 RTL图
5.4 仿真图
6.奇数分频器
奇数分频 50%占空比,既方波输出
6.1 参考程序
module f_odd(clk,en,N,fp_out);
input clk,en;
input[11:0] N;
output fp_out;
reg[11:0] cnt1,cnt2;
wire fp1,fp2;
assign fp1 = (cnt1<=(N-1)/2)?0:1;
assign fp2 = (cnt2<=(N-1)/2)?0:1;
assign fp_out = fp1|fp2;
always@(posedge clk)
if(!en)
cnt1=0;
else if(cnt1 <N-1)
cnt1 <=cnt1+1;
else
cnt1<=0;
always@(negedge clk)
if(!en)
cnt2=0;
else if(cnt2 <N-1)
cnt2 <=cnt2+1;
else
cnt2<=0;
endmodule
6.2 原理图
6.3 仿真图
7. 分频器的应用
7.1 应用
设计输出频率为1kHz,占空比0-100%可调的PWM波形,要求占空比的分辨率为1%。
7.1 .1输出周期计算:
假设系统输入时钟为50MHz,需要1kHz的波形,需要计数器计数值:
50*1000000/1000=50 000;
7.2.1输出占空比计算 占空比:
50000 /100=500; 500为1% 占空比分辨率的最小数值
7.2 参考程序
module pwm_n(clk_in,clr,duty,pwm_out);
input clk_in;
input clr;
input[7:0]duty;
output reg pwm_out;
parameter N=2500,M=25;
reg[14:0]cnt;
always @(posedge clk_in or negedge clr)
if(!clr)
cnt <=0;
else if(cnt==N-1)
cnt=0;
else
cnt<=cnt+1;
always @(clk_in,duty,cnt)
if(!clr)
pwm_out<=1;
else if(cnt<duty*M)
pwm_out=1;
else
pwm_out=0;
endmodule
测试文件
`timescale 1 ps/ 1 ps
module pwm_n_tb();
// constants
// general purpose registers
reg eachvec;
// test vector input registers
reg clk_in;
reg clr;
reg [7:0] duty;
// wires
wire pwm_out;
// assign statements (if any)
pwm_n i1 (
// port map - connection between master ports and signals/registers
.clk_in(clk_in),
.clr(clr),
.duty(duty),
.pwm_out(pwm_out)
);
initial
begin
#10 clk_in=0;
#10 duty<=8'd10;
#100 clr=0;
#10 clr=1;
end
always #10 clk_in=~clk_in;
always #25000
begin
if(duty<8'd100)
duty<=duty+4'd10;
else
duty<=0;
end
begin
end
endmodule
7.3 原理图
7.4 仿真图
总结
从简单的组合逻辑电路到时序逻辑电路,由浅入深。没有试验硬件条件的要仿真实现。后面将逐步完善。