The syntax for code inside a procedural block is different from code that is outside. Procedural blocks have a richer set of statements (e.g., if-then, case), cannot contain continuous assignments*, but also introduces many new non-intuitive ways of making errors. (*Procedural continuous assignments do exist, but are somewhat different from continuous assignments, and are not synthesizable.)
A note on 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.
Always block:
// synthesis verilog_input_version verilog_2001
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
- tip:
如果不按照这种要求的话可能会在模拟和实际硬件中出现难以发现的错误。
// synthesis verilog_input_version verilog_2001
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
If Statement:
// synthesis verilog_input_version verilog_2001
module top_module(
input a,
input b,
input sel_b1,
input sel_b2,
output wire out_assign,
output reg out_always );
always @(*)
if (sel_b1&sel_b2==1) begin
out_always = b;
end
else begin
out_always = a;
end
assign out_assign = out_always;
endmodule
- 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.
module top_module (
input cpu_overheated,
output reg shut_off_computer,
input arrived,
input gas_tank_empty,
output reg keep_driving ); //
always @(*) begin
if (cpu_overheated)
shut_off_computer = 1;
else
shut_off_computer = 0;
end
always @(*) begin
if (~arrived)
keep_driving = ~gas_tank_empty;
else
keep_driving = 0;
end
endmodule
Case Statement:
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 );//
always@(*) begin // This is a combinational circuit
case(sel)
3'b000:begin out = data0;
end
3'b001:begin out = data1;
end
3'b010:begin out = data2;
end
3'b011:begin out = data3;
end
3'b100:begin out = data4;
end
3'b101:begin out = data5;
end
default: out = 0;
endcase
end
endmodule
module top_module (
input [3:0] in,
output reg [1:0] pos );
always @(*)
case(in)
4'h0:begin pos = 2'd0;
end
4'h1:begin pos = 2'd0;
end
4'h2:begin pos = 2'd1;
end
4'h3:begin pos = 2'd0;
end
4'h4:begin pos = 2'd2;
end
4'h5:begin pos = 2'd0;
end
4'h6:begin pos = 2'd1;
end
4'h7:begin pos = 2'd0;
end
4'h8:begin pos = 2'd3;
end
4'h9:begin pos = 2'd0;
end
4'hA:begin pos = 2'd1;
end
4'hB:begin pos = 2'd0;
end
4'hC:begin pos = 2'd2;
end
4'hD:begin pos = 2'd0;
end
4'hE:begin pos = 2'd1;
end
4'hF:begin pos = 2'd0;
end
endcase
endmodule
- From the previous exercise (always_case2), there would be 256 cases in the case statement. We can reduce this (down to 9 cases) if the case items in the case statement supported don’t-care bits. This is what casez is for: It treats bits that have the value z as don’t-care in the comparison.
module top_module (
input [7:0] in,
output reg [2:0] pos );
always @(*)
casez(in) //这个是casez 不是case
8'bzzzzzzz1: begin pos = 0;
end
8'bzzzzzz1z: begin pos = 1;
end
8'bzzzzz1zz: begin pos = 2;
end
8'bzzzz1zzz: begin pos = 3;
end
8'bzzz1zzzz: begin pos = 4;
end
8'bzz1zzzzz: begin pos = 5;
end
8'bz1zzzzzz: begin pos = 6;
end
8'b1zzzzzzz: begin pos = 7;
end
default: pos = 0;
endcase
endmodule
中间不用加begin和end也没事,但不知道有什么区别。
Avoiding latches:
// synthesis verilog_input_version verilog_2001
module top_module (
input [15:0] scancode,
output reg left,
output reg down,
output reg right,
output reg up );
always @(*) begin
up = 1'b0; down = 1'b0; left = 1'b0; right = 1'b0;
case (scancode)
16'he06b: left = 1'b1;
16'he072: down = 1'b1;
16'he074: right=1'b1;
16'he075: up=1'b1;
endcase
end
endmodule