1. 循环结构always
语句结构: always@(时序控制) (语句)
注意:
assign 和 always 语句 功能重合, 选一种即可
// 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@(*) out_alwaysblock=a&b;
endmodule
// 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@(*)
out_always_comb = a^b;
always@(posedge clk) // 注意 完整的结构, 中间带 posedge
out_always_ff <= a^b; //非阻塞赋值 <=,同时执行; 阻塞赋值,按顺序执行
endmodule
笔记:
- 电平敏感变化的always时序控制:
采用关键字 wait , 反应需要等待多少个时钟周期,才会执行后面的语句
always
wait (count_enable) #20 count = count + 1;
// count_enable = 0 , 不执行后面的语句
// count_enable = 1 , 执行 count = count + 1
// count_enable 一直为 1 ,每20个时钟周期执行一次 count = count + 1
- 阻塞赋值和非阻塞赋值
//阻塞赋值
begin // 假设当前 a=1,b=0,c=0
b=a; // b=1;
c=a+b; // c=2;
end
//非阻塞赋值
begin //假设当前 a=1,b=0,c=0
b<=a; //b=1;
c=a+b; //同时执行,此时b还是0,未更新,c=1+0=1;
end
2. if 如果
// 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 );
assign out_assign = ((sel_b1&&sel_b2)?b:a);
always@(*)
begin
if (sel_b1&&sel_b2)
begin
out_always = b;
end
else
begin
out_always = a;
end
end
endmodule
注意: 此处的 & &因为只有一位,也可以选择 按位与 &
判断条件 sel_b1和sel_b2为真,不可以写成 ((sel_b1=1)&&(sel_b2=1)),这样子写会报错
// 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 ); //
always @(*) begin
if (cpu_overheated) //CPU过热,则停止计算机
shut_off_computer = 1;
else if(~cpu_overheated) //CPU没过热,则不停止计算机
shut_off_computer = 0;
end
always @(*) begin
if (~arrived) // 没到达,油箱没空就继续,油箱空了就停车
keep_driving = ~gas_tank_empty;
else if (arrived)
keep_driving = 0;
end
endmodule
3. case 举例
// 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 );//
always@(*) begin // This is a combinational circuit
case(sel)
3'b000: out = data0;
3'b001: out = data1;
3'b010: out = data2;
3'b011: out = data3;
3'b100: out = data4;
3'b101: out = data5;
default : out = 3'b000;
endcase
end
endmodule
// synthesis verilog_input_version verilog_2001
module top_module (
input [3:0] in,
output reg [1:0] pos );
always@(*)
begin
casez(in) // 此处的case 置带有不定式 在,因此要用casez
4'bZZZ1: pos = 2'd0;
4'bZZ10: pos = 2'd1;
4'bZ100: pos = 2'd2;
4'b1000: pos = 2'd3;
default: pos = 0;
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)
8'bz1: pos = 0;
8'bz10: pos = 1;
8'bz100: pos = 2;
8'bz1000: pos = 3;
8'bz10000: pos = 4;
8'bz100000: pos = 5;
8'bz1000000: pos = 6;
8'b10000000: pos = 7;
default: pos = 0;
endcase
end
endmodule
// 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
// 为防止case后面不满足条件的事件不好描述,提前先给 这些量定值
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