当前位置:网站首页>Application of DS18B20 temperature sensor based on FPGA

Application of DS18B20 temperature sensor based on FPGA

2022-06-13 06:51:00 A witty orange

One . Sensor Introduction

ds18b20 It is a commonly used digital temperature sensor , Small size , Low hardware overhead , Strong anti-interference ability , Features of high precision .

1. characteristic

ds18b20 Single line digital temperature sensor has unique advantages :

( 1 ) Single bus interface mode is adopted Only one cable is needed to connect with the microprocessor DS18B20 Two way communication between . Single bus has good economy , Strong anti-interference ability , Suitable for on-site temperature measurement in harsh environment , Easy to use and other advantages , So that users can easily build sensor networks , Introduce a new concept for the construction of measurement system .   
( 2 ) Wide measuring temperature range , High measurement accuracy DS18B20 The measurement range of is -55 ℃ ~+ 125 ℃ ; stay -10~+ 85°C Within the scope of , Accuracy of ± 0.5°C .  
( 3 ) No peripheral components are required in use .  
( 4 ) Support multi-point networking function Multiple DS18B20 It can be connected in parallel to the only single line , Realize multi-point temperature measurement .   
( 5 ) The power supply mode is flexible DS18B20 The power supply can be obtained from the data line through the internal parasitic circuit . therefore , When the time sequence on the data line meets certain requirements , It can be disconnected from external power supply , Thus, the system structure becomes simpler , reliability Higher .   
( 6 ) Measurement parameters can be configured DS18B20 The measurement resolution of can be set by program 9~12 position .   
( 7 ) Negative pressure characteristic when the polarity of the power supply is reversed , The thermometer will not burn out due to heat , But it doesn't work .
( 8 ) Power down protection function DS18B20 The interior contains EEPROM , After the system is powered down , It can still save minutes Set value of resolution and alarm temperature .

2. internal structure

ds18b20 The interior is mainly composed of four parts :64 position ROM, Temperature sensor , Non volatile temperature alarm trigger TH and TL, Configuration register .
64 position ROM
ROM Medium 64 The bit serial number is lithographed before leaving the factory , It can be seen as the DS18B20 Address sequence code , Every time
individual DS18B20 Of 64 Bit serial numbers are different .
64 position ROM Cyclic redundancy check code of the row CRC=X+X+X+1.
ROM The function of is to make every DS18B20 They're all different , In this way, multiple can be connected to one bus DS18B20 Purpose .
 Insert picture description here

3.ds18b20 Pin

  1. GND For the power supply ;
  2. DQ For digital signal input / Output terminal ;
  3. VDD For external power input ( Grounding in parasitic power connection mode )
     Insert picture description here

4.ds18b20 Internal cache

The cache consists of 9 Byte composition , When the temperature conversion command is issued , The converted temperature value is stored in the second part of the cache in the form of two byte complement 0 And the 1 Bytes . Single chip microcomputer can read the data through single line interface , When reading, the low order is in the front , High position behind , Corresponding temperature calculation : The equivalent sign S=0 when , Directly convert binary bits to decimal ; When S=1 when , First change the complement to the original code , Then calculate the decimal value .
  Insert picture description here
  explain :

byte 0 The lower eight bits of data representing the temperature .
byte 1 The upper octet data of temperature .
byte 2 Indicates the high temperature threshold .
byte 3 Indicates the low temperature threshold .
byte 4 Indicates the configuration register .
byte 5、 byte 6、 byte 7 Is reserved bytes .

DS18B20 The temperature sensor in completes the temperature measurement , use 16 Bit binary form provides , In the form of expression , Its
in S Symbol bit .
 Insert picture description here
  for example :
  +125℃ The digital output of 07D0H.( Positive temperature direct 16 To convert a base number to 10 Hexadecimal is the temperature value )
  -55℃ The digital output of is FC90H.( Negative temperature will get 16 Hexadecimal numbers are added after being negated 1 Again into 10 Hexadecimal number )
 Insert picture description here

5.ds18b20 Working sequence

Initialization timing :
 ① The host first sends a message 480-960 Microsecond low level pulse , Then the release bus becomes high level , And then
Of 480 Detect the bus in microseconds , If there is a low level, it means that there is a device on the bus that has made a response . If no low level appears, it is always high level, indicating that there is no device response on the bus .
 ② As a slave device DS18B20 After power on, it has been testing whether there is 480-960 Microsecond low level output
present , If there is , Wait after the bus goes high 15-60 Pull the bus level down after microseconds 60-240 Microseconds respond with pulses , Tell the host that the device is ready . If it's not detected, it's waiting to be detected .
 Insert picture description here
Write operations :
The write cycle is at least 60 Microsecond , Not more than 120 Microsecond . At the beginning of the write cycle, the host pulls down the bus first 1 Microseconds indicate the start of the write cycle . Then if the host wants to write 0, Then continue to pull the low level at least 60 Microseconds until the end of the write cycle , Then release the bus to high level . If the host wants to write 1, Pull down the bus level at the beginning 1 The bus is released to high level after microseconds , Until the end of the write cycle . As a slave DS18B20 Then wait after detecting that the bus has been pulled to the bottom 15 Microseconds and then from 15us To 45us Start sampling the bus , During the sampling period, if the bus is high level 1, If the bus level is low during the sampling period, it is 0.
 Insert picture description here
 Insert picture description here

Read operations :
For the read data operation, the sequence is also divided into read 0 Timing and reading 1 Timing is two processes . The read timeslot is after the single bus is pulled down from the host , stay 1 After microseconds, the single bus must be released to high level , In order to let DS18B20 Transfer data to a single bus .DS18B20 After detecting that the bus is pulled down 1 Microseconds later , Start sending data , If you want to send 0 Pull the bus low until the end of the read cycle . To send 1 Then the release bus is high . The host pulls down the bus at the beginning 1 Release the bus after microseconds , Then pull down the bus level before including 1 Microseconds 15 Complete the sampling and detection of the bus in microseconds , If the bus level is low during the sampling period, it is confirmed as 0. If the bus is high during the sampling period, it is confirmed as 1. Complete a read sequence process , Need at least 60us To complete
 Insert picture description here

6.ds18b20 Single line communication

DS18B20 The single line communication function is time-sharing , He has a strict concept of time slots , If there is confusion in the sequence ,
1-WIRE The device will not respond to the host , So the timing of reading and writing is very important . System pair DS18B20 All operations of the must be carried out according to the agreement . according to DS18B20 According to the agreement , The microcontroller controls DS18B20 To complete the temperature conversion, you must go through the following 3 A step :
(1) Before each reading and writing DS18B20 Perform reset initialization . Reset requires master CPU Pull down the data line 500us , Then release , DS18B20 Wait after receiving the signal 16us~60us about , Then send out 60us~240us The presence of low pulses , Lord CPU After receiving this signal, it means that the reset is successful .
(2) Send a ROM Instructions

Instruction names Instruction code Command function
read ROM33H read DS18B20ROM Code in ( Read 64 Bit address )
ROM matching ( accord with ROM)55H After this command is issued , And then send out 64 position ROM code , Corresponding to the code on the access single bus DS18820 Make it responsive , For the next step DS18B20 Prepare for reading and writing
Search for ROM0F0H Used to determine whether it is connected to the same bus DS18B20 Number and identification of 64 position ROM Address , Prepare for the operation of each device
skip ROM0CCH Ignore 64 position ROM Address , Direct to DS18B20 Send temperature change command , It is suitable for single chip microcomputer
Alert search 0ECH After the command is executed , Only the piece whose temperature exceeds the upper or lower limit of the set value will respond

(3) Send memory instructions

Instruction names Instruction code Command function
Temperature change 44H start-up DS18B20 Perform temperature conversion , The maximum conversion time is 500ms( Typical for 200ms ), The results are stored internally 9 byte RAM in
Read Scratchpad 0BEH Read inside RAM in 9 The contents of Yu Festival
Write register 4EH Send to the inside RAM Of the 3, 4 The byte is written with , Lower temperature data command , Immediately after the command , Is to transfer two bytes of data
Copy register 48H take RAM pass the civil examinations 3,4 Copy the contents of bytes to EEPROM in
Readjustment EEPROM0B8HEEPROM Restore the contents of to RAM No 3, 4 byte
Read power supply mode 0B4H read DS18B20 Power supply mode , Parasitic power supply DS18B20 send out “0”, External power supply DS18B20 send out “1”

Two .FPGA Code implementation

1. State diagram

FPGA As a host ,DS18B20 As a slave .
① The main state machine sends reset pulses - Receive presence pulse - Hair ROM Instructions - Send the temperature conversion command - Time delay - Temperature reading command - Reading temperature ;
② The slave state machine is responsible for sending data or reading data sequence : Pull down the bus - send data / Sampled data - Release the bus ;
Master slave state diagram :
 Insert picture description here
Status description :

M_IDLE: Idle state , Wait for communication to begin ;
M_RST: Send reset pulse ;
M_RELE: Release the bus ;
M_RACK: Receive presence pulse ;
M_RSKP: Send skip ROM Instructions ;
M_SCON: Send temperature conversion command ;
M_WAIT: wait for 750ms;
M_SRTM: Send the temperature reading command ;
M_RTMP: Read temperature value ;
S_IDLE: Idle state , Waiting for transfer request ;
S_LOW: Pull down before sending data 1us;
S_SEND: send out 1bit data ;
S_SAMP: receive 1bit data ;
S_RELE: Release the bus ;
S_DONE: send out / Receiving data once ;

2. Code implementation

2.1DS18B20 Driver module

module ds18b20_driver(
    input                       clk         ,// Clock signal 
    input                       rst_n       ,// Reset signal 
    input                       dq_in       ,  

    output  reg                 dq_out      ,//dq Bus FPGA Output  
    output  reg                 dq_out_en   ,// Output data valid signal 
    output  reg                 temp_sign   ,// Temperature value sign bit  0: just  1: negative 
    output  reg     [23:0]      temp_out    ,// Temperature output 
    output  reg                 temp_out_vld // Temperature output valid signal  
);

// State machine parameters 
    localparam  
                // Host status parameters 
                M_IDLE = 9'b0_0000_0001 ,// Idle state 
                M_REST = 9'b0_0000_0010 ,// Reset 
                M_RELE = 9'b0_0000_0100 ,// Release the bus  -- ds18b20 wait for 
                M_RACK = 9'b0_0000_1000 ,// Receive response  --  The host receives the presence pulse 
                M_ROMS = 9'b0_0001_0000 ,//ROM command  --  skip ROM command 
                M_CONT = 9'b0_0010_0000 ,// conversion 
                M_WAIT = 9'b0_0100_0000 ,// wait for  -- 12bit Temperature conversion time at resolution 
                M_RCMD = 9'b0_1000_0000 ,// Read command  --  Read register command 
                M_RTMP = 9'b1_0000_0000 ,// Read temperature  --  Generate read timeslot  --  receive 2 Byte complement temperature with sign bit 

                // Slave state parameters 
                S_IDLE = 6'b00_0001     ,// Idle state 
                S_LOW  = 6'b00_0010     ,// Pull down the bus  --  The beginning of the time slot 
                S_SEND = 6'b00_0100     ,// send out  -- 15us Inside 
                S_SAMP = 6'b00_1000     ,// sampling  --  stay 15us Inside 
                S_RELE = 6'b01_0000     ,// Release  --  Time slot recovery time 
                S_DONE = 6'b10_0000     ;//

    parameter       
                TIME_1US = 50           ,//1us
                TIME_RST = 500          ,// Reset pulse  500us
                TIME_REL = 20           ,// Host releases bus  20us
                TIME_PRE = 200          ,// The host receives the presence pulse  200us
                TIME_WAIT= 750000       ,// After the host sends the temperature conversion command   wait for 750ms
                TIME_LOW = 2            ,// The host pulls down the bus  2us
                TIME_RW  = 60           ,// Host read 、 Write 1bit 60us
                TIME_REC = 3            ;// Host read 、 finish writing sth. 1bit Release the bus  3us

    localparam
                CMD_ROMS = 8'hCC        ,// skip ROM Instructions 
                CMD_CONT = 8'h44        ,// Temperature conversion command 
                CDM_RTMP = 8'hBE        ;// Read register instructions 

// Signal definition 
    reg     [8:0]       m_state_c   ;// The host is in the current state 
    reg     [8:0]       m_state_n   ;// Host secondary state 

    reg     [5:0]       s_state_c   ;// The slave is in the current state 
    reg     [5:0]       s_state_n   ;// Slave state  

    reg     [5:0]       cnt_1us     ;//1us Counter 
    wire                add_cnt_1us ;
    wire                end_cnt_1us ;

    reg     [19:0]      cnt0        ;// Reset pulse 、 Release 、 There are pulses 、 wait for 750ms
    wire                add_cnt0    ;
    wire                end_cnt0    ;
    reg     [19:0]      X           ;

    reg     [5:0]       cnt1        ;// Count the duration of each state of the slave state machine 
    wire                add_cnt1    ;
    wire                end_cnt1    ;
    reg     [5:0]       Y           ;

    reg     [4:0]       cnt_bit     ;
    wire                add_cnt_bit ;
    wire                end_cnt_bit ;

    reg                 slave_ack   ;// Receive presence pulse 
    reg                 flag        ;//0: Send temperature conversion command  1: Send temperature reading command 
    reg     [7:0]       wr_data     ;
    reg     [15:0]      orign_data  ;// Sampling temperature value register 

    reg     [10:0]      temp_data   ;
    wire    [23:0]      temp_data_w ;// The combinational logic calculates the actual temperature value   Decimal system 

    wire                m_idle2m_rest   ;
    wire                m_rest2m_rele   ;
    wire                m_rele2m_rack   ;
    wire                m_rack2m_roms   ;
    wire                m_roms2m_cont   ;
    wire                m_roms2m_rcmd   ;
    wire                m_cont2m_wait   ;
    wire                m_wait2m_rest   ;
    wire                m_rcmd2m_rtmp   ;
    wire                m_rtmp2m_idle   ;

    wire                s_idle2s_low    ;
    wire                s_low2s_send    ;
    wire                s_low2s_samp    ;
    wire                s_send2s_rele   ;
    wire                s_samp2s_rele   ;
    wire                s_rele2s_low    ;
    wire                s_rele2s_done   ;

// Host state machine design   Describe state transitions 
    [email protected](posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            m_state_c <= M_IDLE;
        end
        else begin
            m_state_c <= m_state_n;
        end
    end

// Host state transition conditions 
    always @(*) begin
        case(m_state_c)
            M_IDLE:begin
                if(m_idle2m_rest)
                    m_state_n = M_REST;
                else
                    m_state_n = m_state_c;
            end
            M_REST:begin
                if(m_rest2m_rele)
                    m_state_n = M_RELE;
                else
                    m_state_n = m_state_c;
            end
            M_RELE:begin
                if(m_rele2m_rack)
                    m_state_n = M_RACK;
                else
                    m_state_n = m_state_c;
            end
            M_RACK:begin
                if(m_rack2m_roms)
                    m_state_n = M_ROMS;
                else
                    m_state_n = m_state_c;
            end
            M_ROMS:begin
                if(m_roms2m_cont)
                    m_state_n = M_CONT;
                else if(m_roms2m_rcmd)
                    m_state_n = M_RCMD;
                else
                    m_state_n = m_state_c;
            end
            M_CONT:begin
                if(m_cont2m_wait)
                    m_state_n = M_WAIT;
                else
                    m_state_n = m_state_c;
            end
            M_WAIT:begin
                if(m_wait2m_rest)
                    m_state_n = M_REST;
                else
                    m_state_n = m_state_c;
            end
            M_RCMD:begin
                if(m_rcmd2m_rtmp)
                    m_state_n = M_RTMP;
                else
                    m_state_n = m_state_c;
            end
            M_RTMP:begin
                if(m_rtmp2m_idle)
                    m_state_n = M_IDLE;
                else
                    m_state_n = m_state_c;
            end
            default:m_state_n = M_IDLE;
        endcase
    end

    assign m_idle2m_rest = m_state_c == M_IDLE && (1'b1)    ;// host IDLE The state is directly converted to the reset state 
    assign m_rest2m_rele = m_state_c == M_REST && (end_cnt0);//500us Reset pulse 
    assign m_rele2m_rack = m_state_c == M_RELE && (end_cnt0);//20us Release the bus 
    assign m_rack2m_roms = m_state_c == M_RACK && (end_cnt0 && slave_ack == 1'b0);//200us, The host receives the receiving pulse 
    assign m_roms2m_cont = m_state_c == M_ROMS && (s_state_c == S_DONE && flag == 1'b0);// The host has sent 8bit skip ROM command  0: Temperature conversion command 
    assign m_roms2m_rcmd = m_state_c == M_ROMS && (s_state_c == S_DONE && flag == 1'b1);// The host has sent 8bit skip ROM command  1: Read the temperature command 
    assign m_cont2m_wait = m_state_c == M_CONT && (s_state_c == S_DONE);// Host send 8bit Temperature conversion command 
    assign m_wait2m_rest = m_state_c == M_WAIT && (end_cnt0);// wait for 750ms convert network 
    assign m_rcmd2m_rtmp = m_state_c == M_RCMD && (s_state_c == S_DONE);// Host send 8bit Read command  -- Wait for the slave to receive data 
    assign m_rtmp2m_idle = m_state_c == M_RTMP && (s_state_c == S_DONE);// The host reads the temperature  -- Wait for the slave to send data 

// Slave state machine design   Describe state transitions 
    [email protected](posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            s_state_c <= S_IDLE;
        end
        else begin
            s_state_c <= s_state_n;
        end
    end   

// Slave state transition condition 
  always @(*) begin
      case(s_state_c)
            S_IDLE:begin
                if(s_idle2s_low)
                    s_state_n = S_LOW;
                else
                    s_state_n = s_state_c;
            end
            S_LOW :begin
                if(s_low2s_send)
                    s_state_n = S_SEND;
                else if(s_low2s_samp)
                    s_state_n = S_SAMP;
                else
                    s_state_n = s_state_c;
            end
            S_SEND:begin
                if(s_send2s_rele)
                    s_state_n = S_RELE;
                else
                    s_state_n = s_state_c;
            end
            S_SAMP:begin
                if(s_samp2s_rele)
                    s_state_n = S_RELE;
                else
                    s_state_n = s_state_c;
            end
            S_RELE:begin
                if(s_rele2s_done)
                    s_state_n = S_DONE;
                else if(s_rele2s_low)
                    s_state_n = S_LOW;
                else
                    s_state_n = s_state_c;
            end
            S_DONE:begin
                s_state_n = S_IDLE;
            end
          default:s_state_n = S_IDLE;
      endcase
  end

    assign s_idle2s_low  = s_state_c == S_IDLE && (m_state_c == M_ROMS ||
                            m_state_c == M_CONT || m_state_c == M_RCMD || m_state_c == M_RTMP);

    assign s_low2s_send  = s_state_c == S_LOW  && (m_state_c == M_ROMS ||
                            m_state_c == M_CONT || m_state_c == M_RCMD) && end_cnt1;// The host sends data  2us 

    assign s_low2s_samp  = s_state_c == S_LOW  && (m_state_c == M_RTMP && end_cnt1);// The slave sends temperature data  2us 
    assign s_send2s_rele = s_state_c == S_SEND && (end_cnt1);// Host read 1bit (60us Finish in )
    assign s_samp2s_rele = s_state_c == S_SAMP && (end_cnt1);// Host write 1bit (60us Finish in )
    assign s_rele2s_low  = s_state_c == S_RELE && (end_cnt1 && end_cnt_bit == 1'b0);// The host has finished reading and writing 1bit (3us)  Continue to the next bit
    assign s_rele2s_done = s_state_c == S_RELE && (end_cnt1 && end_cnt_bit == 1'b1);// The host has finished reading and writing 1bit (3us) bit finish writing sth. 

//1us Counter 
    [email protected](posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt_1us <= 0;
        end
        else if(add_cnt_1us) begin
            if(end_cnt_1us)begin
                cnt_1us <= 0;
            end
            else begin
                cnt_1us <= cnt_1us + 1;
            end
        end
    
    end
    assign add_cnt_1us = m_state_c != M_IDLE;// Not IDLE Status continuous count 
    assign end_cnt_1us = add_cnt_1us && cnt_1us == TIME_1US - 1;

    [email protected](posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt0 <= 0;
        end
        else if(add_cnt0) begin
            if(end_cnt0)begin
                cnt0 <= 0;
            end
            else begin
                cnt0 <= cnt0 + 1;
            end
        end
    
    end
    assign add_cnt0 = (m_state_c == M_REST || m_state_c == M_RELE || m_state_c == M_RACK || m_state_c == M_WAIT) && end_cnt_1us;
    assign end_cnt0 = add_cnt0 && cnt0 == X - 1;

    [email protected](posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            X <= 0;
        end
        else if(m_state_c == M_REST)begin// Reset :500us (480us)
            X <= TIME_RST;
        end
        else if(m_state_c == M_RELE)begin// Release the bus :20us (15-60us Inside )
            X <= TIME_REL;
        end
        else if(m_state_c == M_RACK)begin// Receive response :200us (60-240us)
            X <= TIME_PRE;
        end
        else if(m_state_c == M_WAIT) begin// wait for :750ms ( Wait for the conversion to complete )
            X <= TIME_WAIT;
        end
    end

    [email protected](posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt1 <= 0;
        end
        else if(add_cnt1) begin
            if(end_cnt1)begin
                cnt1 <= 0;
            end
            else begin
                cnt1 <= cnt1 + 1;
            end
        end
    
    end
    assign add_cnt1 = (s_state_c == S_LOW || s_state_c == S_SEND ||
                        s_state_c == S_SAMP || s_state_c == S_RELE) && end_cnt_1us;
    assign end_cnt1 = add_cnt1 && cnt1 == Y - 1;

    [email protected](posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            Y <= 0;
        end
        else if(s_state_c == S_LOW)begin
            Y <= TIME_LOW;// The host pulls down the bus  2us ( Greater than 1us)
        end
        else if(s_state_c == S_SEND || s_state_c == S_SAMP) begin
            Y <= TIME_RW;// Host read / write 1bit 60us ( At least 60us)
        end
        else begin
            Y <= TIME_REC;// The host has finished reading and writing 1bit Release the bus  3us ( At least 1us)
        end
    end

    [email protected](posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt_bit <= 0;
        end
        else if(add_cnt_bit) begin
            if(end_cnt_bit)begin
                cnt_bit <= 0;
            end
            else begin
                cnt_bit <= cnt_bit + 1;
            end
        end
    
    end
    assign add_cnt_bit = s_state_c == S_RELE && end_cnt1;
    assign end_cnt_bit = add_cnt_bit && cnt_bit == ((m_state_c == M_RTMP)?16-1:8-1);// Read the temperature status 16bit data , Other state 8bit data 

//slave_ack  The presence pulse of the sampling sensor 
    [email protected](posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            slave_ack <= 1'b1;
        end// Receive response status   The counter says 60us  sampling 
        else if(m_state_c == M_RACK && cnt0 == 60 && end_cnt_1us)begin
            slave_ack <= dq_in;
        end
    end

    [email protected](posedge clk or negedge rst_n)begin// Command send flag  ( Distinguish between temperature conversion and temperature reading commands )
        if(!rst_n)begin
            flag <= 0;
        end
        else if(m_wait2m_rest)begin
            flag <= 1'b1;
        end
        else if(m_rtmp2m_idle) begin
            flag <= 1'b0;
        end
    end

// The output signal 
    //dq_out
    [email protected](posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            dq_out <= 0;
        end
        else if(m_idle2m_rest | s_idle2s_low | s_rele2s_low | m_wait2m_rest)begin
            dq_out <= 1'b0;
        end
        else if(s_low2s_send) begin
            dq_out <= wr_data[cnt_bit];
        end
    end

    //dq_out_en
    [email protected](posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            dq_out_en <= 0;
        end
        else if(m_idle2m_rest | s_idle2s_low | s_rele2s_low | m_wait2m_rest)begin
            dq_out_en <= 1'b1;// Output  dq_out
        end
        else if(m_rest2m_rele | s_send2s_rele | s_low2s_samp) begin
            dq_out_en <= 1'b0;// No output dq_out
        end
    end

//wr_data  command 
    [email protected](posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            wr_data <= 0;
        end
        else if(m_rack2m_roms)begin///ROM Skip command 
            wr_data <= CMD_ROMS;
        end
        else if(m_roms2m_cont) begin// Temperature conversion command 
            wr_data <= CMD_CONT;
        end
        else if(m_roms2m_rcmd)begin// Read register temperature command 
            wr_data <= CDM_RTMP;
        end
    end
//orign_data  Temperature acquisition 
    [email protected](posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            orign_data <= 0;
        end
        else if(s_state_c == S_SAMP && cnt1 == 12 && end_cnt_1us)begin
            orign_data[cnt_bit] <= dq_in;
        end
    end

//temp_data  Temperature judgment 
    [email protected](posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            temp_data <=0;
        end
        else if(s_state_c == S_SAMP && cnt_bit == 15 && s_samp2s_rele)begin
            if(orign_data[15])
                temp_data <= ~orign_data[10:0] + 1'b1;// negative , Take the reverse and add one 
            else
                temp_data <= orign_data[10:0];// Positive numbers 
        end
    end

/* The actual temperature value is  temp_data * 0.0625;  In order to retain 4 Decimal precision , The actual temperature value is enlarged 10000 times ,  namely temp_data * 625;*/
    assign temp_data_w = temp_data * 625;

//temp_out
    [email protected](posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            temp_out <= 0;
        end
        else if(m_state_c == M_RTMP && s_rele2s_done)begin
            temp_out <= temp_data_w;
        end
    end

//temp_out_vld
    [email protected](posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            temp_out_vld <= 0;
        end
        else begin
            temp_out_vld <= m_state_c == M_RTMP && s_rele2s_done;
        end
    end

//temp_sign
    [email protected](posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            temp_sign <= 0;
        end
        else if(s_state_c == S_SAMP && cnt_bit == 15 && s_samp2s_rele)begin
            temp_sign <= orign_data[15];
        end
    end

endmodule

2.2 Data processing module

module ctrl(
    input                           clk     ,// Clock signal 
    input                           rst_n   ,// Reset signal 
    input                           din_sign,
    input           [23:0]          din     ,
    input                           din_vld ,
       
    output                          dout_sign,
    output          [23:0]          dout    ,
    output  reg                     dout_vld
);

    // Intermediate signal definition 
    reg     [23:0]      din_r       ;
    reg                 din_vld_r0  ;
    reg                 din_vld_r1  ;

    wire    [7:0]       tmp_int_w   ;// Integral part 
    reg     [7:0]       tmp_int_r   ;

    wire    [3:0]       tmp_int_w2  ;
    wire    [3:0]       tmp_int_w1  ;
    wire    [3:0]       tmp_int_w0  ;

    reg     [3:0]       tmp_int_r2  ;
    reg     [3:0]       tmp_int_r1  ;
    reg     [3:0]       tmp_int_r0  ;

    wire    [15:0]      tmp_dot_w   ;// The fractional part 
    reg     [15:0]      tmp_dot_r   ;

    wire    [3:0]       tmp_dot_w3  ;
    wire    [3:0]       tmp_dot_w2  ;
    wire    [3:0]       tmp_dot_w1  ;
    wire    [3:0]       tmp_dot_w0  ;

    reg     [3:0]       tmp_dot_r3  ;
    reg     [3:0]       tmp_dot_r2  ;
    reg     [3:0]       tmp_dot_r1  ;
    reg     [3:0]       tmp_dot_r0  ;

//din_r
    [email protected](posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            din_r <= 0;
        end
        else if(din_vld)begin
            din_r <= din;
        end
    end

//din_vld_r0 din_vld_r1  Shooting 
    [email protected](posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            din_vld_r0 <= 0;
            din_vld_r1 <= 0;
        end
        else begin
            din_vld_r0 <= din_vld;
            din_vld_r1 <= din_vld_r0;
        end
    end

    assign tmp_int_w = din_r/10000;
    assign tmp_dot_w = din_r%10000;

    [email protected](posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            tmp_int_r <= 0;
        end
        else if(din_vld_r0)begin
            tmp_int_r <= tmp_int_w;
            tmp_dot_r <= tmp_dot_w;
        end
    end

    assign tmp_int_w2 = tmp_int_r/100;// Hundred bit 
    assign tmp_int_w1 = tmp_int_r/10%10;// ten 
    assign tmp_int_w0 = tmp_int_r%10;// bits 

    [email protected](posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            tmp_int_r2 <= 0;
            tmp_int_r1 <= 0;
            tmp_int_r0 <= 0;
        end
        else if(din_vld_r1)begin
            tmp_int_r2 <= tmp_int_w2;
            tmp_int_r1 <= tmp_int_w1;
            tmp_int_r0 <= tmp_int_w0;
        end
    end

    assign tmp_dot_w0 = tmp_dot_r/1000;
    assign tmp_dot_w1 = tmp_dot_r/100%10;
    assign tmp_dot_w2 = tmp_dot_r/10%10;
    assign tmp_dot_w3 = tmp_dot_r%10;

    [email protected](posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            tmp_dot_r0 <= 0;          
            tmp_dot_r1 <= 0;      
            tmp_dot_r2 <= 0;      
            tmp_dot_r3 <= 0;      
        end
        else if(din_vld_r1)begin
            tmp_dot_r0 <= tmp_dot_w0;          
            tmp_dot_r1 <= tmp_dot_w1;      
            tmp_dot_r2 <= tmp_dot_w2;      
            tmp_dot_r3 <= tmp_dot_w3;      
        end
    end
    assign dout = {
    tmp_int_r1,tmp_int_r0,tmp_dot_r0,tmp_dot_r1,tmp_dot_r2,tmp_dot_r3};

    [email protected](posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            dout_vld <= 1'b0;
        end
        else begin
            dout_vld <= din_vld_r1;
        end
    end

    assign dout_sign = din_sign;

endmodule

2.3 Digital tube driver module

module seg_driver(
    input                    clk     ,// Clock signal 
    input                    rst_n   ,// Reset signal 
    input                    din_sign,
    input        [23:0]      din     ,
    input                    din_vld ,

    output  reg  [5:0]       sel     ,
    output  reg  [7:0]       dig     
);

// Parameters are defined 
parameter       TIME_1MS = 25_000,

                ZERO     = 7'b100_0000,
                ONE      = 7'b111_1001,
                TWO      = 7'b010_0100,
                THREE    = 7'b011_0000,
                FOUR     = 7'b001_1001,
                FIVE     = 7'b001_0010,
                SIX      = 7'b000_0010,
                SEVEN    = 7'b111_1000,
                EIGHT    = 7'b000_0000,
                NINE     = 7'b001_0000,
                P        = 7'b000_1111,
                N        = 7'b011_1111;

// Signal definition 
reg     [19:0]      cnt_1ms;// Scan frequency counter 
wire                add_cnt_1ms;
wire                end_cnt_1ms;

reg     [3 :0]      disp_num;
reg                 dot;

// Digital tube scanning frequency counting 
[email protected](posedge clk or negedge rst_n)begin
   if(!rst_n)begin
      cnt_1ms <= 0;
   end
   else if(add_cnt_1ms) begin
      if(end_cnt_1ms)begin
         cnt_1ms <= 0;
      end
      else begin
         cnt_1ms <= cnt_1ms + 1;
      end
   end

end
assign add_cnt_1ms = 1'b1;
assign end_cnt_1ms = add_cnt_1ms && cnt_1ms == TIME_1MS - 1;


//seg_sel  Nixie tube chip selection signal 
[email protected](posedge clk or negedge rst_n)begin
   if(!rst_n)begin
      sel <= 6'b111110;
   end
   else if(end_cnt_1ms) begin
      sel <= {
    sel[4:0],sel[5]};
   end
end

// decoding 
[email protected](posedge clk or negedge rst_n)begin
   if(!rst_n)begin
      disp_num  <= 0;
   end
   else begin
      case(sel)
         6'b011111:begin disp_num <= din_sign?4'ha:4'hb;dot <= 1; end
         6'b101111:begin disp_num <= din[23:20];dot <= 1;end
         6'b110111:begin disp_num <= din[19:16];dot <= 0;end
         6'b111011:begin disp_num <= din[15:12];dot <= 1;end
         6'b111101:begin disp_num <= din[11:8] ;dot <= 1;end
         6'b111110:begin disp_num <= din[7 :4] ;dot <= 1;end
         default  :begin disp_num <= 4'hF ;end
      endcase
   end
end 


//segment  Segment selection decoding 
[email protected](posedge clk or negedge rst_n)begin
   if(!rst_n)begin
      dig <= 8'hff;
   end
   else begin// Show decimal point 
      case(disp_num)
         4'h0:dig <= {
    dot,ZERO }  ;
         4'h1:dig <= {
    dot,ONE  }  ;
         4'h2:dig <= {
    dot,TWO  }  ;
         4'h3:dig <= {
    dot,THREE}  ;
         4'h4:dig <= {
    dot,FOUR }  ;
         4'h5:dig <= {
    dot,FIVE }  ;
         4'h6:dig <= {
    dot,SIX  }  ;
         4'h7:dig <= {
    dot,SEVEN}  ;
         4'h8:dig <= {
    dot,EIGHT}  ;
         4'h9:dig <= {
    dot,NINE }  ;
         4'ha:dig <= {
    dot,N    }  ;
         4'hb:dig <= {
    dot,P    }  ;
         default:dig <= 8'hff ;
      endcase
   end
end
endmodule

2.4 Top level modules

module ds18b20_top(
    input           clk     ,// Clock signal 
    input           rst_n   ,// Reset signal 

    inout           dq      ,// Sensor bus 

    output  [5:0]   sel     ,
    output  [7:0]   dig
);

// Signal definition 
    wire            dq_in       ;
    wire            dq_out      ;
    wire            dq_out_en   ;
    wire            temp_sign   ;
    wire    [23:0]  temp_out    ;
    wire            temp_out_vld;
    wire            dout_sign   ;
    wire    [23:0]  dout        ;
    wire            dout_vld    ;

    assign dq = dq_out_en?dq_out:1'bz;
    assign dq_in = dq;


// Modularization 
ds18b20_driver u_ds18b20_driver(
    .clk            (clk            ),
    .rst_n          (rst_n          ),
    .dq_in          (dq_in          ),//dq Bus DS18B20 Output 
    .dq_out         (dq_out         ),//dq Bus FPGA Output ,DS18B20 Input 
    .dq_out_en      (dq_out_en      ),//dq Bus output enable control signal 
    .temp_sign      (temp_sign      ),// Positive and negative temperature 
    .temp_out       (temp_out       ),// Output decimal temperature 
    .temp_out_vld   (temp_out_vld   ) // The temperature acquisition data is valid 
);

ctrl u_ctrl(
    .clk            (clk            ),
    .rst_n          (rst_n          ),
    .din_sign       (temp_sign      ),
    .din            (temp_out       ),
    .din_vld        (temp_out_vld   ),
    .dout_sign      (dout_sign      ), 
    .dout           (dout           ),// Output the temperature value of the corresponding position of the nixie tube bcd code 
    .dout_vld       (dout_vld       )
);

seg_driver seg_driver(
    .clk            (clk            ),
    .rst_n          (rst_n          ),
    .din_sign       (temp_sign      ),
    .din            (dout           ),
    .din_vld        (dout_vld       ),
    .sel            (sel            ),
    .dig            (dig            )
);

endmodule

3. Simulation

ds18b20 Module test file

`timescale 1ns/1ps

module ds18b20_driver_tb();

// Parameters are defined 
    parameter CYCLE = 20;
    defparam  u_ds18b20_driver.TIME_RST = 200,
              u_ds18b20_driver.TIME_PRE = 100,
              u_ds18b20_driver.TIME_WAIT = 750;


// Signal definition 
    reg                     clk         ;
    reg                     rst_n       ;
    reg                     dq_in       ;

    wire                    dq_out      ;
    wire                    dq_out_en   ;
    wire                    temp_sign   ;
    wire    [23:0]          temp_out    ;
    wire                    temp_out_vld;

// Modularization 
ds18b20_driver u_ds18b20_driver(
    .clk                (clk         ),// Clock signal 
    .rst_n              (rst_n       ),// Reset signal 
    .dq_in              (dq_in       ),  

    .dq_out             (dq_out      ),//dq Bus FPGA Output  
    .dq_out_en          (dq_out_en   ),// Output data valid signal 
    .temp_sign          (temp_sign   ),// Temperature value sign bit  0: just  1: negative 
    .temp_out           (temp_out    ),// Temperature output 
    .temp_out_vld       (temp_out_vld) // Temperature output valid signal  
);

    always #(CYCLE/2) clk = ~clk;

    integer i=0;
    initial begin
        clk = 1'b1;
        rst_n = 1'b0;
        dq_in = 0;
        #(CYCLE*20);
        rst_n = 1'b1;
        repeat(5)begin
            for(i=0;i<500000;i=i+1)begin
                dq_in = {
    $random};
                #(CYCLE*20);
            end
            #(CYCLE*20);
        end
        $stop;
    end
endmodule

Host state machine from IDLE–>REST:
stay IDLE The state changes directly to REST state .
 Insert picture description here

 Insert picture description here
Host state machine from REST–>RELE–>RACK:
The reset pulse should last 500us( In the simulation file, it is modified as 200us) Will be transferred to the released state , And the release state lasts 20us The post transition is to receive the presence pulse state .
 Insert picture description here
 Insert picture description here
Host state machine RACK–>ROM:
The receive presence pulse status persists 200us( The simulation file is changed to 100us) And the sampling value is 0 After that, it is transferred to ROM Command status ( Since there is only one temperature sensor , The skip command is used here ).

 Insert picture description here

 Insert picture description here

Slave state machine IDLE–>LOW–>SEND:
 Insert picture description here
ROM The order is over , The slave state machine transfers from the sending state to the releasing state and recovers the time slot , Then pull down the bus , The beginning of a new time slot .
 Insert picture description here
A little

原网站

版权声明
本文为[A witty orange]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/164/202206130645014281.html