wire vs reg: The left-hand-side of an assign statement must be a net type (e.g., wire), while the left-hand-side of a procedural assignment (in an always block) must be a variable type (e.g., reg). These types (wire vs. reg) have nothing to do with what hardware is synthesized, and is just syntax left over from Verilog’s use as a hardware simulation language. 赋值语句的左侧必须是网络类型(例如,wire),而过程赋值的左侧(在always块中)必须是变量类型(例如,reg)。这些类型(wire 与 reg)与合成的硬件无关,只是 Verilog 作为硬件模拟编译语言使用时遗留下来的语法。
module top_module(
input a,
input b,
output wire out_assign,
output reg out_alwaysblock
);
assign out_assign = a & b;
always @(*) begin
out_alwaysblock = a & b;
end
endmodule
2.Clocked: always @(posedge clk)
Clocked always blocks create a blob of combinational logic just like combinational always blocks, but also creates a set of flip-flops;
时钟always块创建一个组合逻辑块,就像组合always块一样,而且还在组合逻辑块的输出处创建一组触发器(或“寄存器”)。逻辑块的输出不是立即改变,而是仅在下一个 (posege clk) 之后改变。
Ways to set value:
module top_module(
input clk,
input a,
input b,
output wire out_assign,
output reg out_always_comb,
output reg out_always_ff );
assign out_assign = a ^ b;
always @(*) begin
out_always_comb = a ^ b;
end
always @(posedge clk) begin
out_always_ff <= a ^ b;
end
endmodule
//--another demo
module top_module(
input a,
input b,
input sel_b1,
input sel_b2,
output wire out_assign,
output reg out_always );
assign out_assign = (sel_b1 & sel_b2 ==1'b1) ? b : a;
always @(*) begin
if(sel_b1==1'b1 && sel_b2==1'b1) begin
out_always = b;
end else begin
out_always = a;
end
end
endmodule
Common source of errors: How to avoid making latches
Syntactically-correct code does not necessarily result in a reasonable circuit (combinational logic + flip-flops). The usual reason is: “What happens in the cases other than those you specified?”. Verilog’s answer is: Keep the outputs unchanged.
语法正确的代码不一定会产生合理的电路(组合逻辑+触发器)。通常的原因是:“除了指定的情况之外,会发生什么情况?”。 Verilog 的答案是:保持输出不变。
inferring latch(es)" messages----Unless the latch was intentional, it almost always indicates a bug; Combinational circuits must have a value assigned to all outputs under all conditions. This usually means you always need else clauses or a default value assigned to the outputs.
Solution: 这通常意味着您始终需要 else 子句或为输出分配默认值。
示例:在组合逻辑中,输出必须要有赋值,且不能是自己本身;
// synthesis verilog_input_version verilog_2001
module top_module (
input cpu_overheated,
output reg shut_off_computer,
input arrived,
input gas_tank_empty,
output reg keep_driving ); //
//==shut_off_computer logic
always @(*) begin
if (cpu_overheated) begin
shut_off_computer = 1;
end else begin
shut_off_computer = 0;
end
end
//====keep_driving logic
always @(*) begin
if(arrived==1'b1) begin
keep_driving = 1'b0;
end else if((~arrived) && (~gas_tank_empty)) begin
keep_driving = 1'b1;
end else begin
keep_driving = 1'b0;
end
end
endmodule
always @(*) begin // This is a combinational circuit
case (in)
1'b1: begin
out = 1'b1; // begin-end if >1 statement
end
1'b0: out = 1'b0;
default: out = 1'bx;
endcase
end
//==6-to-1 multiplexer
// synthesis verilog_input_version verilog_2001
module top_module (
input [2:0] sel,
input [3:0] data0,
input [3:0] data1,
input [3:0] data2,
input [3:0] data3,
input [3:0] data4,
input [3:0] data5,
output reg [3:0] out );//
//==6-to-1 multiplexer
always@(*) begin // This is a combinational circuit
case(sel)
0: out = data0;
1: out = data1;
2: out = data2;
3: out = data3;
4: out = data4;
5: out = data5;
default: out = 4'b0;
endcase
end
endmodule
2.priority encoder
// synthesis verilog_input_version verilog_2001
module top_module (
input [3:0] in,
output reg [1:0] pos );
always @(*) begin
casez(in[3:0])
4'b???1: pos = 2'b00;
4'b??10: pos = 2'b01;
4'b?100: pos = 2'b10;
4'b1???: pos = 2'b11;
default: pos = 2'b00;
endcase
end
endmodule
// synthesis verilog_input_version verilog_2001
module top_module (
input [7:0] in,
output reg [2:0] pos );
always @(*) begin
casez(in[7:0])
8'bzzzz_zzz1: pos = 3'b000;
8'bzzzz_zz10: pos = 3'b001;
8'bzzzz_z100: pos = 3'b010;
8'bzzzz_1000: pos = 3'b011;
8'bzzz1_0000: pos = 3'b100;
8'bzz10_0000: pos = 3'b101;
8'bz100_0000: pos = 3'b110;
8'b1000_0000: pos = 3'b111;
default: pos = 3'b000;
endcase
end
endmodule
3.Avoid latches : set value to outputs
在赋值的时候,必须为所有的输出进行赋值;
module top_module (
input [15:0] scancode,
output reg left,
output reg down,
output reg right,
output reg up );
always @(*) begin
left = 0;
down = 0;
right= 0;
up = 0;
case(scancode[15:0])
16'he06b: left = 1'b1;
16'he072: down = 1'b1;
16'he074: right= 1'b1;
16'he075: up = 1'b1;
endcase
end
endmodule