赞
踩
8个Led灯以0.5s的的速率循环闪烁,参数化设计并且调用三八译码器模块完成该设计。
三八译码器模块见https://blog.csdn.net/weixin_42454243/article/details/122039239 《小梅哥Xilinx FPGA学习笔记2——三八译码器》
设计文件共两个,一个pipeline_led.v文件;一个decoder_3_8.v文件
module pipeline_led(clk,reset_n,led ); input clk; input reset_n; output [7:0] led; reg [24:0] counter; parameter MCNT = 8'd24999999;//parameter 参数 always@(posedge clk or negedge reset_n) if(!reset_n) counter <=0; else if(counter == MCNT) counter <=0; else counter <=counter +1'b1; reg [2:0] counter2;//用3种状态控制8个led灯 always@(posedge clk or negedge reset_n) if(!reset_n) counter2 <=0; else if(counter == MCNT) counter2 <=counter2 +1'b1; //当counter2 ==7 时,自动溢出变成0 //调用其他的子模块 decoder_3_8 decoder_3_8_inst0( .a(counter2[2]),//是因为decoder_3_8子模块中的位拼接,a是高位,c是最低位 .b(counter2[1]), .c(counter2[0]), .out(led)//使用调用模块的功能,对于在该设计文件输出则不需要定义reg型,是因为在子模块中已经对out进行了reg定义,out在此模块中是隐藏的wire。 ); endmodule
module decoder_3_8(a,b,c,out); input a; input b; input c; output [7:0] out; reg [7:0] out; //output reg [7:0] out //以always块描述的信号 赋值,被赋值的对象必须要定义成reg类型 always@(a,b,c)begin //相当于always@(*) case({a,b,c})//位拼接,{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'd5 :out = 8'b0010_0000 3'b110:out = 8'b0100_0000; 3'b111:out = 8'b1000_0000; endcase end endmodule
下面两个激励文件二选一
`timescale 1ns / 1ns module pipeline_led_tb( ); reg clk; reg reset_n; wire [7:0]led; pipeline_led pipeline_led( .clk(clk), .reset_n(reset_n), .led(led) ); initial clk=1; always #10 clk=~clk;//建立仿真时钟信号 initial begin reset_n=0; #201; reset_n=1; #4000000000; $stop; end endmodule
module pipeline_led_tb( ); reg clk; reg reset_n; wire [7:0]led; defparam pipeline_led_inst0.MCNT=2499;//与设计文件中的参数无关parameter MCNT = 8'd24999999;,这里仿真的值为MCNT=2499; pipeline_led pipeline_led_inst0( .clk(clk), .reset_n(reset_n), .led(led) ); initial clk=1; always #10 clk=~clk; initial begin reset_n=0; #201; reset_n=1; #4000000000; $stop; end endmodule
1.仿真图counter的参数设计是24999,横坐标一个大刻度20us,led灯0.5ms亮一次
parameter MCNT = 8'd24999;//parameter 参数,仿真文件选择第一个文件
2.在testbench中使用defparam,仿真图counter的参数设计是2499,横坐标一个大刻度100us,led灯50us亮一次
3…在testbench中使用defparam,仿真图counter的参数设计是249,横坐标一个大刻度20us,led灯5us亮一次
1.对于在验证功能的时候,缩短时间要对所有包含的语句均进行改写,采用参数化设计,定义一个MCNT参数,可以将其用在程序的所有位置,只需要对一处就行修改,程序所有对应位置值都能得到修改;
//为缩短时间,将下面第一条语句改为第二条语句,模块中的counter==8'd24999999均需要改为counter==8'd24999
// else if(counter==25000000-1)
else if(counter==8'd24999) //缩小仿真时间,验证功能
parameter MCNT = 8'd24999;//parameter 参数
2.对于缩短仿真时间,可以不改变设计文件,在testbench中使用defparam;或者用#例化参数MCNT。
defparam pipeline_led_inst0.MCNT=2499;//注意例化的标签名要有唯一性
pipeline_led pipeline_led_inst0(
.clk(clk),
.reset_n(reset_n),
.led(led)
);
// defparam pipeline_led_inst0.MCNT=24999;
pipeline_led
#(
.MCNT(249)
)
pipeline_led_inst0(
.clk(clk),
.reset_n(reset_n),
.led(led)
);
3.上诉第2条,defparam和#例化参数也可以用在设计文件引用其他子模块中。
//对于decoder_3_8模块进行参数化设计
module decoder_3_8(a,b,c,out);
input a;
input b;
input c;
parameter WIDTH = 15;//parameter 参数,该处参数可以任意设计,因为调用的时候,我们可以修改
output [WIDTH:0] out;
reg [WIDTH:0] out;
//在pipeline_led模块中调用decoder_3_8模块,方法一:
defparam decoder_3_8_inst0.WIDTH=7;//注意例化的标签名要有唯一性
decoder_3_8 decoder_3_8_inst0(
.a(counter2[2]),
.b(counter2[1]),
.c(counter2[0]),
.out(led)
);
//在pipeline_led模块中调用decoder_3_8模块,方法二:
// defparam decoder_3_8_inst0.WIDTH=7;//注意例化的标签名要有唯一性
decoder_3_8
#(
.WIDTH(7)
)
decoder_3_8_inst0(
.a(counter2[2]),
.b(counter2[1]),
.c(counter2[0]),
.out(led)
);
后记:把未知当做好奇,而非恐惧。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。