优先编码器就是当有两个或两个以上的信号同时输入编码电路,电路只能对其中一个优先级别高的信号进行编码。即允许几个信号同时有效,但电路只对其中优先级别高的信号进行编码,而对其它优先级别低的信号不予理睬。以集成优先编码器74 ls148为例介绍,其功能表如下:

图1
观察芯片的功能表,有如下特点:
- 8个输入,低有效,高位优先。
- 3位代码,反码输出。
- 3个使能端:一个使能输入,两个使能输出用于扩展。
从上面的功能表可以看出,本芯片是多输入、多输出结构,虽然可以利用上面的真值表和卡诺图化简完全可以形成与或非式的组合逻辑电路,但却相当繁琐。在利用Verilog进行设计时可以充分利用优先级及无关项进行设计,最终可以利用强大的EDA软件进行优化,实现合理的电路。
例1:利用有优先级功能的if语句描述74LS148 8/3优先编码器
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
module M74ls148 ( input nst, input [7:0] nin, output reg [2:0] y, output reg yex, output reg ys ); always@(*) begin if(nst) begin y = 3'b111; yex = 1'b1; ys = 1'b1; end else begin if( !nin[7] ) y = 3'b000; else if (!nin[6]) y = 3'b001; else if (!nin[5]) y = 3'b010; else if (!nin[4]) y = 3'b011; else if (!nin[3]) y = 3'b100; else if (!nin[2]) y = 3'b101; else if (!nin[1]) y = 3'b110; else if (!nin[0]) y = 3'b111; else y = 3'b111; if(~nin) begin yex = 1'b0; ys = 1'b1; end else begin yex = 1'b1; ys = 1'b0; end end end endmodule |
Testbench激励程序test_encode.v
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
`timescale 1 ns / 1 ps module tb_encode (); reg [7:0] nin; reg nst; wire [2:0] y; wire yex; wire ys; initial begin nst = 1'b1; nin = 8'b0; #1 $display("time =%t, nst= %b, nin=%b, y= %b, yex= %b, ys=%b", $time,nst, nin, y, yex, ys); #10 nin = 8'bx; $display("time =%t, nst= %b, nin=%b, y= %b, yex= %b, ys=%b", $time,nst, nin, y, yex, ys); #10 nst = 1'b0; nin = 8'b0xxx_xxxx; $display("time =%t, nst= %b, nin=%b, y= %b, yex= %b, ys=%b", $time,nst, nin, y, yex, ys); #10 nin = 8'b10xx_xxxx; $display("time =%t, nst= %b, nin=%b, y= %b, yex= %b, ys=%b", $time,nst, nin, y, yex, ys); #10 nin = 8'b110x_xxxx; $display("time =%t, nst= %b, nin=%b, y= %b, yex= %b, ys=%b", $time,nst, nin, y, yex, ys); #10 nin = 8'b1110_xxxx; $display("time =%t, nst= %b, nin=%b, y= %b, yex= %b, ys=%b", $time,nst, nin, y, yex, ys); #10 nin = 8'b1111_0xxx; $display("time =%t, nst= %b, nin=%b, y= %b, yex= %b, ys=%b", $time,nst, nin, y, yex, ys); #10 nin = 8'b1111_10xx; $display("time =%t, nst= %b, nin=%b, y= %b, yex= %b, ys=%b", $time ,nst, nin, y, yex, ys); #10 nin = 8'b1111_110x; $display("time =%t, nst= %b, nin=%b, y= %b, yex= %b, ys=%b", $time ,nst, nin, y, yex, ys); #10 nin = 8'b1111_1110; $display("time =%t, nst= %b, nin=%b, y= %b, yex= %b, ys=%b", $time,nst, nin, y, yex, ys); #10 nin = 8'b1111_1111; $display("time =%t, nst= %b, nin=%b, y= %b, yex= %b, ys=%b", $time, nst, nin, y, yex, ys); end M74ls148 M74ls148_inst ( .nst (nst), .nin (nin), .y (y), .yex (yex), .ys (ys) ); endmodule |
$display 函数将在modelsim终端打印出输入输出之间的关系:

从上面的输出可以看出,显示的结果出现错位的情况,原因是给定输入进阶用$display函数评估输出结果,$display 显示的依然是调用module前的结果,只要在$display之前加上适当小的延迟(#delay)即可。
改写仿真程序的延时顺序,就可以得到正确的结果。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
`timescale 1 ns / 1 ps module tb_encode (); reg [7:0] nin; reg nst; wire [2:0] y; wire yex; wire ys; initial begin nst = 1'b1; nin = 8'b0; #10 $display("time =%t, nst= %b, nin=%b, y= %b, yex= %b, ys=%b", $time, nst, nin, y, yex, ys); nin = 8'bx; #10 $display("time =%t, nst= %b, nin=%b, y= %b, yex= %b, ys=%b", $time, nst, nin, y, yex, ys); nst = 1'b0; nin = 8'b0xxx_xxxx; #10 $display("time =%t, nst= %b, nin=%b, y= %b, yex= %b, ys=%b", $time, nst, nin, y, yex, ys); nin = 8'b10xx_xxxx; #10 $display("time =%t, nst= %b, nin=%b, y= %b, yex= %b, ys=%b", $time, nst, nin, y, yex, ys); nin = 8'b110x_xxxx; #10 $display("time =%t, nst= %b, nin=%b, y= %b, yex= %b, ys=%b", $time, nst, nin, y, yex, ys); nin = 8'b1110_xxxx; #10 $display("time =%t, nst= %b, nin=%b, y= %b, yex= %b, ys=%b", $time, nst, nin, y, yex, ys); nin = 8'b1111_0xxx; #10 $display("time =%t, nst= %b, nin=%b, y= %b, yex= %b, ys=%b", $time, nst, nin, y, yex, ys); nin = 8'b1111_10xx; #10 $display("time =%t, nst= %b, nin=%b, y= %b, yex= %b, ys=%b", $time, nst, nin, y, yex, ys); nin = 8'b1111_110x; #10 $display("time =%t, nst= %b, nin=%b, y= %b, yex= %b, ys=%b", $time , nst, nin, y, yex, ys); nin = 8'b1111_1110; #10 $display("time =%t, nst= %b, nin=%b, y= %b, yex= %b, ys=%b", $time ,nst, nin, y, yex, ys); nin = 8'b1111_1111; #10 $display("time =%t, nst= %b, nin=%b, y= %b, yex= %b, ys=%b", $time , nst, nin, y, yex, ys); end M74ls148 M74ls148_inst ( .nst (nst), .nin (nin), .y (y), .yex (yex), .ys (ys) ); endmodule |

Modelsim的仿真波形如下:

图1
例2:利用case语句描述74LS148 8/3优先编码器
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
module M74ls148 ( input nst, input [7:0] nin, output reg [2:0] y, output reg yex, output reg ys ); always@(*) begin casex( {nst, nin} ) {1'b1,8'bxxxx_xxxx}: {y, yex, ys} = 5'b11111; {1'b0,8'b1111_1111}: {y, yex, ys} = 5'b11110; {1'b0,8'b0xxx_xxxx}: {y, yex, ys} = 5'b00001; {1'b0,8'b10xx_xxxx}: {y, yex, ys} = 5'b00101; {1'b0,8'b110x_xxxx}: {y, yex, ys} = 5'b01001; {1'b0,8'b1110_xxxx}: {y, yex, ys} = 5'b01101; {1'b0,8'b1111_0xxx}: {y, yex, ys} = 5'b10001; {1'b0,8'b1111_10xx}: {y, yex, ys} = 5'b10101; {1'b0,8'b1111_110X}: {y, yex, ys} = 5'b11001; {1'b0,8'b1111_1110}: {y, yex, ys} = 5'b11101; default:{y, yex, ys} = 5'b11111; endcase end endmodule |
仿真可以继续采用例中修正的激励程序。结果如下:

可见利用RTL进行逻辑电路描述,把原本复杂繁琐的化简过程交给EDA软件处理,设计者把更多的精力放在功能设计上,在大系统设计上可以做到事半功倍的效果。
作业题:
- 比较if,case, casex的异同, casex是否可以描述带有优先级的逻辑电路
- reg型的变量何时可以综合成组合电路,锁存器,触发器等模型,举例说明。
- 分别利用if,case, casex描述4/2优先编码器,并在FII-PRA006开发板上演示实验结果。
(开关sw1-4作为输入,led6,7显示编码结果)
对应视频: