verilog入门实例<一>分频器,信号灯

verilog入门实例一

  1. 分频器设计,要求:对输入时钟clk,进行分2、5、10分频。例如输入时钟50Mhz,输出时钟就是25、10、5Mhz。
    主要思路:
     偶数分频:假设偶数为EVEN,对时钟信号周期进行计数,则先写一个模(EVEN)的计数器,只要计数至EVEN-1则使输出信号翻转,便形成了偶数分频。
     奇数分频:由两个信号作或运算而成。假设奇数为ODD。第一个信号,以时钟信号的上跳沿进行计数,形成一个模(ODD)的计数器,令计数至0,1,2...(EVEN-3)/2全部为高电平,其他为低电平,形成一个占空比不为0.5的信号。第二个信号,以时钟的下跳沿进行计数,形成一个模(ODD)的计数器令计数至0,1,2...(EVEN-1)/2全部为高电平,其他为低电平,形成一个占空比不为0.5的信号。这两个信号做或运算则可形成奇数分频。举例:5分频。以时钟上跳沿计数,计数为0,1时为高电平,计数为2,3,4为低电平,如此形成一个信号1。同理以时钟下跳沿进行计数,计数为0,1时为高电平,计数为2,3,4为低电平,如此形成一个信号2。两个信号做或运算可以形成奇数分频信号。
module divider(
    input clk;
    input rst_n;
    output clk_div2;
    output clk_div5;
    output clk_div10
);
    reg [3:0]cnt1;
    reg [3:0]cnt2;
    reg [3:0]cnt3;
    
 reg clk_div51,clk_div52;
    
    parameter NUM_DIV_ODD ==5;
    parameter NUM_DIV_EVEN ==10;
    
    //二分频
    always@(posedge clk or negedge rst_n)
        begin
            if(!rst_n)
                clk_div2 <= 1'b0;
            else 
                clk_div2 <= ~clk_div2;
        end
    
    //奇数五分频由两个占空比为0.4的信号相和而成
    
    //第一个上跳沿计数的信号clk_div51
    always@(posedge clk or negedge rst_n)
        begin
        	if(!rst_n)
                cnt1 <= 1'b0;
            else if (cnt < NUM_DIV - 1)
                cnt1 <= cnt1+1'b1;
            else
                cnt1 <= 1'b0;
        end
    
    always@(posedge clk or negedge rst_n)
        begin
            if(!rst_n)
               clk_div51 <= 1'b0;
            else if(cnt1<NUM_DIV/2)
                clk_div51 <=1'b1;
            else
                clk_div51 <= 1'b0;
        end
    
    //第二个下跳沿计数的信号clk_div52
    always@(negedge clk or negedge rst_n)
        begin
            if(!rst_n)
                cnt2 <= 1'b0;
            else if (cnt < NUM_DIV -1 )
                cnt2 <= cnt2 + 1'b1;
            else
                cnt <= 1'b0;
        end
    
    always@(negedge clk or negedge rst_n)
        begin
            if(!rst_n)
                clk_div52 <= 1'b0;
            else if (cnt2 < NUM_DIV/2)
                clk_div52 <= 1'b1;
            else
                clk_div52 <= 1'b0;
            
        end
    assign clk_div5 <= clk_div51 | clk_div52;
    
    //十分频
    always@(posedge clk or negedge rst_n)
        begin
            if (!rst_n)
                begin
                	clk_div10 <= 1'b0;
            		cnt3 <=0;
                end
            else if (cnt3 < NUM_DIV_EVEN/2)
                begin
                    cnt3 <= cnt3 + 1'b1;
                    clk_div10 <= clk_div10;
                end
            else
                begin
                    cnt3 <= 1'b0;
                    clk_div10 <= ~clk_div10;
                end
        end
    

endmodule

testbench

`timescale 1ns/1ps
module tb_divider;
    reg clk;
    reg rst_n;
    
    wire clk_div2;
    wire clk_div5;
    wire clk_div10;
    
    parameter TIME = 20;
    divider uut(
        .clk(clk),
        .rst_div(rst_n),
        .clk_div2(clk_div2),
        .clk_div5(clk_div5),
        .clk_div10(clk_div10)
    );
    
    always@ #(TIME/2) clk = ~clk;
    
    initial
        begin
            clk = 0;
            rst_n = 0;
            #TIME rst_n = 1;
            #(TiME * 80000) $finish;
        end
endmodule

仿真效果:

其中clk_div51和clk_div52是奇数5分频的信号1和信号2。

  1. 信号灯
    要求:东西方向和南北方向各有四盏灯,分别为左拐灯、绿灯、黄灯和红灯
    东西方向信号灯的时间为:红灯55s,黄灯5s,绿灯40s,左拐灯15s;
    南北方向信号灯的时间为:红灯65,黄灯5,绿灯30,左拐灯15s;

思路:把信号灯分为以上7种状态,由于有时间要求,则以5s记一次数,信号灯跑完整个过程,需要120s,则形成一个模24计数器,下面流程图中白色中的数字就是计数值。

真值表:

Light_ns(南北信号灯) Light_ew(东西信号灯) 状态
左 绿 黄 红 左 绿 黄 红
0 0 1 0 0 0 1 0 IDLE
1 0 0 0 0 0 0 1 S1
0 1 0 0 0 0 0 1 S2
0 0 1 0 0 0 0 1 S3
0 0 0 1 1 0 0 0 S4
0 0 0 1 0 1 0 0 S5
0 0 0 1 0 0 1 0 S6

流程图:

design

module signal_light(clk,rst_n,light_ns,light_ew,count);
    input clk,rst_n;
    output light_ns,light_ew;//ns:north sourth,ew:east west
    output count;
    //output clk_count;
    reg[3:0]light_ns,light_ew;
    reg[4:0]count;
    reg[2:0]current_state,next_state;

    
    
    parameter IDLE=3'b000;
    parameter S1=3'b001;
    parameter S2=3'b010;
    parameter S3=3'b011;
    parameter S4=3'b100;
    parameter S5=3'b101;
    parameter S6=3'b110;

   // reg clk_count;
    //reg count1;
    //parameter T=9'd250000000;
/*
 always@(posedge clk or negedge rst_n)
        begin
            if (!rst_n)
                begin
                	clk_count <= 1'b0;
            		cnt1 <=0;
                end
            else if (cnt1 < T/2)
                begin
                    cnt1 <= cnt1 + 1'b1;
                    clk_count <= clk_count;
                end
            else
                begin
                    cnt1 <= 1'b0;
                    clk_count <= ~clk_count;
                end
        end
    */
    //counter
    always@(posedge clk or negedge rst_n)
        begin
            if(!rst_n)
                count<=1'b0;
            else if(count==5'b10111)
                count<=1'd0;
            else
                count<=count+1'b1;
                
        end
    
    always@(posedge clk or negedge rst_n)
        begin
            if(!rst_n)
                current_state<=IDLE;
            else
                current_state<=next_state;
        end
    
    always@(*)
        begin
            case(current_state)
                IDLE:if(!count)next_state=S1;
              		 else next_state=IDLE;
                
                S1:if(count==2)next_state=S2;
                   else next_state=S3;
                
                S2:if(count==9)next_state=S3;
                   else next_state=S2;
                
                S3:begin
			if(count==3)next_state=S2;
                   	else 
                           begin
                               if(count==10)next_state=S4;
                               else next_state=S3;
			    end
		   end
                
                S4:if(count==13)next_state=S6;
                   else next_state=S4;
                
                S5:if(count==22)next_state=S6;
                   else next_state=S5;
                
                S6:begin
			if(count==14)next_state=S5;
                           else 
                                 begin
                                       if(count==23)next_state=S1;
                                       else next_state=S6;
                                 end
                end
                
             default:next_state=IDLE;
            endcase
         end

    always@(posedge clk or negedge rst_n)
        begin
            if(!rst_n)
                begin
                    light_ns<=4'b0010;
                    light_ew<=4'b0010;
                end
            else 
		case(next_state)
                IDLE   :begin
			light_ns<=4'b0010;
			light_ew<=4'b0010;
			end
                S1     :begin
			light_ns<=4'b1000;
                        light_ew<=4'b0001;
			end
                S2     :begin
			light_ns<=4'b0100;
                        light_ew<=4'b0001;
			end
                S3     :begin
			light_ns<=4'b0010;
                        light_ew<=4'b0001;
			end
                S4     :begin
		light_ns<=4'b0001;
                        light_ew<=4'b1000;
			end
                S5     :begin
			light_ns<=4'b0001;
                        light_ew<=4'b0100;
			end
                S6     :begin
			light_ns<=4'b0001;
                        light_ew<=4'b0010;
			end
                default:begin
			light_ns<=4'b0010;
                        light_ew<=4'b0010;
			end
            endcase
        end
    
endmodule

testbench

`timescale 1ns/1ps
module tb_signal_light;
reg clk;
reg rst_n;

wire [4:0]count;

wire [3:0]light_ew;
wire [3:0]light_ns;
//wire clk_count;

parameter TIME=20;

signal_light uut(
    .clk(clk),
    .rst_n(rst_n),
    .light_ns(light_ns),
    .light_ew(light_ew),
    .count(count)
    //.clk_count(clk_count)
);
 always #10 clk = ~clk;
    
    initial
        begin
            clk = 0;
            rst_n = 0;
            #TIME rst_n = 1;
            //#(TiME * 80000) $finish;
        end
endmodule

仿真结果:

结果中还有一个问题就是未分频,应该是要写一个周期的5s的时钟信号。

posted @   习惯科夫  阅读(709)  评论(0编辑  收藏  举报
编辑推荐:
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
阅读排行:
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.