导读:作者有幸在中国电子信息领域的排头兵院校“电子科技大学”攻读研究生期间,接触到前沿的数字IC验证知识,旁听到诸如华为海思、清华紫光、联发科技等业界顶尖集成电路相关企业面授课程,对数字IC验证有了一些知识积累和学习心得。为帮助想入门前端IC验证的朋友,思忱一二后,特开此专栏,以期花最短的时间,走最少的弯路,学最多的IC验证技术知识。
module fulladd(
input wire ain,
input wire bin,
input wire cin,
output wire sum,
output wire cout
);
assign sum = ain ^ bin ^ cim;
assign cout = (ain & bin) | (bin & cin) | (ain & cin);
endmodule
module mux_4_1(
input wire C,
input wire D,
input wire E,
input wire F,
input wire [1:0] S,
input reg Mux_out
);
always@(C or D or E or F or S)
begin
case(S)
2'b00 : Mux_out = C;
2'b01 : Mux_out = D;
2'b10 : Mux_out = E;
default : Mux_out = F;
endcase
end
endmodule
always@(enable or ain)
begin
if(!enable)
yout = 8'b0;
else
case(ain)
3'b000 : yout = 8'b0000_0001;
3'b001 : yout = 8'b0000_0010;
3'b010 : yout = 8'b0000_0100;
3'b011 : yout = 8'b0000_1000;
3'b100 : yout = 8'b0001_0000;
3'b101 : yout = 8'b0010_0000;
3'b110 : yout = 8'b0100_0000;
3'b111 : yout = 8'b1000_0000;
endcase
end
l和1是不一样的!always@(A or B)
begin
Q1 = A > B;
Q2 = A < B;
Q3 = A >= B;
end
// Q3 = A >= B; 等价于下面的代码
if(A >= B)
Q3 = 1
else
Q3 = 0;
module shift(
input wire [3:0] data,
output reg [3:0] q1,
output reg [3:0] q2,
);
parameter B = 2;
always@(data)
begin
q1 = data << B;//左移
q2 = data >> B;//右移
end
endmodule
module count_en(
input wire clock,
input wire reset,
input wire enable,
output reg [WIDTH-1 : 0] out
);
parameter WIDTH = 8;
parameter UDLY = 1;
always@(posedge clock or negedge reset)
begin
if(!reset)
out <= 8'b0;
else if(enable)
out <= #UDLY out + 1; //模仿器件延时,一般不提倡
end
endmodule
module dff_async_pre(
input wire data,
input wire clk,
input wire preset,
output reg q
);
parameter U_DLY = 1;
always@(posedge clk or negedge preset)//异步复位
begin
if(~preset)
q <= #U_DLY 1'b1;
else
q <= #U_DLY data;
end
endmodule
module dff_sync_rst(
input wire data,
input wire clk,
input wire reset,
output reg q
);
parameter U_DLY = 1;
always@(posedge clk)//同步复位
begin
if(!reset)
q <= #U_DLY 1'b0;
else
q <= #U_DLY data;
end
endmodule
module dff_sync(
input wire data,
input wire clk,
input wire reset,
input wire preset,
output reg q
);
parameter U_DLY = 1;
always@(posedge clk or negedge reset or negedge preset)//同步复位+异步复位
begin
if(~reset)
q <= 1'b0;
else if(~preset)
q <= 1'b1;
else
q <= #U_DLY data;
end
endmodule
注:输入的信号称为激励,输入激励的不同组合我们称之为不同的Pattern,也叫测试点(Test Pattern)。输出的信号称为响应。
`timescale 1ns/1ps
module fulladd_tb;
reg ain, bin, cin;
wire cout, sum;
reg clk;
always #1 clk = ~clk; //此处时钟没用,全加器只是个组合逻辑
//产生激励
initial
begin
clk = 0;
ain = 0;
bin = 1;
cin = 1;
#10
ain = 1;
bin = 1;
cin = 0;
#10
ain = 1;
bin = 1;
cin = 1;
#10
$finish;
end
//收集响应
initial
begin
#5;
if(sum!=0) $display("sum calc ERROR!!!, sum = %b", sum);
else $display("SUM calc correct!!!");
if(cout!=1)$display("cout clac ERROR!!!, cout = %b", cout);
else $display("cout calc correct!!!");
#10;
if(sum!=0) $display("sum calc ERROR!!!, sum = %b", sum);
else $display("SUM calc correct!!!");
if(cout!=1)$display("cout clac ERROR!!!, cout = %b", cout);
else $display("cout calc correct!!!");
#10
if(sum!=1) $display("sum calc ERROR!!!, sum = %b", sum);
else $display("SUM calc correct!!!");
if(cout!=1)$display("cout clac ERROR!!!, cout = %b", cout);
else $display("cout calc correct!!!");
end
//例化
fulladd u0_fulladd(
.cout (cout),
.sum (sum),
.ain (ain),
.bin (bin),
.cin (cin)
);
endmodule