Menu Close

优先编码器的设计及Verilog 描述

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

%title插图%num

图1

观察芯片的功能表,有如下特点:

  • 8个输入,低有效,高位优先。
  • 3位代码,反码输出。
  • 3个使能端:一个使能输入,两个使能输出用于扩展。
    1. 使能输入 ST=0 编码; ST=1 禁止
    2. 使能输出 Ys=0使能其他芯片;Ys=1非使能其他芯片
    3. 扩展输出端 Yex=1 本片未编码;Yex=0 本片已编码

从上面的功能表可以看出,本芯片是多输入、多输出结构,虽然可以利用上面的真值表和卡诺图化简完全可以形成与或非式的组合逻辑电路,但却相当繁琐。在利用Verilog进行设计时可以充分利用优先级及无关项进行设计,最终可以利用强大的EDA软件进行优化,实现合理的电路。

例1:利用有优先级功能的if语句描述74LS148 8/3优先编码器

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

`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终端打印出输入输出之间的关系:

%title插图%num

从上面的输出可以看出,显示的结果出现错位的情况,原因是给定输入进阶用$display函数评估输出结果,$display 显示的依然是调用module前的结果,只要在$display之前加上适当小的延迟(#delay)即可。

改写仿真程序的延时顺序,就可以得到正确的结果。

`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

 

%title插图%num

Modelsim的仿真波形如下:

%title插图%num

图1

例2:利用case语句描述74LS148 8/3优先编码器

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

 

仿真可以继续采用例中修正的激励程序。结果如下:

%title插图%num

可见利用RTL进行逻辑电路描述,把原本复杂繁琐的化简过程交给EDA软件处理,设计者把更多的精力放在功能设计上,在大系统设计上可以做到事半功倍的效果。

作业题:

  1. 比较if,case, casex的异同, casex是否可以描述带有优先级的逻辑电路
  2. reg型的变量何时可以综合成组合电路,锁存器,触发器等模型,举例说明。
  3. 分别利用if,case, casex描述4/2优先编码器,并在FII-PRA006开发板上演示实验结果。

(开关sw1-4作为输入,led6,7显示编码结果)

 

Posted in FPGA, FPGA, IP开发, Quartus II, Verilog, Verilog, 教材与教案, 文章

2 Comments

  1. 张洪泉

    练习题:(个人解答)
    1. casex与case功能类似,但是casex语句的判断分支可以带x值,因此符合优先级编码器的描述
    2. 看敏感列表,如果是alway@(*),则reg型变量综合成组合逻辑电路,如果是alway@(a), 则变量综合成锁存器,如果是alway@(posedge clk),则变量综合成触发器
    3.待发

    • tzhuang

      看敏感列表,如果是alway@(*),则reg型变量综合成组合逻辑电路,如果是alway@(a), 则变量综合成锁存器,如果是alway@(posedge clk),则变量综合成触发器. 基本正确,如果是alway@(*)在不完全分支语句中仍然会生成锁存器,具体可以参考”阻塞与非阻塞赋值语句深入探讨(2)” http://www.icfedu.cn/archives/16532

发表评论

相关链接