hdlbits.01xz.net答案 /Verilog Language/Procedure

1.Alwaysblock2

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@(a or b)
out_always_comb = a ^ b;
always@(posedge clk)
out_always_ff = a ^ b;
endmodule

2.Always if

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@(sel_b1 or sel_b2 or a or b)
if(sel_b1 & sel_b2)
out_always = b;
else if(!(sel_b1 & sel_b2))
out_always = a;
else//这是为了防止出现锁存器,这非常重要!!!因为信号并非实际上只有0和1还有x(亚稳态)和z(高阻态)
out_always = 0;
endmodule

** Verilog对于那些我们没有说明的条件默认为保持原样因而很容易出现锁存器!!!**
3.Always if2
本例中即体现了消除锁存:组合电路一定要说清楚所有相关情况的去向,否则就会出现锁存,if一定要else,case务必default

module top_module (
input cpu_overheated,
output reg shut_off_computer,
input arrived,
input gas_tank_empty,
output reg keep_driving ); //

always @(cpu_overheated) begin
if (cpu_overheated)
shut_off_computer = 1;
else
shut_off_computer = 0;
end

always @(arrived or gas_tank_empty) begin
if (arrived | gas_tank_empty)
keep_driving = 0;
else
keep_driving = 1;
end
endmodule

4.Always case
对于case功能,有三点需要注意:
区别于C,它没有switch;
一个item后只允许执行一条语句,如果要执行多条要begin...end
允许item之间有相互重合的部分,C是不允许的,重合时优先执行第一个;

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@(sel or data0 or data1 or data2 or data3 or data4 or data5) 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 = 4'b0000;
endcase
end

endmodule

5.Always case2
本例实现了一个优先编码器,在这里我用了casex(),因为它允许出现x,x表示不关心这个值究竟取什么,使用case()这样写则会报错;
例如xx1就包括:001,011,111,101;如果这里用case()代码会很长;

module top_module (
input [3:0] in,
output reg [1:0] pos );

always@(in)
casex(in)
4'bxxx1: pos = 2'b00;
4'bxx10: pos = 2'b01;
4'bx100: pos = 2'b10;
4'b1000: pos = 2'b11;
default: pos = 2'b00;
endcase
endmodule

这里引入了一个casez();它对高阻态"z"不关心
以下的代码实现是利用了case再overlap时优先执行前一个的特性,因而quartus会警告,建议还是用casex()逻辑上更清晰;

module top_module (
input [7:0] in,
output reg [2:0] pos );
always@(in)
casez(in)
8'bzzzzzzz1: pos = 3'b000;
8'bzzzzzz1z: pos = 3'b001;
8'bzzzzz1zz: pos = 3'b010;
8'bzzzz1zzz: pos = 3'b011;
8'bzzz1zzzz: pos = 3'b100;
8'bzz1zzzzz: pos = 3'b101;
8'bz1zzzzzz: pos = 3'b110;
8'b1zzzzzzz: pos = 3'b111;
default: pos = 3'b000;
endcase
endmodule

7.Always nolatches
本例我们可以看到良好的代码风格能使得描述更为简单清晰。

module top_module (
input [15:0] scancode,
output reg left,
output reg down,
output reg right,
output reg up );

always@(scancode)
begin left = 0; right = 0; up = 0; down = 0;
//每次执行扫描之前都要清零,避免上一次的结果影响下一次,保证了各个其他情况都是有输出均为零
case(scancode)
16'he06b: left = 1;
16'he072: down = 1;
16'he074: right = 1;
16'he075: up = 1;
default:;//因为开始时已经清零,所以default可以不用写内容,但是最好还是写一下default
endcase
end
endmodule
posted @ 2021-03-23 15:53  黑衣の甘铃儿  阅读(252)  评论(0)    收藏  举报