简单来说硬件描述语言有两种用途:1、仿真,2、综合。
从仿真的角度来说,HDL语言面对的是编译器(如Modelsim等),相当于软件思路。 这时: wire对应于连续赋值,如assign
从综合的角度来说,HDL语言面对的是综合器(如DC等),要从电路的角度来考虑。 这时:
为什么在verilog中要定义wire?
有几种情况变量需要定义成wire。
一、assign 语句 例如: reg a,b; wire and_result; ... assign and_result =a&&b; 你可以试试把wire定义成reg。综合器会报错。
二、元件例化时候的输出必须用wire 例如: wire dout; ram u_ram ( ... .out(dout) ... ); wire按照国外的教材上面的定义: wire为无逻辑连线。只做连线,wire本身是不带逻辑性的,所以输入什么输出就是什么。所以你尝试着用always语句对wire变量赋值。综合器就会报错。 那么你可能会问。assign c =a&&b不是就是对wire的赋值吗? 其实并非如此。综合器综合时将a&&b综合成ab经过一个与门。而c只是连接到与门输出的线。正真综合出与门的是&&。而不是c。
大体上来说,wire和reg都类似于C/C++的变量,但若此变量要放在begin…end内,该变量就需使用reg,在begin…end之外,则使用wire。
另外使用wire时,需搭配assign;reg则不必。
input,ouput,inout默认值都是wire。
若wire和reg用错地方,compiler都会提醒,所以不必太担心。
组合逻辑输出变量,可以直接用assign。
如果不指定为reg类型,那么就默认为1位wire类型,故无需指定1位wire类型的变量。
专门指定出wire类型,可能是多位或为使程序易读。
wire只能被assign连续赋值,reg只能在initial和always中赋值。
比如: module lddata(clk,rst,cs,din,dout,tmpdata); input clk, rst,cs; input din; output dout,tmpdata; reg tmpdata; always@(posedge clk or negedge rst) if(!rst) tmpdata <=0; else tmpdata<= din; assign dout = tmpdata|cs; endmodule
其实他们是不同的抽象级别,wire 如同vhdl中的signal类型,是和实际的物理连接对应的,而reg属于算法描述层次用的类型,和实际电路没有直接的对应关系,也就是说它相当于c语言中的变量(int,float等),vhdl中的variable。reg不和实际的电路如寄存器对应,高层次的描述时用。而always其实算是算法级描述的语句,所以其中的变量必须声明为reg。
比如:一个简单的组合逻辑的例子,用了reg类型 module mux(a,b,c,sel); input a,b,sel; output c;reg c; always @(sel or a or b) if(sel ==1'b0) c=a; else c=b; endmodule;
这个综合出来就是一个简单的二选一选择器,组合逻辑电路。
看它描述的方式,是不是就是把电路的行为(功能)描述出来了,这种就是算法级描述。
wire表示直通,即输入有变化,输出马上无条件地反映(如与、非门的简单连接)。reg表示一定要有触发,没有输入的时候可以保持原来的值,但不直接实际的硬件电路对应(并非不能生成实际电路)。
线网型数据包括wire,wand,wor等几种类型,需要在被一个或一个以上驱动源驱动时,才能各自决定其不同线网型数据的最终值。
两者的区别是:reg寄存器型数据保持最后一次的赋值,而wire线网型数据需要持续的驱动。