3.3 信号定义
下面需要将 module 补充完整,首先要做的是定义信号的类型。在这里再次强调,在进行 reg 和 wire 类型判断的时候,总会有多余的联想,比如认为 reg 就是寄存器,wire 是线;或者认为 reg 类型会综合成寄存器,wire 类型不会综合成寄存器。实际上这些与信号是 reg 型还是 wire 型都没有关系。
至简设计法建议不要进行任何联想,只遵从一个规则:“用 always 实现的是 reg 型,其他都是 wire型”。进行信号定义时,除了信号的类型还需要确定信号的位宽。至简设计法在这里分享一个非常实用的获取信号位宽的技巧:打开计算器,点击“查看”,选择“程序员”模式,在“十进制”下输入数字后就会获得对应的信号位宽。
cnt0 是用 always 产生的信号,因此类型为 reg。cnt0 计数的最大值为 50_000_000。如图 3.2- 5 所示,通过计算器可以得知该信号需要用 26 根线表示,即位宽是26位。代码如下所示:
同样的,cnt1 也是用 always 产生的信号,因此类型为 reg。cnt1 计数的最大值为 14,需要用 4根线表示,即位宽是 4 位。编辑状态下输入“Reg4”调用至简设计法模板,补充完整后得到代码表示如下:
add_cnt0 和 end_cnt0 都是用 assign 方式设计的,因此类型为 wire。其值是 0 或者 1,用 1 根线表示即可,即位宽为 1。编辑模式下输入“Wire1”调用模板,补充完整后得到代码表示如下:
add_cnt1 和 end_cnt1 也是用 assign 方式设计的,因此类型为 wire。其值是 0 或者 1,用 1 根线表示即可,即位宽为 1。编辑模式下输入“Wire1”调用模板,补充完整后得到代码表示如下:
led0、led1、led2、led3 是用 always 方式设计的,因此类型为 reg。其值是 0 或者 1,用 1 根线表示即可。编辑模式下输入“Reg1”调用模板,补充完整后得到代码表示如下:
整个代码的设计工作至此已经完成,完整的工程代码如下所示:
下面附上完整代码:
module huxiled( clk , rst_n , led0 , led1 , led2 , led3 ); input clk ; input rst_n ; output led0 ; output led1 ; output led2 ; output led3 ; reg led0 ; reg led1 ; reg led2 ; reg led3 ; reg [ 25:0] cnt0 ; wire add_cnt0 ; wire end_cnt0 ; always @(posedge clk or negedge rst_n) begin if (rst_n==0) begin cnt0 <= 0; end else if(add_cnt0) begin if(end_cnt0) cnt0 <= 0; else cnt0 <= cnt0+1 ; end end assign add_cnt0 = 1; assign end_cnt0 = add_cnt0 && cnt0 == 50000000-1 ; reg [ 3:0] cnt1 ; wire add_cnt1 ; wire end_cnt1 ; always @(posedge clk or negedge rst_n) begin if (rst_n==0) begin cnt1 <= 0; end else if(add_cnt1) begin if(end_cnt1) cnt1 <= 0; else cnt1 <= cnt1+1 ; end end assign add_cnt1 = end_cnt0; assign end_cnt1 = add_cnt1 && cnt1 == 14-1 ; always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin led0<=1; end else if(add_cnt1&&cnt1==1-1)begin led0<=0; end else if(add_cnt1&&cnt1==2-1)begin led0<=1; end end always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin led1<=1; end else if(add_cnt1&&cnt1==3-1)begin led1<=0; end else if(add_cnt1&&cnt1==5-1)begin led1<=1; end end always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin led2<=1; end else if(add_cnt1&&cnt1==6-1)begin led2<=0; end else if(add_cnt1&&cnt1==9-1)begin led2<=1; end end always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin led3<=1; end else if(add_cnt1&&cnt1==10-1)begin led3<=0; end else if(add_cnt1&&cnt1==14-1)begin led3<=1; end end endmodule
第4节 仿真
4.1 编写测试信号
module tb_huxiled; parameter CYCLE = 20000; //因为我用modelsim去仿真的时候,他的信号单位是ps,而实际需要设置20ns,既如此就20ns等价于20000ps reg clk; reg rst_n; wire led0; wire led1; wire led2; wire led3; huxiled uut( .clk (clk) , .rst_n (rst_n), .led0 (led0), .led1 (led1), .led2 (led2), .led3 (led3) ); initial begin clk = 0; forever#(CYCLE/2)begin clk = ~clk; end end initial begin #1 rst_n = 0; #(10*CYCLE); rst_n = 1; end endmodule
4.2 仿真
分析时序信号以后,可以证明满足项目的要求。
第 5 节 综合与上板
4.1新建工程
打开软件 Quartus Ⅱ,点击“File”下拉列表中的 New Project Wzard...新建工程选项,如下图所示。
随后会出现图 3.2-7 所示的 Quartus 新建工程介绍,直接点击“Next”:
此时出现的是工程文件夹、工程名、顶层模块名设置界面,如图 3.2-8 所示。注意目录为:D:/mdy_book/mdyBookHuxiLed,工程名和顶层名为 mdyBookHuxiLed。这里再次进行强调,为了避免初学者使用过程中出现报错情况,强烈建议按照本书的工程名和文件名进行设置,设置完成后点击 Next。
新建工程类型设置选择“Empty project”,如下图所示,然后点击“Next”。
文件添加界面如图 3.2-10 所示,点击右侧的“Add”按钮,选择已经写好的“mdyBookHuxiLed.v”文件,此时文件会在下方显示出来,随后点击“Next”。
芯片型号选择界面如图 3.2-11 所示,选择“Cyclone ⅣE”,在芯片型号选择处选择“EP4CE15F23C8”,之后点击“Next”。