玩转FPGA山寨版

看了《玩转FPGA》,写的不错,写写山寨版和大家交流!

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

做了一个LED测试仪器的项目,半年过去了,都没有时间写博客,现在闲下来写写!

项目中用到了DS18B20温度传感器,在网上找到了一个驱动代码,经过我改造一下做成定制IP和大家分享!

一、DS18B20定制IP  Verilog HDL代码

//**********************************************************************************//

module avalon_slave_DS18B20(
               address,
               clk,
               reset_n,
               readdata,
               TEMP
            );

  output  [ 15: 0] readdata;
  input   [  1: 0] address;
  input            clk;
  input            reset_n;
  inout            TEMP;

  wire             clk_en;
  wire    [ 15: 0] data_in;
  wire    [ 15: 0] read_mux_out;
  reg     [ 15: 0] readdata;
  assign clk_en = 1;
  //s1, which is an e_avalon_slave
  assign read_mux_out = {16 {(address == 0)}} & data_in;
  always @(posedge clk or negedge reset_n)
    begin
      if (reset_n == 0)
          readdata <= 0;
      else if (clk_en)
          readdata <= read_mux_out;
    end

  assign data_in = temperature_buf; //Ds18b20用12位存贮温值度最高位为符号位;

//++++++++++++++++++++++++++++++++++++++
// 分频器50MHz->1MHz 开始
//++++++++++++++++++++++++++++++++++++++
reg [5:0] cnt;                         // 计数子 
always@(posedge clk or negedge reset_n)
begin
  if (!reset_n)   cnt <= 1'b0;
  else  if (cnt == 6'd49) cnt <= 1'b0;
  else   cnt <= cnt + 1'b1;
end

reg clk_1us;                            // 1MHz 时钟

always@(posedge clk or negedge reset_n)
begin
  if (!reset_n) clk_1us <= 1'b0;
  else if (cnt <= 6'd24)  clk_1us <= 1'b0;
  else   clk_1us <=1'b1;
end     

//--------------------------------------
// 分频器50MHz->1MHz 结束
//--------------------------------------


//++++++++++++++++++++++++++++++++++++++
// 延时模块 开始
//++++++++++++++++++++++++++++++++++++++
reg [19:0] cnt_1us;                      // 1us延时计数子
reg cnt_1us_clear;                       // 请1us延时计数子

always@(posedge clk_1us)
begin
  if(cnt_1us_clear) cnt_1us <= 1'b0;
  else  cnt_1us <= cnt_1us + 1'b1;
end
//--------------------------------------
// 延时模块 结束
//--------------------------------------


//++++++++++++++++++++++++++++++++++++++
// DS18B20状态机 开始
//++++++++++++++++++++++++++++++++++++++
//++++++++++++++++++++++++++++++++++++++
// 格雷码
parameter S00     = 5'h00;
parameter S0      = 5'h01;
parameter S1      = 5'h03;
parameter S2      = 5'h02;
parameter S3      = 5'h06;
parameter S4      = 5'h07;
parameter S5      = 5'h05;
parameter S6      = 5'h04;
parameter S7      = 5'h0C;
parameter WRITE0  = 5'h0D;
parameter WRITE1  = 5'h0F;
parameter WRITE00 = 5'h0E;
parameter WRITE01 = 5'h0A;
parameter READ0   = 5'h0B;
parameter READ1   = 5'h09;
parameter READ2   = 5'h08;
parameter READ3   = 5'h18;

reg [4:0] state;                       // 状态寄存器
//-------------------------------------

reg TEMP_buf;                      // One-Wire总线 缓存寄存器

reg [15:0] temperature_buf;            // 采集到的温度值缓存器(未处理)
reg [5:0] step;                        // 子状态寄存器 0~50
reg [3:0] bit_valid;                   // 有效位  
  
always@(posedge clk_1us or negedge reset_n)
begin
  if (!reset_n)
  begin
    TEMP_buf <= 1'bZ;
    step         <= 6'd0;
    state        <= S00;
  end
  else
  begin
    case (state)
      S00 : begin              
              temperature_buf <= 16'h001F;
              state           <= S0;
            end
      S0 :  begin                       // 初始化
              cnt_1us_clear <= 1'b1;
              TEMP_buf  <= 1'b0;              
              state         <= S1;
            end
      S1 :  begin
              cnt_1us_clear <= 1'b0;
              if (cnt_1us == 20'd500)         // 延时500us
              begin
                cnt_1us_clear <= 1'b1;
                TEMP_buf  <= 1'bZ;  // 释放总线
                state         <= S2;
              end 
            end
      S2 :  begin
              cnt_1us_clear <= 1'b0;
              if (cnt_1us == 20'd100)         // 等待100us
              begin
                cnt_1us_clear <= 1'b1;
                state         <= S3;
              end 
            end
      S3 :  if (~TEMP)              // 若18b20拉低总线,初始化成功
              state <= S4;
            else if (TEMP)          // 否则,初始化不成功,返回S0
              state <= S0;
      S4 :  begin
              cnt_1us_clear <= 1'b0;
              if (cnt_1us == 20'd400)         // 再延时400us
              begin
                cnt_1us_clear <= 1'b1;
                state         <= S5;
              end 
            end        
      S5 :  begin                       // 写数据
              if      (step == 6'd0)       // 0xCC
              begin
                step  <= step + 1'b1;
                state <= WRITE0;
              end
              else if (step == 6'd1)
              begin
                step  <= step + 1'b1;
                state <= WRITE0;
              end
              else if (step == 6'd2)
              begin                
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= WRITE01; 
              end
              else if (step == 6'd3)
              begin
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= WRITE01;                
              end
              else if (step == 6'd4)
              begin
                step  <= step + 1'b1;
                state <= WRITE0;
              end
              else if (step == 6'd5)
              begin
                step  <= step + 1'b1;
                state <= WRITE0;
              end
              else if (step == 6'd6)
              begin
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= WRITE01;
              end
              else if (step == 6'd7)
              begin
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= WRITE01;
              end
              
              else if (step == 6'd8)       // 0x44
              begin
                step  <= step + 1'b1;
                state <= WRITE0;
              end
              else if (step == 6'd9)
              begin
                step  <= step + 1'b1;
                state <= WRITE0;
              end
              else if (step == 6'd10)
              begin
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= WRITE01;
              end
              else if (step == 6'd11)
              begin
                step  <= step + 1'b1;
                state <= WRITE0;
              end
              else if (step == 6'd12)
              begin
                step  <= step + 1'b1;
                state <= WRITE0;
              end
              else if (step == 6'd13)
              begin
                step  <= step + 1'b1;
                state <= WRITE0;
              end
              else if (step == 6'd14)
              begin
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= WRITE01;
                 
              end
              else if (step == 6'd15)
              begin
                step  <= step + 1'b1;
                state <= WRITE0;
              end
              
              // 第一次写完,750ms后,跳回S0
              else if (step == 6'd16)
              begin
                TEMP_buf <= 1'bZ;
                step         <= step + 1'b1;
                state        <= S6;                
              end
              
              // 再次置数0xCC和0xBE
              else if (step == 6'd17)      // 0xCC
              begin
                step  <= step + 1'b1;
                state <= WRITE0;
              end
              else if (step == 6'd18)
              begin
                step  <= step + 1'b1;
                state <= WRITE0;
              end
              else if (step == 6'd19)
              begin
                TEMP_buf <= 0;
                step         <= step + 1'b1;
                state        <= WRITE01;                
              end
              else if (step == 6'd20)
              begin
                step  <= step + 1'b1;
                state <= WRITE01;
                TEMP_buf <= 1'b0;
              end
              else if (step == 6'd21)
              begin
                step  <= step + 1'b1;
                state <= WRITE0;
              end
              else if (step == 6'd22)
              begin
                step  <= step + 1'b1;
                state <= WRITE0;
              end
              else if (step == 6'd23)
              begin
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= WRITE01;
              end
              else if (step == 6'd24)
              begin
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= WRITE01;               
              end
              
              else if (step == 6'd25)      // 0xBE
              begin
                step  <= step + 1'b1;
                state <= WRITE0;
              end
              else if (step == 6'd26)
              begin
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= WRITE01;                
              end
              else if (step == 6'd27)
              begin
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= WRITE01;                
              end
              else if (step == 6'd28)
              begin
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= WRITE01;                
              end
              else if (step == 6'd29)
              begin
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= WRITE01;
              end
              else if (step == 6'd30)
              begin
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= WRITE01;
              end
              else if (step == 6'd31)
              begin
                step  <= step + 1'b1;
                state <= WRITE0;
              end
              else if (step == 6'd32)
              begin
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= WRITE01;
              end
              
              // 第二次写完,跳到S7,直接开始读数据
              else if (step == 6'd33)
              begin
                step  <= step + 1'b1;
                state <= S7;
              end 
            end
      S6 :  begin
              cnt_1us_clear <= 1'b0;
              if (cnt_1us == 20'd750000 | TEMP)     // 延时750ms!!!!
              begin
                cnt_1us_clear <= 1'b1;
                state         <= S0;    // 跳回S0,再次初始化
              end 
            end
            
      S7 :  begin                       // 读数据
              if      (step == 6'd34)
              begin
                bit_valid    <= 1'b0;
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= READ0;
              end
              else if (step == 6'd35)
              begin
                bit_valid    <= bit_valid + 1'b1;
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= READ0;
              end
              else if (step == 6'd36)
              begin
                bit_valid    <= bit_valid + 1'b1;
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= READ0;
              end
              else if (step == 6'd37)
              begin
                bit_valid    <= bit_valid + 1'b1;
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= READ0;               
              end
              else if (step == 6'd38)
              begin
                bit_valid    <= bit_valid + 1'b1;
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= READ0;                
              end
              else if (step == 6'd39)
              begin
                bit_valid    <= bit_valid + 1'b1;
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= READ0;               
              end
              else if (step == 6'd40)
              begin
                bit_valid    <= bit_valid + 1'b1;
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= READ0;                
              end
              else if (step == 6'd41)
              begin
                bit_valid    <= bit_valid + 1'b1;
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= READ0;
              end
              else if (step == 6'd42)
              begin
                bit_valid    <= bit_valid + 1'b1;
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= READ0;                
              end
              else if (step == 6'd43)
              begin
                bit_valid    <= bit_valid + 1'b1;
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= READ0;
              end
              else if (step == 6'd44)
              begin
                bit_valid    <= bit_valid + 1'b1;
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= READ0;                
              end
              else if (step == 6'd45)
              begin
                bit_valid    <= bit_valid + 1'b1;
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= READ0;                
              end
              else if (step == 6'd46)
              begin
                bit_valid    <= bit_valid + 1'b1;
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= READ0;                
              end
              else if (step == 6'd47)
              begin
                bit_valid    <= bit_valid + 1'b1;
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= READ0;                
              end
              else if (step == 6'd48)
              begin
                bit_valid    <= bit_valid + 1'b1;
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= READ0;                
              end
              else if (step == 6'd49)
              begin
                bit_valid    <= bit_valid + 1'b1;
                TEMP_buf <= 1'b0;
                step         <= step + 1'b1;
                state        <= READ0;                
              end
              else if (step == 6'd50)
              begin
                step  <= 1'b0;
                state <= S0;
              end 
            end            
            
            
      //++++++++++++++++++++++++++++++++
      // 写状态机
      //++++++++++++++++++++++++++++++++
      WRITE0 :
            begin
              cnt_1us_clear <= 1'b0;
              TEMP_buf  <= 1'b0;       // 输出0             
              if (cnt_1us == 20'd80)        // 延时80us
              begin
                cnt_1us_clear <= 1'b1;
                TEMP_buf  <= 1'bZ;  // 释放总线,自动拉高                
                state         <= WRITE00;
              end 
            end
      WRITE00 :                         // 空状态
              state <= S5;
      WRITE01 :                         // 空状态
              state <= WRITE1;
      WRITE1 :
            begin
              cnt_1us_clear <= 1'b0;
              TEMP_buf  <= 1'bZ;    // 输出1   释放总线,自动拉高
              if (cnt_1us == 20'd80)        // 延时80us
              begin
                cnt_1us_clear <= 1'b1;
                state         <= S5;
              end 
            end
      //--------------------------------
      // 写状态机
      //--------------------------------
      
      
      //++++++++++++++++++++++++++++++++
      // 读状态机
      //++++++++++++++++++++++++++++++++
      READ0 : state <= READ1;           // 空延时状态
      READ1 :
            begin
              cnt_1us_clear <= 1'b0;
              TEMP_buf  <= 1'bZ;    // 释放总线
              if (cnt_1us == 20'd10)        // 再延时10us
              begin
                cnt_1us_clear <= 1'b1;
                state         <= READ2;
              end 
            end
      READ2 :                           // 读取数据
            begin
              temperature_buf[bit_valid] <= TEMP;
              state                      <= READ3;
            end
      READ3 :
            begin
              cnt_1us_clear <= 1'b0;
              if (cnt_1us == 20'd55)        // 再延时55us
              begin
                cnt_1us_clear <= 1'b1;
                state         <= S7;
              end 
            end
      //--------------------------------
      // 读状态机
      //--------------------------------
      
      
      default : state <= S00;
    endcase 
  end 
end 

assign TEMP = TEMP_buf;         // 注意双向口的使用
//--------------------------------------
// DS18B20状态机 结束
//--------------------------------------

endmodule

//**********************************************************************************//

二、定制IP在SOPC Builder中的设定

在Quartus II软件安装目录下建立自己的IP文件夹,<Quartus II软件安装目录>\altera\90\ip里面建立一个MyIP的文件夹,

在文件夹在建立一个DS18B20文件夹,我们把上面代码COPY下来做成Verilog代码的文件avalon_slave_DS18B20.v,

在Quartus II建立工程,打开SOPC Builder,点击File菜单下的New Component,选择HDL File的标签,点击Add

,<Quartus II软件安装目录>\altera\90\ip\MyIP\DS18B20\avalon_slave_DS18B20.v文件,在Signal标签里面的Temp

选择如下图:

Interface标签如下图:

Component Wizard标签:

所有Edit的沟都去掉,点击Finish即可!

三、SOPC Builder配置

不用多说,看看图片:

但会报错:

把Interface标签参数类型全都改为integer型就可

四、Quartus 工程文件

五、NIOS II  C 代码

//**************************************************************************//

#include"stdio.h"
#include"system.h"

int main(void)
{
    float temp;
    volatile short *data = ( short * ) DS18B20_BASE;
    while(1)
    {
        temp = (float) (*data / 16.0); //DS18B20 采用12位补码形式,读出数据直接除以16.0,不是16,不然就是小数部分了
        printf("-DS18B20 SENSOR-\n**TEMP:%6.2f**\n",temp);
    }
    return 0;
}
//*************************************************************************//

posted on 2011-01-20 10:48  Neddy11  阅读(2104)  评论(25)    收藏  举报