Verilog RTL 新手代码设计 (边沿捕获器、实例化电路模块并互联、多路选择器、交叉开关、优先编码器)

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视图:
在这里插入图片描述
波形仿真:
在这里插入图片描述

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值