Verilog HDL学习笔记(1)_LED_3-8/4-16译码器

CSDN的Markdown不支持Verilog语法高亮(lll¬ω¬) , 代码段颜值大幅下降

Verilog HDL

  • 1.led_test
    • 设计文档:
    • 仿真文档:
    • 易错点总结
  • 2. 3-8译码器、4-16译码器的实现
    • 3-8 译码器
    • 设计文档
      • 第一版
        • 编译结果分析
      • 仿真文件
        • 时域仿真误差分析
      • 4-16 译码器
      • 易错点总结

1.led_test

设计文档:

module led_test(a,b,key_in,led_out);//模块开始,模块名与项层名保持一致 
                                                 //(端口a,端口b,按键输入,灯的输出)
//定义端口
	input a;//输入端口A input表示输入类型ab分 开写利于写注释
	input b;//输入端口B
	input key_in;//按键输入, 实现输入通道选择
	output led_out;//led 控制输出端口
//端口定义完毕,下面进行逻辑设计
	
	//按键按下,低电平,输出与端口A保持一致
	//当key_in == 0时,led_out = a
	assign led_out = (key_in == 0) ? a : b; //assign--连续赋值语句设计组合逻辑() ?:选择语句

endmodule//模块结尾

仿真文档:

`timescale 1ns/1ps //定义仿真时间精度   延时1纳秒/精度为1皮秒

module led_test_tb;
   
//激励信号定义,对应连接待测试模块的输入端口
	reg signal_a;
	reg signal_b;
	reg signal_c;
	
//待检测信号定义,对应连接到待测试模块的输出端口
	wire led;
	
//例化待测试模块	
	//将定义的三个端子连接在下面的模块上
	led_test led_test0(       //引入模块并命名为led_test0
	.a(signal_a),
	.b(signal_b),
	.key_in(signal_c),
	.led_out(led));

//产生激励
   initial begin //开始仿真
	   signal_a = 0; signal_b = 0; signal_c = 0; //三个按键的初始状态
		#100; //延时100ns
	   signal_a = 0; signal_b = 0; signal_c = 1; 
		#100; //延时100ns
		signal_a = 0; signal_b = 1; signal_c = 0; 
		#100; //延时100ns
		signal_a = 0; signal_b = 1; signal_c = 1; 
		#100; //延时100ns
		signal_a = 1; signal_b = 0; signal_c = 0; 
		#100; //延时100ns
		signal_a = 1; signal_b = 0; signal_c = 1; 
		#100; //延时100ns
		signal_a = 1; signal_b = 1; signal_c = 0; 
		#100; //延时100ns
		signal_a = 1; signal_b = 1; signal_c = 0; 
		#200; 
		$stop;//仿真结束,不然会陷入循环
    end //这里容易忘记

endmodule

易错点总结

  1. 文件名和模块名要保持一致
  2. 模块endmodule,还有仿真激励的end要记得写

2. 3-8译码器、4-16译码器的实现

3-8 译码器

A B C out
0 0 0 0000_0001
0 0 1 0000_0010
0 1 0 0000_0100
0 1 1 0000_1000
1 0 0 0001_0000
1 0 1 0010_0000
1 1 0 0100_0000
1 1 1 1000_0000

设计文档

第一版

module my3_8(a,b,c,out);//端口列表
   //定义端口类型
    input a;//输入端口A
	input b;//输入端口B
	input c;//输入端口C
	//输出端口
	output [7:0]out;//[7:0]表示位宽=7+1=8位,高位在前,低位在后
	
	//assign 连续赋值语句
	//always@()一旦出现括号中的内容,就开始执行begin和end之间的语句
	always@(a,b,c)begin
	   case({a,b,c})//case语法和C语言差不多  //{}表示位拼接,这里是把abc三个一位的拼接成三位的信号
		   3'b000:out = 8'b0000_0001;//3位bit 000 //_是占位符,不影响逻辑,只是为了好看
			3'b001:out = 8'b0000_0010;
			3'b010:out = 8'b0000_0100;
			3'b011:out = 8'b0000_1000;
			3'b100:out = 8'b0001_0000;
			3'b101:out = 8'b0010_0000;
			3'b110:out = 8'b0100_0000;
			3'b111:out = 8'b1000_0000;
			//如果注释了上一句 可以写default:out = 8'b1000_0000;
			//两种写法结果相同 同C语言
		endcase
	end

endmodule 
  • 但是会出现如下报错
    Verilog HDL学习笔记(1)_LED_3-8/4-16译码器_第1张图片
  • 报错原因:没有定义output的类型,这里因为使用了always@赋值,所以只能把输出定义为reg
  • 只需要在output声明下面加一句:
//输出端口
	output [7:0]out;//[7:0]表示位宽=7+1=8位,高位在前,低位在后
	reg [7:0]out;
	
	//assign 连续赋值语句

编译结果分析

Verilog HDL学习笔记(1)_LED_3-8/4-16译码器_第2张图片

仿真文件

`timescale 1ns/1ns

module my3_8_tb; 
   
	//激励信号源 reg
	reg a;
	reg b;
	reg c;
	
	//观测信号、输出信号 wire
	wire [7:0] out;
	
	my3_8 u1( //复制粘贴待仿真文件名及端口列表
	.a(a),
	.b(b),
	.c(c),
	.out(out)
	);
	
	initial begin 
	   a = 0; b = 0; c = 0;
		#200;
	   a = 0; b = 0; c = 1;
		#200;
		a = 0; b = 1; c = 0;
		#200;
	   a = 0; b = 1; c = 1;
		#200;
		a = 1; b = 0; c = 0;
		#200;
	   a = 1; b = 0; c = 1;
		#200;
		a = 1; b = 1; c = 0;
		#200;
	   a = 1; b = 1; c = 1;
		#200;
		$stop;
	end
	
endmodule 

时域仿真误差分析

  • 0000_0001翻转为0000_0010时需要变化两位,而这两位变化的速度不同,所以会出现一个极短的暂态0000_0000
    Verilog HDL学习笔记(1)_LED_3-8/4-16译码器_第3张图片

4-16 译码器

类比3-8译码器,不再赘述

易错点总结

  1. 新建工程时要避免工程名以数字开头,如3-8译码器工程名不可以写“3_8code”,可以写“my3_8code”
  2. reg是寄存器类型的输出,如果使用了always@进行赋值,只能把输出定义为reg型
  3. 输出类型有两种reg–寄存器型,wire–线网型

你可能感兴趣的:(数字电路)