Menu Close

3/8译码器及Verilog不同实现方法

译码器正好与编码器的行为相反,译码是将编码还原到本码的过程,即每组代码有一个相应输出端为有效(高/低)电平,其余输出端为无效(低/高)电平。

  1. 按照功能可将译码器分为:
  2. 变量译码器:如 2/4译码器,3/8译码器,4/16译码器等。
  3. 码制变换器:BCD/16,格雷码/16,
  4. 显示译码 :数码管,ASCII等

例1:设计3/8变量译码器 ,要求3位输入,8位输出,输出的8种组合中只有一位为1,其它为零,8种组合与3位变量的最小项一一对应,如表1:

表一:

从表一种可以看出,3/8译码器非常简单,根据真值表可以直接写出逻辑表达式,这里直接给出Verilog的代码描述。

第一种方法:与或非并发赋值

在并发语句中直接将组合逻辑赋给对应的输出变量

module dec3t8
(
    input  a, b, c,
    output y0, y1, y2, y3, y4, y5, y6, y7
);
assign    y0 = ~a & ~b & ~c;
assign    y1 = ~a & ~b &  c;
assign    y2 = ~a &  b & ~c;
assign    y3 = ~a &  b &  c;
assign    y4 =  a & ~b & ~c;
assign    y5 =  a & ~b &  c;
assign    y6 =  a &  b & ~c;
assign    y7 =  a &  b &  c;
 
endmodule

 

第二种方法,在always过程中采用if语句译码

module dec38if
(
    input      [2:0] a,
    output reg [7:0] y
);
 
always@(*)  
begin
    y = 8'b0;
 
    if(a[2])    
    begin
        if(a[1]) 
        begin
            if(a[0]) y[7] = 1'b1;
            else     y[6] = 1'b1;
        end
        else  
        begin
            if(a[0]) y[5] = 1'b1;
            else     y[4] = 1'b1;
        end
    end
    else 
    begin
        if(a[1])    
        begin
            if(a[0]) y[3] = 1'b1;
            else     y[2] = 1'b1;
        end
        else    
        begin
            if(a[0]) y[1] = 1'b1;
            else     y[0] = 1'b1;
        end
    end
end
 
 
endmodule

 

仿真激励程序testbench

`timescale 1 ns / 1 ps
 
module tb_dis (); 
     
reg  [2:0] a; 
 
wire [7:0] y;
 
initial 
begin
    a = 3'b000;
    #10
    $display("time =%t, a= %b,  y= %b ",$time ,a, y);
 
    a = 3'b001;
    #10
    $display("time =%t, a= %b,  y= %b ",$time ,a,y);
 
    a = 3'b010;
    #10
    $display("time =%t, a= %b,  y= %b ",$time ,a, y);
 
    a = 3'b011;
    #10
    $display("time =%t, a= %b,  y= %b ",$time ,a, y);
 
    a = 3'b100;
    #10
    $display("time =%t, a= %b,  y= %b ",$time ,a, y);
 
    a = 3'b101;
    #10
    $display("time =%t, a= %b,  y= %b ",$time ,a,y);
 
    a = 3'b110;
    #10
    $display("time =%t, a= %b,  y= %b ",$time ,a, y);
 
    a = 3'b111;
    #10
    $display("time =%t, a= %b,  y= %b ",$time ,a,y);
 
end
 
 
dec38if dec38if_inst
(
    .a (a),
    .y (y)
);
 
 
endmodule

 

$display函数显示的结果

Modelsim的仿真结果:

图1

第三种方法采用always 过程中case语句实现

module dec38case
(
    input      [2:0] a,
    output reg [7:0] y
);
 
always@(*)  
begin
    case(a)
    7: y = 8'b1000_0000;
    6: y = 8'b0100_0000;
    5: y = 8'b0010_0000;
    4: y = 8'b0001_0000;
    3: y = 8'b0000_1000;
    2: y = 8'b0000_0100;
    1: y = 8'b0000_0010;
    0: y = 8'b0000_0001;
    default: y = 8'bxxxx_xxxx;
    endcase
 
end
 
endmodule

 

在case 语句的最后使用default语句对其它情况做了8’bxxxx_xxxx的赋值,这种情况对于仿真观察非常有用,其实在真实的运行也是存在的,比如在开关输入,按键输入等都有抖动情况,对于输入从低电平到高电平过度期间存在X值的情况。修改仿真程序观察X或Z输入的情况。

仿真程序如下:

`timescale 1 ns / 1 ps
 
 
module tb_dis (); 
 
reg  [2:0] a; 
 
wire [7:0] y;
 
initial 
begin
    a = 3'b000;
    #10
    $display("time =%t, a= %b,  y= %b ",$time ,a, y);
 
    a = 3'b001;
    #10
    $display("time =%t, a= %b,  y= %b ",$time ,a, y);
 
    a = 3'b010;
    #10
    $display("time =%t, a= %b,  y= %b ",$time ,a, y);
 
    a = 3'b011;
    #10
    $display("time =%t, a= %b,  y= %b ",$time ,a, y);
 
    a = 3'b100;
    #10
    $display("time =%t, a= %b,  y= %b ",$time ,a, y);
 
    a = 3'b101;
    #10
    $display("time =%t, a= %b,  y= %b ",$time ,a, y);
 
    a = 3'b110;
    #10
    $display("time =%t, a= %b,  y= %b ",$time ,a, y);
 
    a = 3'b111;
    #10
    $display("time =%t, a= %b,  y= %b ",$time ,a, y);
 
    a = 3'b11z;
    #10
    $display("time =%t, a= %b,  y= %b ",$time ,a, y);
 
    a = 3'b1xx;
    #10
    $display("time =%t, a= %b,  y= %b ",$time ,a, y);
 
end
 
 
dec38case dec38case_inst
(
    .a (a),
    .y (y)
);
 
 
endmodule

 

$display 函数的显示结果:

Modelsim 波形显示结果如图2:

图2

第四种方法,不考虑输入有z,x 的情况

always @ ( * )
begin
    y = 0;
    y[a] = 1’b1;
end

 

总结:在组合电路的设计中,可以有多种方法实现,描述方式也各不相同,最终都可以达到同一个目的。其它方法还有很多,如function,task, for… loop,repeat等语法结构都可以实现。同时也要提醒一点,在顺序语句中使用了reg类型的变量,不一定就会综合成时序电路,如本文的描述最终综合结果都是组合电路。

练习题:

  1. 利用repeat语句实现3/8 译码器。
  2. 理由function实现3/8译码器
  3. 利用task实现3/8译码器
  4. 举例说明reg在什么条件下会综合成触发器?

 

对应视频:

Posted in FPGA, FPGA 教材教案, Quartus II, Verilog, Verilog, Vivado, 教材与教案

发表回复

相关链接