1.边沿捕获器
举例来说,一个在CLK时钟驱动下,对输入信号IN进行上跳沿捕获的电路,它的Verilog代码如下所示,
module top(
CLK , // input clock
IN , // input
OUT ); // output
input CLK; input IN; output OUT;
reg d1R, d2R; // 电路中的D触发器输出端
reg OUT; // 组合逻辑输出信号,作为输出端口
// 生成移位寄存的D触发器,我们要明确,下面代码的写法会生成d1R和d2R两个D触发器。
// 并且d1R和d2R级联构成IN信号的移位寄存器。这是EDA工具不会篡改的事实。
always @ (posedge CLK) begin
d1R <= IN ;
d2R <= d1R ;
end
// 判断上跳沿的组合逻辑,我们要明确,下面的代码是一个以d1R、d2R信号作为输入,
// 以OUT信号作为输出的组合逻辑,并且代码中指出了OUT信号与d1R、d2R信号的逻辑
// 关系(好比是真值表),但是究竟用怎样的逻辑门实现(好比是卡诺图的画圈)
// 那是EDA工具要关心的事情。
always @ (d1R or d2R) begin
if((d2R == 0)&&(d1R == 1)) // 新值为1,旧值为0,跳变发生
OUT = 1'b1;
else
OUT = 1'b0;
end
endmodule
// endmodule top
另外`对于Quartus工具EDA工具进行编译之后,Tools -> Netlist Viewer -> RTL Viewer
就会提取出RTL结构如图所示,我们可以观察EDA工具解析出的RTL是否和我们预想的一致,这是一种重要的验证手段。
2.实例化电路模块并互联
Verilog代码的重要功能之一是实例化电路模块,并且对这些模块进行布线连接,每个被实例化的Verilog module 就如同某个型号的芯片, 每对该module的一次实例化,就如同使用了一次该芯片。同样,把各个实例化的module的信号连接起来,就如同在电路元件之间用导线进行互联一样。
以下代码演示了在顶层模块中,把一个加法器实例化了2次。
2个加法器实例对象的输入输出分别与顶层模块的输入输出相连
// 顶层模块
module top(
IN ,
OUT0 ,
OUT1 );
input [4-1:0] IN ;
output[4-1:0] OUT0;
output[4-1:0] OUT1;
wire [4-1:0] W_add0_out;
wire [4-1:0] W_add1_out;
// 第1次实例化, 加法器子模块
add U0_add(
.IN0 (IN ),
.IN1 (4'h1 ),
.OUT (W_add0_out));
// 第2次实例化, 加法器子模块
add U1_add(
.IN0 (IN ),
.IN1 (4'h2 ),
.OUT (W_add1_out));
// 端口接线互联
assign OUT0 = W_add0_out;
assign OUT1 = W_add1_out;
endmodule
// 加法器子模块
module add(
IN0 ,
IN1 ,
OUT );
input [4-1:0] IN0;
input [4-1:0] IN1;
output[4-1:0] OUT;
reg [4-1:0] OUT;
always @ (IN0 or IN1) begin
OUT = IN0 + IN1;
end
endmodule
在Quartus项目中编译代码,然后使用菜单,Quartus工具,Tools -> Netlist Viewer -> RTL Viewer 观察RTL视图,
可以看到如上图所示,两个实例化的加法器模块,每个加法器的输入输出端口和顶层模块的输入输出端口已经连接。
3.多路选择器
首先使用verilog编写2选1的mux代码,如下所示:
// module top, 选择器(mux)的代码,
module top(
IN0 , // input 1
IN1 , // input 2
SEL , // select
OUT ); // out data
parameter WL = 16; // 输入输出数据信号位宽
input [WL-1:0] IN0, IN1;// 选择器的两个输入数据信号
input SEL; // 通道选通的控制信号
output[WL-1:0] OUT; // 选择器的输入数据信号
reg [WL-1:0] OUT;
// 生成组合逻辑的代码
always @ (IN0 or IN1 or SEL) begin
if(SEL) // SEL为1 选择输入1
OUT = IN1;
else // SEL为0 选择输入0
OUT = IN0;
end
endmodule
// endmodule top
观察RTL视图如下
并且进行波形仿真
验证实验正确
然后进行4选1的mux实验,代码如下:
// module top, 选择器(MUX)的代码
module top(
IN0,
IN1,
IN2,
IN3,
SEL0,
SEL1,
OUT);
parameter WL=16;
input [WL-1:0] IN0,IN1,IN2,IN3;
input SEL0,SEL1;
output [WL-1:0] OUT;
reg [WL-1:0] OUT;
always @ (IN0 or IN1 or IN2 or IN3 or SEL0 or SEL1)
begin
if (SEL1==0)
begin
if (SEL0==0)
OUT = IN0;
else
OUT = IN1;
end
else
begin
if (SEL0==0)
OUT = IN2;
else
OUT = IN3;
end
end
endmodule
// endmodule top
RTL视图
波形仿真
验证实验正确
4.交叉开关
首先使用verilog编写2x2路交叉开关代码,如下所示:
// module top, a 2x2 crossbar switch circuit
module top(
IN0 , // input 1
IN1 , // input 2
SEL0 , // select the output0 source
SEL1 , // select the output1 source
OUT0 , // output data 0
OUT1 ); // output data 1
parameter WL = 16;
input [WL-1:0] IN0, IN1;
input SEL0, SEL1;
output[WL-1:0] OUT0, OUT1;
reg [WL-1:0] OUT0, OUT1;
// get the OUT0
always @ (IN0 or IN1 or SEL0) begin
if(SEL0)
OUT0 = IN1;
else
OUT0 = IN0;
end
// get the OUT1
always @ (IN0 or IN1 or SEL1) begin
if(SEL1)
OUT1 = IN1;
else
OUT1 = IN0;
end
endmodule
// endmodule top
RTL视图
2x2路交叉开关资源消耗
接下来编写一个4X4路交叉开关,代码如下:
module top (IN0,IN1,IN2,IN3,SEL0,SEL1,SEL2,SEL3,SEL4,SEL5,SEL6,SEL7,
OUT0,OUT1,OUT2,OUT3);
parameter WL = 16;
input [WL-1:0] IN0,IN1,IN2,IN3;
input SEL0,SEL1,SEL2,SEL3,SEL4,SEL5,SEL6,SEL7;
output [WL-1:0]OUT0,OUT1,OUT2,OUT3;
reg [WL-1:0]OUT0,OUT1,OUT2,OUT3;
// GEI THE OUT0
always @ (IN0 or IN1 or IN2 or IN3 or SEL0 or SEL1)
begin
if (!SEL0)
if(!SEL1)
OUT0 = IN0;
else
OUT0 = IN1;
else
if(!SEL1)
OUT0 = IN2;
else
OUT0 = IN3;
end
always @ (IN0 or IN1 or IN2 or IN3 or SEL2 or SEL3)
begin
if(!SEL2)
if(!SEL3)
OUT1 = IN0;
else
OUT1 = IN1;
else
if(!SEL3)
OUT1 = IN2;
else
OUT1 = IN3;
end
always @ (IN0 or IN1 or IN2 or IN3 or SEL4 or SEL5)
begin
if(!SEL4)
if(!SEL5)
OUT2 = IN0;
else
OUT2 = IN1;
else
if(!SEL5)
OUT2 = IN2;
else
OUT2 = IN3;
end
always @ (IN0 or IN1 or IN2 or IN3 or SEL6 or SEL7)
begin
if(!SEL6)
if(!SEL7)
OUT3 = IN0;
else
OUT3 = IN1;
else
if(!SEL7)
OUT3 = IN2;
else
OUT3 = IN3;
end
endmodule
RTL视图
4X4路交叉开关资源消耗:
对比2x2与4x4之间消耗资源,可以发现4x4交叉开关消耗的引脚数是2x2的2倍
5.优先编码器
首先编写verilog代码如下:
// module top, 4 input priority encoder with zero input check
module top(
IN , // input
OUT ); // output
input [3:0] IN;
output[2:0] OUT;
reg [2:0] OUT;
// get the OUT
always @ (IN) begin
if(IN[3]) // 第一优先
OUT = 3'b011;
else if(IN[2]) // 第二优先
OUT = 3'b010;
else if(IN[1]) // 第三优先
OUT = 3'b001;
else if(IN[0]) // 第四优先
OUT = 3'b000;
else // 什么都没有检测到
OUT = 3'b111; // 输出值可自定义,不和上面的输出值混淆即可
end
endmodule
RTL视图:
波形仿真:
编写一个8输入的优先编码器,代码如下:
module top(
IN,
OUT);
input [7:0] IN;
output [2:0] OUT;
reg [2:0] OUT;
always @(IN)
begin
if(IN[7])
OUT = 3'b111;
else if(IN[6])
OUT = 3'b110;
else if(IN[5])
OUT = 3'b101;
else if(IN[4])
OUT = 3'b100;
else if(IN[3])
OUT = 3'b011;
else if(IN[2])
OUT = 3'b010;
else if(IN[1])
OUT = 3'b001;
else
OUT = 3'b000;
end
endmodule
RTL视图:
波形仿真: