这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » wenyangzeng 进程贴 数字频率计

共30条 2/3 1 2 3 跳转至
工程师
2012-10-19 21:11:11     打赏
11楼

进程7、按键控制LED
8只按键分别控制8只LED的亮灭。

module key_led(
            CLK,RESET,
            KEY[7:0],
            LED[7:0]
            );
input   CLK;
input   RESET;   
input   [7:0]KEY;
output  [7:0]LED;

reg[7:0] key_rst;
always @(posedge CLK  or negedge RESET)
    if (!RESET) key_rst <= 8'b1111_1111;
    else key_rst <= (KEY[7:0]);
reg[7:0] key_rst_r;  
always @ ( posedge CLK  or negedge RESET )
    if (!RESET) key_rst_r <= 8'b1111_1111;
    else key_rst_r <= key_rst;
wire[7:0] key_an = key_rst_r & ( ~key_rst);

reg[19:0]  cnt;  
always @ (posedge CLK  or negedge RESET)
    if (!RESET) cnt <= 20'd0; 
    else if(key_an) cnt <=20'd0;
    else cnt <= cnt + 1'b1;
 
reg[7:0] low_sw;
always @(posedge CLK  or negedge RESET)
    if (!RESET) low_sw <= 8'b1111_1111;
    else if (cnt == 20'hfffff)    
      low_sw <=(KEY[7:0]);

reg  [7:0] low_sw_r; 
always @ ( posedge CLK  or negedge RESET )
    if (!RESET) low_sw_r <= 8'b1111_1111;
    else low_sw_r <= low_sw;
 
wire[7:0] led_ctrl = low_sw_r[7:0] & ( ~low_sw[7:0]);
reg d1;
reg d2;
reg d3;
reg d4;
reg d5;
reg d6;
reg d7;
reg d8;
 
always @ (posedge CLK or negedge RESET)
    if (!RESET) begin
        d1 <= 1'b0;
        d2 <= 1'b0;
        d3 <= 1'b0;
        d4 <= 1'b0;
        d5 <= 1'b0;
        d6 <= 1'b0;
        d7 <= 1'b0;
        d8 <= 1'b0;
      end
    else begin      
        if ( led_ctrl[0] ) d1 <= ~d1;   
        if ( led_ctrl[1] ) d2 <= ~d2;
        if ( led_ctrl[2] ) d3 <= ~d3;
        if ( led_ctrl[3] ) d4 <= ~d4;   
        if ( led_ctrl[4] ) d5 <= ~d5;
        if ( led_ctrl[5] ) d6 <= ~d6;
        if ( led_ctrl[6] ) d7 <= ~d7;   
        if ( led_ctrl[7] ) d8 <= ~d8;
      end
assign LED[0] = d1 ? 1'b1 : 1'b0;       
assign LED[1] = d2 ? 1'b1 : 1'b0;
assign LED[2] = d3 ? 1'b1 : 1'b0;
assign LED[3] = d4 ? 1'b1 : 1'b0;
assign LED[4] = d5 ? 1'b1 : 1'b0;
assign LED[5] = d6 ? 1'b1 : 1'b0;      
assign LED[6] = d7 ? 1'b1 : 1'b0;
assign LED[7] = d8 ? 1'b1 : 1'b0;
endmodule



                       控制结果:奇数LED亮,偶数LED灭


工程师
2012-10-19 21:18:50     打赏
12楼


 
                                                    引脚分配图

工程师
2012-10-22 20:21:40     打赏
13楼

进程8、LED数码管显示DIP开关状态

设定外设板上8位DIP开关从左到右分别为D7到D0位,开关拨向下时该位为1,向上为0,读取8位开关的0-255状态值显示在3位LED数码管上。
//----------
//顶层文件
//dip_to_led.v
//----------
module dip_to_led
(
  CLK, RSTn,
  Number_Data,
  Row_Scan_Sig, Column_Scan_Sig
);
        input CLK;
  input RSTn;
  input [7:0]Number_Data;
  output [7:0]Row_Scan_Sig;
  output [2:0]Column_Scan_Sig;
  wire [3:0]Hund_Data;
  wire [3:0]Ten_Data;
  wire [3:0]One_Data;
  number_mod_module U1
  (
      .CLK( CLK ),
    .RSTn( RSTn ),
    .Number_Data( Number_Data ),
    .Hund_Data ( Hund_Data ),
    .Ten_Data( Ten_Data ),
    .One_Data( One_Data )
  );
  wire [7:0]Hund_SMG_Data;
  wire [7:0]Ten_SMG_Data;
  wire [7:0]One_SMG_Data;
  smg_encoder_module U2
  (
      .CLK( CLK ),
    .RSTn( RSTn ),
    .Hund_Data( Hund_Data ),
    .Ten_Data( Ten_Data ),
    .One_Data( One_Data ),
   
    .Hund_SMG_Data( Hund_SMG_Data ),
    .Ten_SMG_Data( Ten_SMG_Data ),
    .One_SMG_Data( One_SMG_Data )
 );
  smg_scan_module U3
  (
      .CLK( CLK ),
    .RSTn( RSTn ),
    .Hund_SMG_Data(Hund_SMG_Data ),
    .Ten_SMG_Data( Ten_SMG_Data ),
    .One_SMG_Data( One_SMG_Data ),
    .Row_Scan_Sig( Row_Scan_Sig ),
    .Column_Scan_Sig( Column_Scan_Sig )
  );
endmodule
//-----------------
//smg_scan_module.v
//----------------
module smg_scan_module
(
 CLK,RSTn,
 Hund_SMG_Data,Ten_SMG_Data,One_SMG_Data,
 Row_Scan_Sig,Column_Scan_Sig
 
);
 input CLK;
 input RSTn;
 input [7:0] Hund_SMG_Data;
 input [7:0] Ten_SMG_Data;
 input [7:0] One_SMG_Data;
 output [7:0]Row_Scan_Sig;
 output [2:0] Column_Scan_Sig;
  row_scan_module U1
(
 .CLK (CLK ),
 .RSTn ( RSTn ),
 .Hund_SMG_Data(Hund_SMG_Data ),
 .Ten_SMG_Data (Ten_SMG_Data),
 .One_SMG_Data(One_SMG_Data),
 .Row_Scan_Sig(Row_Scan_Sig)
);
 column_scan_module U2
(
 .CLK (CLK ),
 .RSTn ( RSTn ),
 .Column_Scan_Sig(Column_Scan_Sig)

);
endmodule
//--------------------
//column_scan_module.v
//--------------------
module column_scan_module
(
  CLK,RSTn,Column_Scan_Sig
);
 input CLK;
 input RSTn;
 output [3:0]Column_Scan_Sig;
 parameter T10MS = 18'd199_999;
 reg [17:0]Count1;
 
 always @ (posedge CLK or negedge RSTn)
  if ( !RSTn )
   Count1 <= 18'd0;
  else if (Count1 == T10MS )
   Count1 <= 18'd0;
  else
   Count1 <= Count1 + 18'b1;
   
 reg [1:0] t;
 
 always @  (posedge CLK or negedge RSTn)
  if ( !RSTn )
   t <= 2'd0;
  else if( t == 2'd3 )
   t <= 2'd0;
  else if ( Count1 == T10MS )
   t <= t + 1'b1;
   
 reg [2:0] rColumn_Scan;
 always @  (posedge CLK or negedge RSTn)
     if ( !RSTn )
         rColumn_Scan <=3'b110;
       else if(Count1 == T10MS )
         case (t)
   2'd0 : rColumn_Scan <= 3'b110;
   2'd1 : rColumn_Scan <= 3'b101;
   2'd2 : rColumn_Scan <= 3'b011;
  endcase
  
 assign Column_Scan_Sig = rColumn_Scan;
endmodule
//-------------------
//number_mod_module.v
//-------------------
module number_mod_module
(
 CLK,RSTn,
 Number_Data,
 Hund_Data,Ten_Data,One_Data
);

 input CLK;
 input RSTn;
 input [7:0]Number_Data;
 output [3:0] Hund_Data; 
 output [3:0] Ten_Data;
 output [3:0] One_Data;

 reg [31:0]rHund;
 reg [31:0]rTen;
 reg [31:0]rOne;
 
 always @ (posedge CLK or negedge RSTn )
  if( !RSTn )
   begin
    rHund <=32'd0;
    rTen <= 32'd0;
    rOne <= 32'd0;
   end
  else
   begin
    rHund <= Number_Data/100;
    rTen <= Number_Data %100/10;
    rOne <= Number_Data %10;
   end
 assign Hund_Data = rHund[3:0];  
 assign Ten_Data = rTen[3:0];
 assign One_Data = rOne[3:0];
 
endmodule
//------------------------
//row_scan_module.v
//------------------------
module row_scan_module
(
  CLK,RSTn,
  Hund_SMG_Data,Ten_SMG_Data ,One_SMG_Data,
  Row_Scan_Sig
);

 input CLK;
 input RSTn;
 input [7:0] Hund_SMG_Data;
 input [7:0] Ten_SMG_Data;
 input [7:0] One_SMG_Data;
 output [7:0] Row_Scan_Sig;
 
 parameter T10MS = 18'd199_999;
 
 reg [17:0]Count1;
 
 always @ ( posedge CLK or negedge RSTn )
  if( !RSTn )
   Count1 <= 18'd0;
  else if ( Count1 == T10MS )
   Count1 <= 18'd0;
  else
   Count1 <= Count1 + 18'b1;
   
   reg [1:0] t;
  
   always @ ( posedge CLK or negedge RSTn )
  if( !RSTn )
   t <= 2'd0;
  else if ( t == 2'd3)
   t <= 2'd0;
  else if (Count1 == T10MS )
       t <= t + 1'b1;
      
   reg [7:0]rData;
  
   always @ ( posedge CLK or negedge RSTn )
  if( !RSTn )
      rData <= 8'd0;
   else if ( Count1 == T10MS )
   case (t )
   2'd2 : rData <= Hund_SMG_Data;
   2'd1 : rData <= Ten_SMG_Data;
   2'd0 : rData <= One_SMG_Data;
  endcase
  
 assign Row_Scan_Sig = rData;
 
endmodule
//---------------------
//smg_encoder_module.v
//---------------------
module smg_encoder_module
(
 CLK, RSTn,
 Hund_Data,Ten_Data,One_Data,
 Hund_SMG_Data,Ten_SMG_Data,One_SMG_Data
);

 input CLK;
 input RSTn;
 
 input [7:0]Hund_Data;
 input [3:0] Ten_Data;
 input [3:0] One_Data;
 
 output [7:0] Hund_SMG_Data;
 output [7:0] Ten_SMG_Data;
 output [7:0] One_SMG_Data;
 
 parameter _0 = 8'b1100_0000, _1 = 8'b1111_1001, _2 = 8'b1010_0100,
           _3 = 8'b1011_0000, _4 = 8'b1001_1001, _5 = 8'b1001_0010,
           _6 = 8'b1000_0010, _7 = 8'b 1111_1000, _8 = 8'b1000_0000,
           _9 = 8'b1001_0000;
 reg [7:0] rHund_SMG_Data;

 always @ (posedge CLK or negedge RSTn )
   if( !RSTn)
     begin
   rHund_SMG_Data <= 8'b1111_1111;
  end
  else
   case (Hund_Data)
    
    4'd0 : rHund_SMG_Data <= _0;
    4'd1 : rHund_SMG_Data <= _1;
    4'd2 : rHund_SMG_Data <= _2;
    4'd3 : rHund_SMG_Data <= _3;
    4'd4 : rHund_SMG_Data <= _4;
    4'd5 : rHund_SMG_Data <= _5;
    4'd6 : rHund_SMG_Data <= _6;
    4'd7 : rHund_SMG_Data <= _7;
    4'd8 : rHund_SMG_Data <= _8;
    4'd9 : rHund_SMG_Data <= _9;
   endcase
          
 reg [7:0] rTen_SMG_Data;

 always @ (posedge CLK or negedge RSTn )
   if( !RSTn)
     begin
   rTen_SMG_Data <= 8'b1111_1111;
  end
  else
   case (Ten_Data)
    
    4'd0 : rTen_SMG_Data <= _0;
    4'd1 : rTen_SMG_Data <= _1;
    4'd2 : rTen_SMG_Data <= _2;
    4'd3 : rTen_SMG_Data <= _3;
    4'd4 : rTen_SMG_Data <= _4;
    4'd5 : rTen_SMG_Data <= _5;
    4'd6 : rTen_SMG_Data <= _6;
    4'd7 : rTen_SMG_Data <= _7;
    4'd8 : rTen_SMG_Data <= _8;
    4'd9 : rTen_SMG_Data <= _9;
   endcase
   
  reg [7:0] rOne_SMG_Data;
  always @ ( posedge CLK or negedge RSTn)
   if( !RSTn)
    begin
     rOne_SMG_Data <= 8'b1111_1111;
    end
   else
    case (One_Data)
   
    4'd0 : rOne_SMG_Data <= _0;
    4'd1 : rOne_SMG_Data <= _1;
    4'd2 : rOne_SMG_Data <= _2;
    4'd3 : rOne_SMG_Data <= _3;
    4'd4 : rOne_SMG_Data <= _4;
    4'd5 : rOne_SMG_Data <= _5;
    4'd6 : rOne_SMG_Data <= _6;
    4'd7 : rOne_SMG_Data <= _7;
    4'd8 : rOne_SMG_Data <= _8;
    4'd9 : rOne_SMG_Data <= _9;
   endcase
  assign Hund_SMG_Data = rHund_SMG_Data; 
  assign Ten_SMG_Data = rTen_SMG_Data;
  assign One_SMG_Data = rOne_SMG_Data;
 endmodule

 


工程师
2012-10-22 20:23:50     打赏
14楼





                           0x0f(b00001111) = 15


  
                                   0xcf(b11001111) = 207


                
                               0xff(b11111111) = 255


工程师
2012-10-22 20:25:10     打赏
15楼


                                                               引脚分配图

工程师
2012-10-29 15:13:38     打赏
16楼

进程9 、串行通讯

        为了验证那片5V的MAX232工作在3V能否胜任,即进入RS232通讯练习,估计5V器件工作在3V时,性能会打折扣,故波特率只设定在9600,波特率设定:
module bps_module
(
   CLK, RSTn,
  Count_Sig,
  BPS_CLK
);

    input CLK;
  input RSTn;
  input Count_Sig;
  output BPS_CLK;
  reg [12:0]Count_BPS;
    always @ ( posedge CLK or negedge RSTn )
     if( !RSTn )
       Count_BPS <= 13'd0;
   else if( Count_BPS == 13'd5208 )
       Count_BPS <= 13'd0;
   else if( Count_Sig )
       Count_BPS <= Count_BPS + 1'b1;
   else
       Count_BPS <= 13'd0;
    assign BPS_CLK = ( Count_BPS == 13'd2604 ) ? 1'b1 : 1'b0;

endmodule
//----------------------
//  发送控制:
//---------------------
module tx_control_module
(
    CLK, RSTn,
  TX_En_Sig, RX_Data, BPS_CLK,
    TX_Done_Sig, TX_Pin_Out
);

   input CLK;
  input RSTn;
  input TX_En_Sig;
  input [7:0]RX_Data;
  input BPS_CLK;
  output TX_Done_Sig;
  output TX_Pin_Out;
  reg [3:0]i;
  reg rTX;
  reg isDone;
  always @ ( posedge CLK or negedge RSTn )
      if( !RSTn )
        begin
            i <= 4'd0;
      rTX <= 1'b1;
      isDone  <= 1'b0;
    end
    else if( TX_En_Sig )
        case ( i )
        4'd0 :
      if( BPS_CLK ) begin i <= i + 1'b1; rTX <= 1'b0; end
      4'd1, 4'd2, 4'd3, 4'd4, 4'd5, 4'd6, 4'd7, 4'd8 :
      if( BPS_CLK ) begin i <= i + 1'b1; rTX <= RX_Data[ i - 1 ]; end
      4'd9 :
      if( BPS_CLK ) begin i <= i + 1'b1; rTX <= 1'b1; end
      4'd10 :
      if( BPS_CLK ) begin i <= i + 1'b1; rTX <= 1'b1; end
      4'd11 :
      if( BPS_CLK ) begin i <= i + 1'b1; isDone <= 1'b1; end
     
      4'd12 :
      begin i <= 1'b0; isDone <= 1'b0; end
         endcase
       assign TX_Pin_Out = rTX;
  assign TX_Done_Sig = isDone;
endmodule
//-------------------
//接收控制
//-------------------
module rx_control_module
(
    CLK, RSTn,
  H2L_Sig, RX_Pin_In, BPS_CLK, RX_En_Sig,
    Count_Sig, RX_Data, RX_Done_Sig,TX_En_Sig
 
);

    input CLK;
  input RSTn;
  input H2L_Sig;
  input RX_En_Sig;
  input RX_Pin_In;
  input BPS_CLK;
   output Count_Sig;
  output [7:0]RX_Data;
  output RX_Done_Sig;
  output TX_En_Sig;
  reg [3:0]i;
  reg [7:0]rData;
  reg isCount;
  reg isDone;
  reg isTxen;
  always @ ( posedge CLK or negedge RSTn )
      if( !RSTn )
        begin
            i <= 4'd0;
      rData <= 8'd0;
      isCount <= 1'b0;
      isDone <= 1'b0;
      isTxen <= 1'b0;
    end
    else if( RX_En_Sig )
        case ( i )
           4'd0 :
      if( H2L_Sig ) begin i <= i + 1'b1; isCount <= 1'b1; end
      4'd1 :
      if( BPS_CLK ) begin i <= i + 1'b1; end
      4'd2, 4'd3, 4'd4, 4'd5, 4'd6, 4'd7, 4'd8, 4'd9 :
      if( BPS_CLK ) begin i <= i + 1'b1; rData[ i - 2 ] <= RX_Pin_In; end
      4'd10 :
      if( BPS_CLK ) begin i <= i + 1'b1; end
      4'd11 :
      if( BPS_CLK ) begin i <= i + 1'b1; end
      4'd12 :
      begin i <= i + 1'b1; isDone <= 1'b1; isCount <= 1'b0; end
      4'd13 :
      begin i <= 1'b0; isDone <= 1'b0; isTxen <= 1'b1;end     
    endcase
  assign Count_Sig = isCount;
  assign RX_Data = rData;
  assign RX_Done_Sig = isDone;
 assign TX_En_Sig = isTxen;
endmodule

其余代码省略

      使用串口助手进行调试,接口板上8只LED显示接收到的1个字节的数据,同时每隔2秒钟向上位机发送所接收到的数据。
     
还好,这只MAX232马马虎虎还能在3V下正常工作。大家可以不用对它动手术了。

点击下载
串口通讯演示软件.rar测试一下你的MAX232。


 
                                     引脚分配图
运行结果见下页


工程师
2012-10-29 15:18:33     打赏
17楼


                                           接收到73H数据并发送



                                           接收到85H数据并发送


                                         上位机接收、发送

工程师
2012-11-03 14:34:04     打赏
18楼

进程10,DS1302数字时钟

     参考DS1302手册可知:访问DS1302时钟芯片使用串行通讯方式,需要3条信号线:/RST,SCLK,SIO。

                
                                               DS1302读写时序
              
    读/写的时序图如上图,第一个字节是“访问寄存器地址”第二个字节
是“写数据”,写操作中都是时钟上升沿有效。读数据则不需要第二字节操作,读出的数据在时钟的下降沿有效。操作器件/RST必须拉高。数据都是从LSB开始,MSB结束。
  
                                        
                                                寄存器格式
 
      读/写操作寄存器格式见上图,“访问寄存器地址”这个字
节的格式:


                                                    命令格式

BIT7    固定
BIT6    访问寄存器空间/访问RAM空间
BIT5..1 地址数据
BIT0   读/写操作
    于是,在Verilog HDL语言中,访问寄存器地址的格式可以写成:
{2'b10,5'd Addr,1'b R/W}
其中BIT7固定为1、BIT6固定为0,
则读分钟寄存器就可以写成:{2'b10,5‘d2,1’b1}
   写分钟寄存器59写成:{2'b10,5‘d2,1’b0}{4'd5,4'd9}
秒寄存器的BIT7位为0,启动DS1302,为1关闭之,
时寄存器的BIT7位为0,是24小时制,为1是12小时制,
控制寄存器BIT7位为0,关闭写保护,为1,打开写保护。

 
                                 SIO三态门

读写DS1302时的数据线为双向SIO,图中isOut为高时IO为输出,向DS1302写操作,isOut为低时SIO为输入,对DS1302读操作。Verilg HDL 语言表示方法:
assign SIO=isOut ? Data_Out : 1'bz;
assign Data_In = SIO;

    进程中将8位LED数码管动态显示与读写DS1302进程相结合,首先关闭DS1302写保护,接着对时分秒写入23时59分00秒,然后就一直读取这3个寄存器的数据并在8位LED数码管上显示。运行中可以观察到当时钟运行到23-59-59后,下1秒显示为:00-00-00。同时跑马灯用的LED管也利用起来,显示了从0-59秒的二进制格式。最右边的黄色LED每隔1秒亮灭变化。由于Verilg HDL是并行操作,虽然没有使用任何中断,但FPGA同时处理多个进程很轻松,数码LED没有任何闪烁的感觉。


工程师
2012-11-03 14:43:50     打赏
19楼

module clock_top
(
  CLK, RSTn,
  KEY,
  SEG, DIG,
 
  RST,
  SCLK,
  SIO,
  SEC_Data,
  MIN_Data,
  HOU_Data,
  LED,
  YELLOW

);

     input CLK;
  input RSTn;
  input [7:0]KEY;
  output [7:0]SEG;
  output [7:0]DIG;
 
  output RST;
  output SCLK;
  inout SIO;
  output [7:0]SEC_Data;
  output [7:0]MIN_Data;
  output [7:0]HOU_Data;
  output [7:0]LED;
     output [2:0]YELLOW;
 
  /**************************************/

  wire [3:0]Data7;
  wire [3:0]Data6;
  wire [3:0]Data5;
  wire [3:0]Data4;
  wire [3:0]Data3;
  wire [3:0]Data2;
  wire [3:0]Data1;
  wire [3:0]Data0;
 
  number_swap_module U1
  (
      .CLK( CLK ),
    .RSTn( RSTn ),
    .KEY( Number_Data ), 
    .SEC_Data(SEC_Data),
    .MIN_Data(MIN_Data),
    .HOU_Data(HOU_Data),
    .Data7 ( Data7 ), 
    .Data6 ( Data6 ), 
    .Data5 ( Data5 ),
    .Data4 ( Data4 ), 
    .Data3 ( Data3 ),  
    .Data2 ( Data2 ),
    .Data1 ( Data1 ),  
    .Data0 ( Data0 ) 
  );
 
  /****************************************/

  wire [7:0]Bit7;
  wire [7:0]Bit6;
  wire [7:0]Bit5;
  wire [7:0]Bit4;
  wire [7:0]Bit3;
  wire [7:0]Bit2;
  wire [7:0]Bit1;
  wire [7:0]Bit0;
 
  seg_encoder_module U2
  (
      .CLK( CLK ),
    .RSTn( RSTn ),
   
    .Data7 ( Data7 ), 
    .Data6 ( Data6 ), 
    .Data5 ( Data5 ),
    .Data4 ( Data4 ), 
    .Data3 ( Data3 ), 
    .Data2 ( Data2 ),
    .Data1 ( Data1 ), 
    .Data0 ( Data0 ),
   
    .Bit7 ( Bit7 ), 
    .Bit6 ( Bit6 ), 
    .Bit5 ( Bit5 ),
    .Bit4 ( Bit4 ), 
    .Bit3 ( Bit3 ),  
    .Bit2 ( Bit2 ),
    .Bit1 ( Bit1 ), 
    .Bit0 ( Bit0 )    );
 
  /*****************************************/
 
 comp_scan_module U3
  (
      .CLK( CLK ),
    .RSTn( RSTn ),

    .Bit7 ( Bit7), 
    .Bit6 ( Bit6 ), 
    .Bit5 (Bit5 ),
    .Bit4 ( Bit4), 
    .Bit3 ( Bit3 ), 
    .Bit2 (Bit2 ),
    .Bit1 ( Bit1), 
    .Bit0 ( Bit0 ), 
    .SEG ( SEG ), 
    .DIG ( DIG ) 
  );
 
 
  exp13_demo_module U4
 
  (
  .CLK( CLK ),
  .RSTn( RSTn ),
  .RST(RST),
  .SCLK(SCLK),
  .SIO(SIO),
  .SEC_Data(SEC_Data),
  .MIN_Data(MIN_Data),
  .HOU_Data(HOU_Data),
  .LED(LED),
  .YELLOW(YELLOW)
    );
 /*******************************/
endmodule

  module function_module
(
    CLK, RSTn,
  Start_Sig,
  Words_Addr,
  Write_Data,
  Read_Data,
  Done_Sig,
  RST,
  SCLK,
  SIO
);

    input CLK;
  input RSTn;
  input [1:0]Start_Sig;
  input [7:0]Words_Addr;
  input [7:0]Write_Data;
  output [7:0]Read_Data;
  output Done_Sig;
  output RST;
  output SCLK;
  inout SIO;   //SIO和寄存器isOut组成三态门IO口
 
    /*****************************/
 
  parameter T0P5US = 4'd9;
 
  /*****************************/
 
  reg [3:0]Count1;
 
  always @ ( posedge CLK or negedge RSTn )
        if( !RSTn )
        Count1 <= 4'd0;
    else if( Count1 == T0P5US ) 
        Count1 <= 4'd0;
    else if( Start_Sig[0] == 1'b1 || Start_Sig[1] == 1'b1 )
        Count1 <= Count1 + 1'b1;
    else
        Count1 <= 4'd0;
  
  /*****************************/
 
        reg [5:0]i;   //执行步骤的寄存器
  reg [7:0]rData;  //暂存数据的寄存器
  reg rSCLK;   //用来驱动SCLK的寄存器
  reg rRST;   //用来驱动RST的寄存器
  reg rSIO;   //用来驱动SIO输出的寄存器
  reg isOut;   //用来控制IO方向寄存器
  reg isDone;   //完成标志寄存器

    
    always @ ( posedge CLK or negedge RSTn ) 
      if( !RSTn )
        begin
        i <= 6'd0;
      rData <= 8'd0;
      rSCLK <= 1'b0;
      rRST <= 1'b0;
      rSIO <= 1'b0;
      isOut <= 1'b0;
      isDone <= 1'b0;
    end
    
/***************************************************************************************
Start_Sig为2'b10 时是“写字节操作”。
步骤0:对rData,rSCL,rRST(CE),isOut等寄存器进行初始化。
步骤1-16:将“第一字节数据”(访问寄存器地址字节)发送出去。传输规则与SPI有点相似,在时间下降
沿设置数据,时间上升沿锁存数据。
步骤17:再次对rData设置为“第二字节数据”。
步骤18-33:将“第二字节数据”发送出去。
步骤34:对rRST(CE)拉低。以示“写字节操作”已经结束。
步骤35-36:反馈完成信号。
Start_Sig为2'b01 时是“读字节操作”。

*****************************************************************************************/
   else if( Start_Sig[1] )
       case( i )  
    
         0 :
       begin rSCLK <= 1'b0; rData <= Words_Addr; rRST <= 1'b1; isOut <= 1'b1; i <= i + 1'b1; end
      
       1, 3, 5, 7, 9, 11, 13, 15 :
       if( Count1 == T0P5US ) i <= i + 1'b1;
       else begin rSIO <= rData[ (i >> 1) ]; rSCLK <= 1'b0; end
      
       2, 4, 6, 8, 10, 12, 14, 16 :
       if( Count1 == T0P5US ) i <= i + 1'b1;
       else begin rSCLK <= 1'b1; end
      
       17 :
       begin rData <= Write_Data; i <= i + 1'b1; end
      
       18, 20, 22, 24, 26, 28, 30, 32 :
       if( Count1 == T0P5US ) i <= i + 1'b1;
       else begin rSIO <= rData[ (i >> 1) - 9 ]; rSCLK <= 1'b0; end
      
       19, 21, 23, 25, 27, 29, 31, 33 :
       if( Count1 == T0P5US ) i <= i + 1'b1;
       else begin rSCLK <= 1'b1; end
      
       34 :
       begin rRST <= 1'b0; i <= i + 1'b1; end
      
       35 :
       begin isDone <= 1'b1; i <= i + 1'b1; end
      
       36 :
       begin isDone <= 1'b0; i <= 6'd0; end
      
     endcase
/***************************************************************************************
Start_Sig为2'b01 时是“读字节操作”。在读操作中,第一字节和第二字节数据显然对时间沿的敏感不同。
步骤0:对rData,rSCL,rRST(CE),isOut等寄存器进行初始化。
步骤1-16:将“第一字节数据”(访问寄存器地址字节)发送出去。传输规则与SPI有点相似,在时间下降
沿设置数据,时间上升沿锁存数据。
步骤17:对IO口的方向改变为输入,亦即将isOut设置为逻辑0。
步骤18-33:“读取一个字节数据操作”,该操作在时间的下降沿从SIO读取数据。DS1302的数据传输都是从
LSB开始到MSB结束。
步骤34:对rRST(CE)拉低。以示“写字节操作”已经结束。
步骤35-36:恢复IO口为输出,拉高isOut寄存器,然后产生一个完成信号。
从DS1302芯片读取的数据会暂存在rData寄存器,该寄存器会驱动Read_Data这条信号线。assign Read_Data = rData;
*****************************************************************************************/

        else if( Start_Sig[0] )
       case( i )
    
         0 :
       begin rSCLK <= 1'b0; rData <= Words_Addr; rRST <= 1'b1; isOut <= 1'b1; i <= i + 1'b1; end
      
       1, 3, 5, 7, 9, 11, 13, 15 :
       if( Count1 == T0P5US ) i <= i + 1'b1;
       else begin rSIO <= rData[ (i >> 1) ]; rSCLK <= 1'b0; end
      
       2, 4, 6, 8, 10, 12, 14, 16 :
       if( Count1 == T0P5US ) i <= i + 1'b1;
       else begin rSCLK <= 1'b1; end
    
         17 :
         begin isOut <= 1'b0; i <= i + 1'b1; end
      
       18, 20, 22, 24, 26, 28, 30, 32 :
       if( Count1 == T0P5US ) i <= i + 1'b1;
       else begin rSCLK <= 1'b1; end
      
       19, 21, 23, 25, 27, 29, 31, 33 :
       if( Count1 == T0P5US ) begin i <= i + 1'b1; end
       else begin rSCLK <= 1'b0; rData[ (i >> 1) - 9 ] <= SIO; end
      
       34 :
       begin rRST <= 1'b0; isOut <= 1'b1; i <= i + 1'b1; end
      
       35 :
       begin isDone <= 1'b1; i <= i + 1'b1; end
      
       36 :
       begin isDone <= 1'b0; i <= 6'd0; end
      
     endcase
  
  /********************************/
  
  assign Read_Data = rData;  //
  assign Done_Sig = isDone;
  
  assign RST = rRST;
  assign SCLK = rSCLK;
  assign SIO = isOut ? rSIO : 1'bz; //该行定义了SDA这个IO口是由isOut这个寄存器控制着“输入输出”。
       //当isOut为逻辑1时,SIO口是输出状态,反之是输入状态
  
  /********************************/

endmodule

相关LED数码动态扫描显示代码省略




点击下载DS1302数字时钟.rar


工程师
2012-11-03 21:07:40     打赏
20楼
回复楼上:菜鸟系“刚要入门”级,参加FPGA DIY,并不是为了走过场,每个进程我都立足于弄懂原理,学到真正知识。代码当然要参考高手的,不过一定要消化吸收为己用。进程里将秒计数同时以二进制方式显示,就是为了有别抄袭之嫌。

共30条 2/3 1 2 3 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]