verilog初学篇(二)

这里用第一篇用到的数码管做个简单的秒表,这里说“简单的”,因为初学,就只循环从0到9。完成这个有个准备工作:

1.时钟分频

因为板子的时钟信号不是1s,而是远小于1s,所以要累加多个周期,周期变大,则频率变小,所以叫“分频”。这样的话,就知道要设一个计数器,道理很简单,从0开始,累加到n-1,再加就变回0,同时让新周期信号取反,循环下去,得到的半个周期就变成原来一个周期的n倍,那一个周期就是原来2n倍。

1. 试写变成4倍

开始时写代码如下:

module myclk(
input clk_in,
input rst,
output reg clk_out
);
parameter CNT_4=2;//n=2,2n倍就是4倍
reg [25:0] counter=0;
always @ (posedge clk_in or negedge rst)
if(~rst)
counter<=0;
else
if(counter<CNT_4-1)
counter<=counter+1;
else begin
counter<=0;
clk_out<=~clk_out;
end
endmodule

这里用到一个rst(即reset重置),先说一下rst,rst按键按下后rst=0,否则为1。

另外,同步复位和异步复位其实很简单,想一下如果我按下rst,必然此时是从1到0,是下降沿negedge rst,如果写成always @ (posedge clk or negedge rst),按下按键后肯定是rst=0,即~rst,这时不用管clk,肯定执行if( ~rst)条件下的,这叫异步;而如果写成always @ (posedge clk),虽然按下按键后rst=0,但我clk的上升沿还没到,所以不会立刻有反应,必须等到clk上升沿,这叫同步;

仿真波形图,测试时给定周期变换的clk_in,先给rst一个周期的0相当于按下按键来初始化,之后都为1。关于时钟分频,详细请看:verilog时钟分频设计https://blog.csdn.net/moon9999/article/details/75020355

2.写1s的代码

我这里用板子为50MHz,自然就是50M倍,如下:

module myclk(
input clk_in,
input rst,
output reg clk_1s
);
parameter CNT_1S=25_000_000;//n=25M,2n倍即是50M倍
reg [25:0] counter;
always @ (posedge clk_in or negedge rst)
if(~rst) begin
counter<=0;
clk_1s<=0;
end
else
if(counter<CNT_1S-1)
counter<=counter+1;
else begin
counter<=0;
clk_1s<=~clk_1s;
end
endmodule

2.写秒表

有了上述思想,接下来就按照这个来写秒表:

module shumaguan_jishi(
 input clk,
 input rst,
 output [6:0] light,
 output com0
);
 assign com0=1;
 reg [3:0] num;
 
 myclk myclk(
  .clk_in(clk),
  .rst(rst),
  .clk_1s(clk_1s)
 );
 always @ (posedge clk_1s or negedge rst)
  if(~rst) 
   num<=0;
  else begin
   if(num<9)
    num<=num+1;
   else     
    num<=0;
   end
 shumaguan shumaguan(
  .num(num),
  .light(light)
 );
endmodule

 module myclk(
 input clk_in,
 input rst,
 output reg clk_1s
    );
 parameter CNT_1S=25_000_000;//n=25M,2n倍即是50M倍
 reg [25:0] counter;
 always @ (posedge clk_in or negedge rst)
  if(~rst) begin
   counter<=0;
   clk_1s<=0;
  end
  else
   if(counter<CNT_1S-1)
    counter<=counter+1;
   else begin
    counter<=0;
    clk_1s<=~clk_1s;
   end 
endmodule

module shumaguan(
 input [3:0] num,
 output reg [6:0] light
);
 always @ (num)
  case(num)
   4'h0: light<=7'b1111110;
   4'h1: light<=7'b0110000;
   4'h2: light<=7'b1101101;
   4'h3: light<=7'b1111001;
   4'h4: light<=7'b0110011;
   4'h5: light<=7'b1011011;
   4'h6: light<=7'b1011111;
   4'h7: light<=7'b1110000;
   4'h8: light<=7'b1111111;
   4'h9: light<=7'b1111011;
default: light<=7'b1111110;
  endcase
endmodule

我这里为了练习模块化以及参数传入,把模块分开写了,下面给出一个不分开的,看起来少一些,道理是一样的:

module shumaguan_jishi(
 input clk,
 input rst,
 output reg [6:0] light,
 output com0
);
 assign com0=1;
 parameter CNT_1S=50_000_000;
 reg [25:0] counter;
 reg [3:0] num;
 
 always @ (posedge clk_in or negedge rst)
  if(~rst)  begin
   counter<=0;
   num<=0;
  end
  begin
  else 
   if(counter<CNT_1S-1)
    counter<=counter+1;
   else begin
    counter<=0;
    num<=num+1;
    end
  end 
always @ (num)
  case(num)
   4'h0: light<=7'b1111110;
   4'h1: light<=7'b0110000;
   4'h2: light<=7'b1101101;
   4'h3: light<=7'b1111001;
   4'h4: light<=7'b0110011;
   4'h5: light<=7'b1011011;
   4'h6: light<=7'b1011111;
   4'h7: light<=7'b1110000;
   4'h8: light<=7'b1111111;
   4'h9: light<=7'b1111011;
   default: light<=7'b1111110;
  endcase
endmodule

这里为什么用CNT_1S=50_000_000?因为上面时钟分频取反再取反才是一个周期,才让数加1,这里我直接让数加1,所以就是50M。

第二篇完

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值