不少Verilog初学者都搞不清楚reg和wire的用法区别。对此,berkeley的CS150中总结得很清楚,源文件地址见参考小节。
一、关于 wire
(可描述组合逻辑)
在Verilog中, wire
可以纯粹看作一根导线(或者任意位宽的总线)。在使用 wire
时需要注意以下几点语法规则:
wire
类型用于将模块例化时的输入输出端口连接到你设计的电路的其他地方。wire
类型在模块声明也作为输入输出。wire
类型必须被其他东西驱动而不能用于存储数据。wire
类型在 always@ 块中不能作为 = 或 <= 的左值。(即always块中必须用reg赋值,下面例1)🔑wire
类型是assign
语句中左值的唯一合法类型。🔑wire
类型可以将两个基于Verilog的设计相结合,是一种无状态的方法(并不是很明白这里指的是什么意思)。wire
类型只能用于组合逻辑建模。
下面这段程序给出了几种 wire
类型合法使用的例子
wire A, B, C, D, E; // simple 1-bit wide wires
wire [8:0] Wide; // a 9-bit wide wire
reg I;
assign A = B & C; // using a wire with an assign statement
always @(B or C) begin
I = B | C; // using wires on the right-hand side of an always@
// assignment
end
mymodule mymodule_instance(
.In (D ),
.Out (E )
); // using a wire as the output of a module
二、关于 reg
(既可描述组合逻辑也可描述时序逻辑)
reg
和wire有点类似,但能够存储信息(状态),类似寄存器。在使用 reg
时有以下这些语法规则:
reg
类型可以用于连接模块例化时的输入。reg
类型不能用于连接模块例化时的输出。reg
类型可以在模块声明时作为输出。reg
类型不能在模块声明时作为输入。reg
类型是 always@ 块中作为 = 或 <= 左值的唯一合法类型。🔑reg
类型是 initial 块中作为 = 左值的唯一合法类型(用于Test Bench)。reg
类型不能作为assign
语句的左值。reg
类型能用于创建寄存器,以用于 always@(posedge Clock) 块。reg
类型既可以描述组合逻辑也可以描述时序逻辑。🔑
下面这段程序给出了几种 reg
类型合法使用的例子
wire A,B;
reg I,J,K; // simple 1-bit wide reg elements .
reg [8:0] Wide ; // a 9-bit wide reg element
always @(A or B) begin
I = A | B; // using a reg as the left-hand side of an always@
// assignment
end
initial begin //using a reg in an initial block .
J=1'b1;
#1
J =1'b0;
end
always @(posedge Clock) begin
K<=I; // using a reg to create a positive -edge - triggered register
end
三、wire
和 reg
的共性
在下面这几种情况下 wire
和 reg
可以通用:
- 都可以作为
assign
语句的右值以及 always@ 块中作为 = 或 <= 的右值。 - 都可以接到模块例化的输入端口。
以上就是Verilog中wire和reg的主要区别了,有不少观点认为Verilog中会出现这样的区别是由于历史遗留原因,无从解释。对于我们使用者而言,只能强行记住它们之间的区别了,多写写自然就记住了。
例1
错误写法(对应上面一第四点,二第五点):会有报错 Illegal reference to net "sout".
module mux4to1(
input [1:0] sel ,
input [1:0] p0 ,
input [1:0] p1 ,
input [1:0] p2 ,
input [1:0] p3 ,
output [1:0] sout
);
always @(*)
case(sel)
2'b00: sout = p0 ;
2'b01: sout = p1 ;
2'b10: sout = p2 ;
default: sout = p3 ;
endcase
endmodule
修改后正确写法:
module mux4to1(
input [1:0] sel ,
input [1:0] p0 ,
input [1:0] p1 ,
input [1:0] p2 ,
input [1:0] p3 ,
output [1:0] sout);
reg [1:0] sout_t ;
always @(*)
case(sel)
2'b00: begin
sout_t = p0 ;
end
2'b01: sout_t = p1 ;
2'b10: sout_t = p2 ;
default: sout_t = p3 ;
endcase
assign sout = sout_t ;
endmodule