用Verilog设计通用二进制encoder

-- TOC --

二进制encoder,就是将一个1-out-of-n的信号,编码成一个二进制信号。

二进制encoder

binary_encoder

上图右边,是一个8to3的二进制encoder,上图左边,是binary encoder的一般化的逻辑图。一般都有一个EN信号,上图没有画出来。

通用二进制encoder的Verilog实现

binary encoder的verilog实现代码和测试仿真代码如下:

`timescale 1ns / 100ps


module encoder_generic(A, EN, Y);
    parameter N, S;
    input [N-1:0] A;
    input EN;
    output reg [S-1:0] Y;
    integer i,on;

    always @ (*) begin
        Y = 0;
        if (EN) begin
            on = 0;
            for (i=0; i<N; i=i+1)
                if (A[i]==1) begin
                    Y = i;
                    on = on + 1;
                end
            if (on != 1) Y = 0;
        end
    end
endmodule


module test_encoder_generic();
    parameter S=4, N=2**S;
    reg [N-1:0] A;
    reg EN;
    wire [S-1:0] Y;
    integer i,j,k;

    encoder_generic #(N,S) UUT(A, EN, Y);
    initial begin
        for (i=0; i<2; i=i+1)
            for (j=0; j<N; j=j+1) begin
                EN = i;
                A = 0; A[j] = 1;
                #10;
                if ((EN==0) && (Y!=0))
                    $display("Y should be zero when EN=0!");
                if ((EN==1) && (Y!=j))
                    $display("Error j=%d",j);
            end
        $display("Test Done!");
    end
endmodule

上面这段代码存在2个问题:

  1. N必须小于或等于S的二次幂,在大于的情况下,encoder_generic的输出会有重复;
  2. 测试代码不完整,没有完全覆盖异常输入的情况,比如有多个输入信号assert的时候。

其实,我是写了一段代码专门测试错误输入的情况,但是遇到一个编译错误:Range must be bounded by constant expressions. 我写了一个 A[j-1:0] = k; 这样一句,j 是一个循环变量,一时找不到解决方案,就删掉了。

仿真wave

下图是S=4,N=16时的wave图,很OK:

wave_16to4

写verilog代码有一个基本思路:构造遍历输入,等待一小会,然后检查输出是否符合预期!测试代码要有error打印,判断测试仿真成功,要既没有error打印,wave也符合预期,看不出问题。

本文链接:https://cs.pynote.net/hd/verilog/202110015/

-- EOF --

-- MORE --