(电工基地课程笔记)基本时序逻辑

7 篇文章 0 订阅
7 篇文章 1 订阅

今天重新复习了D触发器。

D触发器就是个真正的reg,时钟的有效沿到来时,输出值更新为输入值,其他时候输出值保持不变,与输入无关

reg q;

always@(posedge clk)begin

  q<=d;

end

//clk是非常重要的概念

//低端FPGA如果跑软核,一般时钟频率100MHz

 

1.方波越窄,就要用越高频的正弦信号叠加

 

2.时钟是FPGA里面最繁忙的信号


3.当上升沿来临时,把d的值给q


4.上升沿是posedge,下降沿negedge

5.


   Synchronous reset              Asynchronous reset

同步复位:听时钟的话;

异步复位:不听时钟的话


6.reset表示高有效,reset_n表示低有效//养成良好的代码习惯!

7.但是时钟是FPGA最重要的东西,所以一般少用异步复位,多用同步复位

 

8.!!!如果没有重要的特殊功能,一般用同步复位

 

1.D触发器要能锁存正确的数据,要求:

 I.数据在时钟有效沿来到之前,必须稳定一段时间,称为“建立时间”Tsu

 II.数据在时钟有效沿来到之后,必须稳定一段时间,称为“保持时间”TH

2.注意,Modesim的功能仿真,D触发器都是理想的

 I.不需要建立和保持时间,如果数据变化与时钟有效沿同时出现,将锁存到数据变化后的新值(e.g.1),有因果关系的除外(e.g.2

 

II.因此,建议在功能仿真时,将时钟与数据变化错开半个时钟周期,以免与实际情况混淆

III.仿真时,需要对D触发器赋初值,理想的D触发器初始值为X

  两种方法1.initial 2.复位reset

(Flip-Flop)

1.自学格雷码计数、BCD码使用方法(2016.7.7需要学习数字电路)

 module xxx(……);

……

   reg [7:0] q;

   always@(posedge clk) begin

      q <= q + 8b1;

   end

 

   reg [7:0] gray;

   always@(posedge clk) begin

      gray <= q ^ (q >> 1);

   end

……

Endmodule

2.练习1:描述JK触发器,并仿真,注意使用initial块对寄存器赋初始值

module JKtest(input clk,

   input J,input K,output reg Q

    );

    initial Q<=1;

    reg d;

    always@(posedge clk)

    begin

      d=(J & ~Q )| (~K & Q );

      Q<=d;

    end

endmodule

 

激励块://根据自己需要自行设计

module testbench  ;

 

  wire   Q   ; //output reg型对应是wire型!!

  reg    J   ;

  reg    clk   ;

  reg    K   ;

  JKtest  

   DUT  (

       .Q (Q ) ,

      .J (J ) ,

      .clk (clk ) ,

      .K (K ) );

initial

begin

 clk = 1'b0;

 J=1'b0;

 K=1'b0;

 end

 always

  #10 clk=~clk;

  always

    #15 J=~J;

      always

    #20 K=~K;

 

  initial

   #1000 $stop;

endmodule

 

1.T触发器

计数器

1.八位计数器(不一定自成模块)

module XXX(...)

...

  reg[9:0] cnt;

always@(posedge clk) begin

  cnt <=cnt + 10’b1;

end

...

endmodule

 

2.带有复位

...

Reg [9:0] cnt;

always@(posedge clk) begin

  If(rst) cnt <=10’b0;

Else cnt <=cnt + 10’b1;

End

...

 

3.计到特定值(模)

 ...

   Reg[9:0] cnt;

always@(posedge clk) begin

  If(cnt< 10’d999) cnt<=cnt + 10’b1;

  Else cnt <=10’b0;

End

...

Tips:这可以实现一个数字域的锯齿波(单极性)

4.计到特定范围

...

  Reg signed [9:0] cnt;

always@(posedge clk) begin

  If(cnt < 10’sd499) cnt <= cnt +10’sd1;

Else cnt <= -10’sd500;

End

...

Tips:这可以实现一个数字域的锯齿波(双极性)

练习2:编写testbench,仿仿看带有复位输入、进位输出的模M计数器

 编写感想:Modesim自动生成固然方便,但是Function定义就不会自动加上,让我迷惑了好久

`timescale 100ns/1ns
module testbench  ; 

parameter M  = 60 ; 
  wire   [Log2(M-1) : 0]cnt   ; 
  reg    rst   ; 
  wire    co   ; 
  reg    clk   ; 
   function integer Log2(input integer x);
    for(Log2 = 0; x > 1; x = x >> 1) 
  
       Log2 = Log2 + 1;
 
  endfunction
  initial clk=1'b0;
  counterM    #( M  )
   DUT  ( 
       .cnt (cnt ) ,
      .rst (rst ) ,
      .co (co ) ,
      .clk (clk ) );  
      always
     #10 clk=~clk;
initial begin
  rst=1'b0;
  #1000 rst=1'b1;
  
end
endmodule


 

分频(很大的坑来了啊)

问题:50MHz的时钟下,如果想让一个计数器每毫秒计一次怎么做?

可以用一个模50000的计数器(每毫秒计一圈)的最高位作为时钟!?

不行!!但凡在FPGA用到时钟必须谨慎,时钟在FPGA是神圣的,不能随便乱用。要求大家,写always块时,用到的时钟模块,必须用同一个clk!!(特殊情况以后再学)

 

可以用使能来做 ,都是同一个clk

module XXX(……);

……

   reg [15:0] cnt50k;

   always@(posedge clk) begin

      if(cnt50k < 16d49999)

         cnt50k <= cnt50k + 16b1;

      else

         cnt50k <= 16b0;

   end

   wire enPer1ms = (cnt50k == 16d49999);//每毫秒一个高电平

   reg [9:0] cntPer1ms;

   always@(posedge clk) begin

      if(enPer1ms)

         cntPer1ms <= cntPer1ms + 10b1;

//

   end

……

endmodule

 

2.用于传递事件的使能

编写testbench,仿仿看,注意不要“仿一天”,改为50Hz26’d49

3.使能去抖

正确的做法,先把key的每个下跳沿处理为单个使能信号

 

module XXX(input key, ……);//并没有用两个reg,而使用了两位的寄存器

   reg [1:0] keyDly;

   always@(posedge clk) begin

      keyDly <= {keyDly[0], key};//位拼接,keyDly0】赋给了高位

   end

   wire keyPress = (keyDly == 2b10);

   reg [9:0] cntKey;

   always@(posedge clk) begin

      if(keyPress)

         cntKey <= cntKey + 10b1;

   end

……

endmodule

 

Tips:复习位拼接操作符{}

位拼接操作符可以将多个操作数连接起来,组成一个操作数。拼接操作符的每个操作数必须是有确定位宽的数,这是由于为了确定拼接结果的位宽,必须知道每个操作数的位宽,因此无位宽的数不能作为拼接操作符的操作数

E.g.

//a=1’b1,b=2’b00,c=2’b10,d=3’b110

Y={b , c}//结果为4b0010

Y={a , b , c , d, 3’b001}//结果为11’b10010110001

Y={a,b[0],c[1]}//结果为3b101

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值