What is the difference between a reg and a wire? When are we supposed to use reg and when are we supposed to use wire in a verilog module. I have also noticed sometimes that a output is declared again as a reg. E.g reg Q in a D flip flop. I have read this somewhere - "The target output of procedural assignment statements must be of reg data type." What are procedural assignment statements? I have throughly googled this but was not able to find a clear explanation.
Wire:-
Wires are used for connecting different elements. They can be treated as physical wires. They can be read or assigned. No values get stored in them. They need to be driven by either continuous assign statement or from a port of a module.
Reg:-
Contrary to their name, regs don't necessarily correspond to physical registers. They represent data storage elements in Verilog/SystemVerilog. They retain their value till next value is assigned to them (not through assign statement). They can be synthesized to FF, latch or combinatorial circuit. (They might not be synthesizable !!!)
Wires and Regs are present from Verilog timeframe. SystemVerilog added a new data type called logic to them. So the next question is what is this logic data type and how it is different from our good old wire/reg.
Logic:-
As we have seen, reg data type is bit mis-leading in Verilog. SystemVerilog's logic data type addition is to remove the above confusion. The idea behind is having a new data type called logic which at least doesn't give an impression that it is hardware synthesizable. Logic data type doesn't permit multiple drivers. It has a last assignment wins behavior in case of multiple assignments (which implies it has no hardware equivalence). Reg/Wire data types give X if multiple drivers try to drive them with different values. Logic data type simply assigns the last assignment value. The next difference between reg/wire and logic is that logic can be both driven by assign block, output of a port and inside a procedural block like this
logic a; assign a = b ^ c; // wire style always (c or d) a = c + d; // reg style MyModule module(.out(a), .in(xyz)); // wire style