实验1、组合逻辑

教程

Verilog HDL拥有非常自由的语法,条条大路通罗马。

1、2-4译码器的三种写法

module decoder2_4 (
decode_in,
decode_out
);
input [1:0] decode_in;
output [3:0] decode_out;

//写出逻辑表达式,然后像卡诺图一样写出来
assign decode_out[0] = ~decode_in[1] & ~decode_in[0];
assign decode_out[1] = ~decode_in[1] & decode_in[0];
assign decode_out[2] = decode_in[1] & ~decode_in[0];
assign decode_out[3] = decode_in[1] & decode_in[0];

endmodule
module decoder2_4 (
decode_in,
decode_out
);
input [1:0] decode_in;
output [3:0] decode_out;

//用?:语句写
assign decode_out = decode_in[0] ? 
    (decode_in[1]? 4'b1000: 4'b0010):
    (decode_in[1]? 4'b0100: 4'b0001);

endmodule
module decoder2_4 (
decode_in,
decode_out
);
input [1:0] decode_in;
output reg [3:0] decode_out;

always @(*) begin //组合逻辑的always块写法,这样就可以用if-else或者case语句啦
    if (decode_in == 2'b00)
        decode_out = 4'b0001;
    else if (decode_in == 2'b01)
        decode_out = 4'b0010;
    else if (decode_in == 2'b10)
        decode_out = 4'b0100;
    else if (decode_in == 2'b11)
        decode_out = 4'b1000;
end

endmodule

2、Testbench验证

第一步:先写一下testbench decoder_testbench.v:

`timescale 1ns/1ns
`include "decoder2_4.v"

module decoder_testbench;

reg [1:0] in;
wire [3:0] out1,out2,out3;

decoder2_4_1 dut0(
.decode_in      (in)
, .decode_out   (out1)
);

decoder2_4_2 dut1(
.decode_in      (in)
, .decode_out   (out2)
);

decoder2_4_3 dut2(
.decode_in      (in)
, .decode_out   (out3)
);

integer i; //integer is a 32b unsigned integer

initial begin
    $dumpfile("wave.vcd");
    $dumpvars(0);
end

initial begin
    $monitor("time=%4d, in=%4b, out0=%04b, out1=%04b, out2=%04b", $time, in, out1, out2, out3);
    // $monitor为Verilog系统自带函数, 格式像c++的printf一样,意为“每当要print的变量发生变化即打印”,同理还有$display(仅在当前仿真运行时间打印一样结果)
    for(i=0; i<8; i=i+1) begin
        #10 in = i; 
    end
end

endmodule

用iverilog快速验证一下:

cd [到当前存放dff.v和dff_tb.v的文件夹] # 进入工作目录
iverilog -o wave decoder_testbench.v # 将dff_tb.v编译为wave可执行文件
vvp -n wave #运行该可执行文件进行仿真(simulation)

如果到此运行顺利的话,当前文件夹会生成一个新的wave.vcd(正如dff_tb.v里面写的$dumpfile(“wave.vcd”)所写)。然后用gtkwave打开这个波形:

gtkwave wave.vcd

就可以得到。你之前预测的结果是正确的么?

由于我们的testbench.v里写了$monitor(每当里面涉及的variable)

3、2-4译码器的FPGA实现验证

请根据以下教程,将上述testbench和三种decoder的设计置于FPGA上实验,输入用按键。

参考:

练习

1、奇偶校验码 (parity check code)设计

奇偶校验码是最简单的查错编码 (error detection code),其行为是输入m位码字,如果有奇数个1则编码器输出1;如果有偶数个1则编码输出为0。

Note

[问题1] 用Verilog HDL设计一个输入有16位的奇偶校验码,并写testbench验证。

  • 提示:这是对于输入位的什么按位逻辑操作?一种逻辑操作即可搞定。

2、温度计码 (thermometer code)设计

温度计码是模数转换器ADC中常用的编码,一个温度计码解码器的例子为:

输入

输出

0000000

000

0000001

001

0000011

010

0000111

011

0001111

100

0011111

101

0111111

110

1111111

111

它就是长得像温度计。

Note

[问题2]

2.1 用Verilog HDL设计一个输入是1023位的温度计解码器,用组合逻辑实现上述功能,并写testbench验证。

2.2 温度计码很容易出错哦,比如出现1000011码字,在问题2.1的基础上改进加入报错端口,一旦有错码字,报错端口error=1,否则保持为0。请完成一个全新的设计:带校验功能的温度计解码!