- 多路选择器:
设计定义:将使用按键控制LED的亮灭抽象为多路选择器,两路信号分别输出高低电平,一个选择信号用来控制哪路输出。注意激励信号与检测信号是在用户设计的模块之外的!代码:
module LED_test(a,b,key,led);
//问题1:端口列表必须得写全,省略是system verilog的写法
input wire a;
input wire b;//两路信号,分别为高电平和低电平
input wire key;//按键
output wire led;
assign led = (key==1)?a:b;
endmodule
易错点:模块端口列表需要写出输入输出端口,省略端口是System Verilog的写法,不要混淆。
testbench:
`timescale 1ns/1ps
module ledtest_bench;
//激励信号定义,与模块的输入相连
reg signal_a;
reg signal_b;
reg signal_c;
//待检测信号定义,与模块的输出相连
wire led;
//例化待测试模块
LED_test U1(.a(signal_a),.b(signal_b),.key(signal_c),.led(led));
//产生激励
initial begin
#0;
signal_a=0; signal_b=0; signal_c=0;
#100; //问题2:延时也是一个语句!
signal_a=1; signal_b=0; signal_c=0;//a高电平,b低电平
#100;
signal_a=1; signal_b=0; signal_c=1;
#100;
$stop;
end
endmodule
易错点1:延时也是语句,需要加“;”。
易错点2:激励信号是reg类型!!检测信号是wire型!!!与综合代码中的端口类型定义是不一致的,甚至可能是相反的。
- 仿真时的注意事项:
进行仿真前,如果是想在quartus中直接启动modelsim的功能仿真和时序仿真,则需要将工程的testbench仿真程序放入路径中,设置步骤:assignments-settings-EDA tools settings-simulation-设置工具名字以及testbench文件的路径,如果testbench是与工程文件夹放在一起的话,则每一次仿真时都需要选择路径,找到要仿真的testbench文件。
上图是门级仿真(时序仿真)时的设置,slow指出仿真速度是慢速的,速度等级7,芯片内核电压是1.2v,,温度是极限温度100°C时的时序仿真(考虑了门电路延时)。
仿真过程中,使用这些工具来观察延时情况(暂态的持续时间)。
- 3_8译码器
代码:
module decoder3_8(a,b,c,out);
input wire a;
input wire b;
input wire c;
output reg [7:0] out;
always@(*) begin
case({a,b,c})
3'b000:out = 8'b0000_0001;
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;
endcase
end
endmodule
testbench:
`timescale 1ns/1ps
module decoder38_testbench;
//激励信号与检测信号
reg signal_a; //激励信号一定是reg型!!!
reg signal_b;
reg signal_c;
wire [7:0]out; //检测信号一定是wire型!!!
//例化待测试模块
decoder3_8 U1(.a(signal_a),.b(signal_b),.c(signal_c),.out(out));
//施加激励过程
initial begin
#0;
signal_a = 0;signal_b =0;signal_c =0;//通常是clock和rst信号
#20;
signal_a = 0;signal_b =0;signal_c =1;
#20;
signal_a = 0;signal_b =1;signal_c =0;
#20;
signal_a = 0;signal_b =1;signal_c =1;
#20;
signal_a = 1;signal_b =0;signal_c =0;
#20;
signal_a = 1;signal_b =0;signal_c =1;
#20;
signal_a = 1;signal_b =1;signal_c =0;
#20;
signal_a = 1;signal_b =1;signal_c =1;
#20; //最后一个信号持续20个时间单位,不要忘记这最后一个延时
$stop; //激励终止
end
endmodule
- 观察RTL图:来判断case生成锁存器的条件:
当综合模块的代码为上面的代码时,即case语句的条件选项8种都列出来了,则不会生成锁存器,或者去掉几种条件选项,换成default语句,也不会生成锁存器,如下图一。
而去掉一些条件选项,并且不加default语句时,则会生成锁存器,如下图二。
这里打破了我之前的理解,我之前以为即使写满case语句的8种条件(0-7),条件依然是不完备的,我以为还存在一些位为x或者z的情况,所以还得写default语句,否则还是会生成锁存器latch。现在确定了,case语句的条件选项不考虑x和z的选项,即只要条件选项列满了所有0和1的可能组合,就不会生成锁存器!!!(而casex里面的位x或z则是无关位,也不考虑,遇到再补充。)
8种条件选项列完或加default语句生成的电路
条件选项不完备生成的带锁存器的电路
补充,时序仿真时的变换过程,体会一下电路的延时导致的问题:
从0000_0001→0000_0010的变化过程存在暂态,这是一个不稳定的情况,如果后面的芯片接收信号非常灵敏的话,则暂态会导致错误,解决办法在后面。
Over!!