HDLBits(7)9.19
2 Verilog语言
2.4 程序
2.4.5 Always case
当可能的情况较多时,适合使用 case 语句而非 if-else 语句
case 语句以 case 开头,每个 case 项以冒号结束
case 项后的执行语句可以是单条,也可以是多条,但多条需要用 begin-end 进行说明
case项允许重复和部分重叠,执行程序匹配到的第一个
当 case 项均不符合,则执行 default 项
always @(*) begin
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
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 = 4'b0000;
endcase
end
endmodule
2.4.6 优先编码器(Priority encoder)
优先编码器是组合电路,当给定输入时,输出输入向量中的右边第一个1的位置。例如,输入8'b10010000的,则优先编码器将输出3'd4,因为位[4]是从右数第一个1
构建一个4位优先编码器。如果没有输入均为零,则输出零
//方法1,将每种可能的数字分别作为case
module top_module (
input [3:0] in,
output reg [1:0] pos);
always@(*)
case(in)
4'b0000: pos = 2'b00;
4'b0001: pos = 2'b00;
4'b0010: pos = 2'b01;
4'b0011: pos = 2'b00;
4'b0100: pos = 2'b10;
4'b0101: pos = 2'b00;
4'b0110: pos = 2'b01;
4'b0111: pos = 2'b00;
4'b1000: pos = 2'b11;
4'b1001: pos = 2'b00;
4'b1010: pos = 2'b01;
4'b1011: pos = 2'b00;
4'b1100: pos = 2'b10;
4'b1101: pos = 2'b00;
4'b1110: pos = 2'b01;
4'b1111: pos = 2'b00;
default: pos = 2'b00;
endcase
endmodule
//由于case项若有多项为真,按照顺序执行匹配到的第一个,所以可以只针对每个位是否为1
module top_module (
input [3:0] in,
output reg [1:0] pos );
always@(*)begin
case(1)
in[0]:pos=2'd0;
in[1]:pos=2'd1;
in[2]:pos=2'd2;
in[3]:pos=2'd3;
default:pos=2'd0;
endcase
end
endmodule
2.4.7 Always casez
casez:在比较中将具有z的位是为无关项,例如:无论是 10 还是 11 都会匹配到 1z 项
构建一个8输入的优先编码器
module top_module (
input [7:0] in,
output reg [2:0] pos);
always @(*)
casez (in)
8'bzzzzzzz1: pos = 0;
8'bzzzzzz1z: pos = 1;
8'bzzzzz1zz: pos = 2;
8'bzzzz1zzz: pos = 3;
8'bzzz1zzzz: pos = 4;
8'bzz1zzzzz: pos = 5;
8'bz1zzzzzz: pos = 6;
8'b1zzzzzzz: pos = 7;
default: pos = 0;
endcase
endmodule
2.4.8 Always nolatches
可以通过在always和case之间设置默认值来避免锁存器的生成并减少代码量
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;
16'he072: down = 1;
16'he074: right = 1;
16'he075: up = 1;
endcase
end
endmodule