虚拟项目——计数器的verilog实现
2015-10-27 17:57
375 查看
在做这个虚拟项目之前虽然也有参加有关的培训,但如此完整、正规的进行还是第一次。
首先来说一说我所做项目的要求,简单来讲就是在各种条件允许的情况下控制一个寄存器进行向上或向下的计数。当达到门限值的时候进入报警系统,产生一个信号输出持续八个单位并清零寄存器。这个项目的难点在于满足文档要求的同时还要使得报警装置与其相配。再有一个就是testbench的书写,要考虑各种可能出现的错误(源代码与testbench的书写风格完全不同)。
下面说一下在做项目过程中所得到的一些经验。
在写源代码的过程中:尽量用状态机写,刚开始本以为这么简单的功能只用一个always块就够了而且当时用的是quartus写的(quartus不同always块触发条件相同时就报错,这样就没法写状态机了)。但在老师的要求下用状态机重写的时候发现了很多问题:首先状态机的时序与组合逻辑是分离开的,这样有利于条件执行步骤的分离。而只是一个always块只是按着时间的顺序走,很容易遗漏东西,而且在以后的检查过程中很难检查出来;在定下基本的书写风格之后,要仔细研究要求文档,尽量做到完成每一步之后该怎么办,同时确认每一步的执行是否符合要求。直到最后的波形检验的时候仍然能发现与同队其他人功能上有出入的地方;在删减某个变量的时候用查找功能确认逻辑遗漏,不然很容易就发现波形走到莫名其妙。
对于testbench来说,首先要明确它的功能:首先是机遇源代码激励信号;其次是检验执行过程是否有误。前者通过initial和always块完成,后者则通过各式各样的task来实现,目标明确才能做好。这里主要想说一点就是对于某个信号的控制及波形的选择最好是在一个块里完成,以便在执行的过程中不冲突,也便于之后的检查。
最后就是对于波形的检测,通过对testbench和被测代码的仿真通过波形图来确认功能的实现,在遇到问题后要考虑其中的问题,既可能是原来代码有问题也有可能是testbench的问题,这里要想一个侦探一样的通过蛛丝马迹开确定问题所在,并找到解决方法。在检验的过程中我习惯于把所有的信号都列出来以便于查找的过程中没有遗漏,但考虑到之后功能的复杂化,想到的办法是对各个块进行命名,这样便能准确的拉出所有想要的信号,其可行性还有待实践。
计数器代码:
testbench代码:
验证后所得实验图:
思考与总结
目前对于代码的注释还有很大的问题,而且端口、寄存器名称都是老师预先给的。距离独立设计或者是真正的上手还远远不够,同时状态机、一些基本的语法还不是很熟练的掌握,希望能在以后的学习中逐渐改变才行。
首先来说一说我所做项目的要求,简单来讲就是在各种条件允许的情况下控制一个寄存器进行向上或向下的计数。当达到门限值的时候进入报警系统,产生一个信号输出持续八个单位并清零寄存器。这个项目的难点在于满足文档要求的同时还要使得报警装置与其相配。再有一个就是testbench的书写,要考虑各种可能出现的错误(源代码与testbench的书写风格完全不同)。
下面说一下在做项目过程中所得到的一些经验。
在写源代码的过程中:尽量用状态机写,刚开始本以为这么简单的功能只用一个always块就够了而且当时用的是quartus写的(quartus不同always块触发条件相同时就报错,这样就没法写状态机了)。但在老师的要求下用状态机重写的时候发现了很多问题:首先状态机的时序与组合逻辑是分离开的,这样有利于条件执行步骤的分离。而只是一个always块只是按着时间的顺序走,很容易遗漏东西,而且在以后的检查过程中很难检查出来;在定下基本的书写风格之后,要仔细研究要求文档,尽量做到完成每一步之后该怎么办,同时确认每一步的执行是否符合要求。直到最后的波形检验的时候仍然能发现与同队其他人功能上有出入的地方;在删减某个变量的时候用查找功能确认逻辑遗漏,不然很容易就发现波形走到莫名其妙。
对于testbench来说,首先要明确它的功能:首先是机遇源代码激励信号;其次是检验执行过程是否有误。前者通过initial和always块完成,后者则通过各式各样的task来实现,目标明确才能做好。这里主要想说一点就是对于某个信号的控制及波形的选择最好是在一个块里完成,以便在执行的过程中不冲突,也便于之后的检查。
最后就是对于波形的检测,通过对testbench和被测代码的仿真通过波形图来确认功能的实现,在遇到问题后要考虑其中的问题,既可能是原来代码有问题也有可能是testbench的问题,这里要想一个侦探一样的通过蛛丝马迹开确定问题所在,并找到解决方法。在检验的过程中我习惯于把所有的信号都列出来以便于查找的过程中没有遗漏,但考虑到之后功能的复杂化,想到的办法是对各个块进行命名,这样便能准确的拉出所有想要的信号,其可行性还有待实践。
计数器代码:
<span style="font-family: Arial, Helvetica, sans-serif;">module cntnub(</span>
//reset & clk// rst, clk, //parameter// start, cnt_type, up_gate, down_gate, //output signal// cpu_irq ); //clk & reset// input rst; input clk; //input signal// input start; input cnt_type; input[7:0] up_gate; input[7:0] down_gate; //output// output cpu_irq; reg[2:0] current_state; reg[2:0] next_state; //save the count data// reg[7:0] count_data; reg cpu_irq; reg[3:0] irq_cnt; parameter s_idle=0; parameter s_1=1; parameter s_11=2; parameter s_12=3; parameter s_2=4; //this is a always which let the module stop and rsest when the rst is on// //if the rst is being on the state will stay s_idle// //the current_state will run next_state unless the rst is off // always@(posedge clk) begin if(!rst) current_state<=s_idle; else current_state<=next_state; end //this is an always which is drscribed the combinatorial logic// //the current_state will run s_1 unless !state// //if the count_data is the gate ,the cpu_irq will be on and keep on 8 clk// always@(*) begin if(rst) begin case(current_state) s_idle: if(start) next_state=s_1; else next_state=s_idle; s_1://check the datat up or count down// if(cnt_type) next_state=s_11; else next_state=s_12; s_11://check the data is the up_gate// begin if(count_data==up_gate) cpu_irq=1; else next_state=s_11; end s_12://check the data is the down_gate// begin if(count_data==down_gate) cpu_irq=1; else next_state=s_12; end default: next_state=s_idle; endcase end end //keep the cpu_irq for 8 clk// //make sure the codition which the state go// always@(posedge cpu_irq or negedge rst or posedge clk) begin if(!rst) irq_cnt<=0; else if(cpu_irq) begin irq_cnt<=0; if(clk) irq_cnt<=irq_cnt+1; if(irq_cnt==8)begin cpu_irq<=0; irq_cnt<=0; count_data<=0; end end end //describe the temporal logic // //make sure the step what you do// always@(posedge clk or negedge rst) begin if(!rst) next_state<=s_idle; else begin case(next_state) s_idle: begin cpu_irq<=0; count_data<=0; end s_11://data up count// begin count_data<=count_data+1; end s_12://data down count// begin count_data<=count_data-1; end default next_state<=s_idle; endcase end end endmodule
testbench代码:
`define tc01_00 module top( ); //clk and rst// reg clk; reg rst; //choice data count up or down// reg cnt_type; reg start;//drive cntnub count// reg [7:0] up_gate; //up warning// reg [7:0] down_gate;//down warning// reg [7:0] cnt_test; wire cpu_irq;//waining output signal// parameter clk_time=10; //sampling the system timing// integer timea; integer timeb; //count the en_start timing// integer cnt; //count test number// integer run_number; always #clk_time clk = ~clk; //time cycle 20ns// //intital start condition// initial begin up_gate = 8'h50; down_gate = 8'hef; clk = 1'b0; rst = 1'b0; #10; rst = 1'b1; end //module instantiation// cntnub DUT( .rst(rst), .clk(clk), .start(start), .up_gate(up_gate), .down_gate(down_gate), .cpu_irq(cpu_irq), .cnt_type(cnt_type) ); //make the tesk run when every posclk// initial begin @(posedge rst) begin end fork irq_check(); timer_check(); cnt_type<=0; join end //run `define // initial begin @(posedge clk)begin end `ifdef tc01_00 tc01_00(); //start the tesk tc01_00// `endif end //drive signal,cnt:the time of en_start// task tc01_00; begin for(run_number=0; run_number<10; run_number=run_number+1) begin for(cnt=0; cnt<1000; cnt=cnt + 1) begin @(posedge clk)begin end start <= 1'b1; end start <= 1'b0; repeat(100) begin @(posedge clk)begin end end end $finish; end endtask //check the cpu_irq timeing is 8clk// task irq_check; begin forever begin //count the time between cou_irq up and down// @(posedge cpu_irq) begin timea = $time; end @(negedge cpu_irq) begin timeb =$time; end if((timeb-timea)/(2*clk_time) != 8) begin $display("The Timer cpu_irq output cycle not equal to 8 clock"); $finish; end else begin $display("The Timer cpu_irq output cycle is equal to 8 clock"); end end end endtask //check the timer cou_irq output is right// task timer_check; begin forever begin @(posedge clk) begin if(start) begin if(cnt_type) begin @(negedge cpu_irq) begin up_gate<=up_gate+1; end cnt_test = cnt_test + 1; end else begin cnt_test = cnt_test - 1; @(negedge cpu_irq) begin down_gate<=down_gate-1; end end end else begin cnt_test = 0; end if(cnt_type) begin if(cnt < up_gate && cpu_irq) begin //check the timer when up_cout// $display("The Timer cpu_irq output is Wrong !!!!!"); $finish; end else if(cnt_test == up_gate+2 && !cpu_irq) begin $display("The Timer cpu_irq output is Wrong !!!!!"); $finish; end else if (cnt_test > (up_gate+9) && cpu_irq) begin $display("The Timer cpu_irq output is Wrong !!!!!"); $finish; end end else begin//check the tier when down_count// if(cnt_test > down_gate && cpu_irq) begin $display("The Timer cpu_irq output is Wrong !!!!!"); $finish; end else if(cnt_test == down_gate-2 && !cpu_irq) begin $display("The Timer cpu_irq output is Wrong !!!!!"); $finish; end else if(cnt_test < (down_gate-9) && cpu_irq) begin $display("The Timer cpu_irq output is Wrong !!!!!"); $finish; end end end end end endtask endmodule
验证后所得实验图:
思考与总结
目前对于代码的注释还有很大的问题,而且端口、寄存器名称都是老师预先给的。距离独立设计或者是真正的上手还远远不够,同时状态机、一些基本的语法还不是很熟练的掌握,希望能在以后的学习中逐渐改变才行。
相关文章推荐
- 输入流InputStream的reset()和mark()方法注意事项
- Java:抽象类abstract和接口Interface
- (职员)2015-10-27 星期二 日志
- [jquery-delegate] iphone_4s _iphone _5c_中不兼容jQuery delegate 事件(does not wok)
- hdoj 3861 The King’s Problem【强连通缩点建图&&最小路径覆盖】
- navicat 导出导入数据
- 基于FP-Tree的关联规则FP-Growth推荐算法基本思想
- 解决 Gradle DSL method not found: 'android()'
- IOS 验证码
- 黑马程序员—基础—设计一个方法,用于获取一个字符串中指定子串出现的次数,
- iftop安装
- java编码解码乱码问题
- android studio 怎么回到欢迎界面
- 移动CRMapp项目总结
- 非洲儿童(南阳oj1036)(馋)
- Xcode 7如何免费真机调试iOS应用
- 制作百度地图
- 百度语音识别demo:去掉离线识别功能
- UIImageView变灰
- 在linux环境下尝试使用gcc编译一个程序,并验证-E\-S\-c选项