Système d'acquisition de données basé sur FPGA (trois) final

table des matières

8. Module de commande de bouton

Neuf, module de commande FIFO

10. Module de commande DAC

11. Intégration du système


Lien de téléchargement de ce fichier de projet de conception (y compris les notes): https://download.csdn.net/download/qq_33231534/12450178  


Les deux premiers articles ont été élaborés sur les modules de base du système d'acquisition de données.Les suivants présenteront les modules de commande pour l'interconnexion et la communication de ces modules de base, y compris le module de commande par boutons et le module de commande FIFO.

8. Module de commande de bouton

La fonction principale du module de commande de bouton est la suivante: lorsque le bouton est enfoncé, il contrôle les temps de conversion analogique-numérique ADC.

La liste des ports de signal de ce module est la suivante:

Tableau 8.1 Liste des signaux du port du module de commande des touches
Nom du signal E / S Chiffres Description de la fonction
clk je 1 Horloge système 50 MHz
rst_n je 1 Réinitialisation du système
key_flag je 1 Signal valide du bouton
tran_num je 7 Les conversions
adc_done je 1 Indicateur de conversion ADC terminée
adc_en LES 1 Indicateur d'activation de la conversion ADC

Le code du module est: key_ctrl.v

//-------------------------------------------------------------------
//https://blog.csdn.net/qq_33231534 PHF的CSDN   
//File name:           key_ctrl.v
//Last modified Date:  2020/5/23
//Last Version:        
//Descriptions:        按键控制模块:按键按下,控制ADC转换tran_num次
//-------------------------------------------------------------------

module key_ctrl(
    input                   clk         , //系统时钟50MHz
    input                   rst_n       , //系统复位
    input                   key_flag    , //按键有效信号
    input   [ 6: 0]         tran_num    , //转换次数
    input                   adc_done    , //ADC一次转换完成标志
    output  reg             adc_en        //ADC转换使能标志      
);

reg   [  6: 0]         cnt          ; //计数器,计数ADC转换次数
reg                    add_flag     ; //计数器加1标志
wire                   add_cnt      ; //加一条件
wire                   end_cnt      ; //结束条件

//按键按下,add_flag为1,开始计数
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        add_flag <= 0;
    end
    else if(key_flag) begin
        add_flag <= 1;
    end
    else if(end_cnt)begin
        add_flag <= 0;
    end
end

//计数器,ADC使能一次,计数器加1
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt <= 0;
    end
    else if(add_cnt)begin
        if(end_cnt)
            cnt <= 0;
        else
            cnt <= cnt + 1'b1;
    end
end

assign add_cnt = add_flag==1 && adc_en;       
assign end_cnt = add_cnt && cnt== tran_num-1;   

//adc_en输出控制
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        adc_en <= 0;
    end
    else if(key_flag || (add_flag && adc_done)) begin
        adc_en <= 1;
    end
    else begin
        adc_en <= 0;
    end
end
endmodule

Comme cette partie est relativement simple, aucun diagramme de forme d'onde de simulation n'est fourni.


Neuf, module de commande FIFO

La fonction du module de contrôle FIFO est la suivante: lorsque la conversion ADC est terminée, les données sont stockées dans le FIFO, et en même temps, lorsque les données sont envoyées au port série, les données sont lues à partir du FIFO et les données 12 bits sont divisées en deux 8 bits et envoyées au port série.

La liste des ports de signal de ce module est la suivante:

Tableau 9.1: Liste des ports de signal du module de commande FIFO
Nom du signal E / S Chiffres Description de la fonction
clk je 1 Horloge système 50 MHz
rst_n je 1 Réinitialisation du système
vide je 1 signal nul de données fifo
tx_done je 1 Indicateur de transmission de données en série terminée
q je 12 Données lues depuis fifo
adc_done je 1 Conversion ADC terminée une fois l'indicateur
adc_data_out je 12 Données 12 bits converties par ADC
rdreq LES 1 autorisation de lecture fifo
send_en LES 1 Activation de l'envoi du port série
data_byte LES 8 Sortie des données envoyées
Wrreq LES 1 Activation d'écriture FIFO, définie sur 1 une fois la conversion ADC terminée
data_to_fifo LES 12 Les données converties par ADC sont stockées dans FIFO

Le code du module de contrôle FIFO est: fifo_ctrl.v

//-------------------------------------------------------------------
//https://blog.csdn.net/qq_33231534 PHF的CSDN   
//File name:           fifo_ctrl.v
//Last modified Date:  2020/5/23
//Last Version:        
//Descriptions:        FIFO控制模块:当ADC转换完成后,将数据存入FIFO,
//                     同时在往串口发送数据时控制从FIFO读取数据并将12位
//                     数据分成两次8位发送到串口
//-------------------------------------------------------------------

module fifo_ctrl(
    input                   clk         , //系统时钟50MHz
    input                   rst_n       , //系统复位
    input                   empty       , //fifo数据空信号
    input                   tx_done     , //串口数据发送完成标志
    input   [ 11: 0]        q           , //从fifo读出的数据
    input                   adc_done    , //ADC转换完成一次标志
    input   [ 11: 0]        adc_data_out, //ADC转换完成的12位数据

    output reg              rdreq       , //fifo读使能
    output reg              send_en     , //串口发送使能
    output reg [7:0]        data_byte   , //输出发送的数据
    output reg              wrreq       , //FIFO写使能,在ADC转换结束后置1
    output reg [11:0]       data_to_fifo  //ADC转换完成的数据存入FIFO
);

parameter IDLE      = 3'b000     ; //空闲状态
parameter DATA_R    = 3'b001     ; //当fifo数据不为空时,读取fifo数据
parameter DATA_S    = 3'b010     ; //将fifo的12位数据发送出去
parameter SEND_1    = 3'b011     ; //发送前4位数据
parameter SEND_2    = 3'b100     ; //发送后8位数据

reg   [  2: 0]         state_c      ; //状态改变
reg   [  2: 0]         state_n      ; //现在状态

//状态机
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        state_c <= IDLE;
    end
    else begin
        state_c <= state_n;
    end
end

//状态改变条件
always  @(*)begin
    case(state_c)
        IDLE:begin
                if(empty==0)
                    state_n = DATA_R;
                else
                    state_n = state_c;
             end
        DATA_R:state_n = DATA_S;
        DATA_S:state_n = SEND_1;
        SEND_1:begin
                  if(tx_done)
                      state_n = SEND_2;
                  else
                      state_n = state_c;
               end
        SEND_2:begin
                  if(tx_done)
                      state_n = IDLE;
                  else
                      state_n = state_c;
               end                  
    endcase
end

//各个状态下rdreq和send_en输出的结果
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        rdreq <= 0;
        send_en <= 0;
    end
    else begin
        case(state_c)
            IDLE:  begin
                       if(empty==0)
                           rdreq <= 1;
                       else
                           rdreq <= 0;
                   end
            DATA_R:begin rdreq <= 0; end
            DATA_S:begin send_en <= 1; data_byte <= {4'd0,q[11:8]}; end
            SEND_1:begin 
                       send_en <= 0; 
                       if(tx_done)begin
                           send_en <= 1;
                           data_byte <= q[7:0];
                       end
                   end
            SEND_2:begin send_en <= 0; end                
        endcase
    end
end

//ADC转换完成后将数据存入FIFO
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        data_to_fifo <= 0;
    end
    else if(adc_done) begin
        data_to_fifo <= adc_data_out;
    end
end

//ADC转换完成写使能打开
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        wrreq <= 0;
    end
    else if(adc_done) begin
        wrreq <= 1;
    end
    else begin
        wrreq <= 0;
    end
end

endmodule

Le test de simulation est le suivant:


10. Module de commande DAC

La fonction du module de contrôle DAC est la suivante: lors de la réception de la commande spécifiée par le port série, il commence à convertir les données sinusoïdales de la ROM en DAC.

La liste des ports de signal de ce module est la suivante:

Tableau 10.1: Liste des ports de signal du module de commande DAC
Nom du signal E / S Chiffres Description de la fonction
clk je 1 Horloge système 50 MHz
rst_n je 1 Réinitialisation du système
data_rx je 8 Commande reçue du port série
rx_done je 1 1 octet de données du port série recevant l'indicateur d'achèvement
dac_done je 1 Indicateur de conversion DAC terminée
adr LES 12 Ligne d'adresse ROM
dac_en LES 1 Indicateur d'activation de la conversion DAC

Le code du module de contrôle DAC est: dac_ctrl.v

//-------------------------------------------------------------------
//https://blog.csdn.net/qq_33231534 PHF的CSDN   
//File name:           dac_ctrl.v 
//Last modified Date:  2020/5/23
//Last Version:        
//Descriptions:        DAC控制模块:当接收串口指定的指令时,
//                     开始将ROM的正弦数据进行DAC转换
//-------------------------------------------------------------------

module dac_ctrl(
    input                   clk         ,//系统时钟50MHz
    input                   rst_n       ,//系统复位
    input   [ 7: 0]         data_rx     ,//从串口接收到的指令
    input                   rx_done     ,//1字节串口数据接收完成标志
    input                   dac_done    ,//DAC转换完成标志
    output  reg [11:0]      addr        ,//ROM的地址线
    output  reg             dac_en       //DAC转换使能标志
);

//控制地址线自加1
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        addr <= 0;
    end
    else if(dac_en) begin
        addr <= addr + 1'b1;
    end
end

//DAC转换使能标志
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        dac_en <= 0;
    end
    else if(rx_done || dac_done) begin
        dac_en <= 1;
    end
    else begin
        dac_en <= 0;
    end
end

endmodule

Ce module est relativement simple et ne fait pas de débogage de simulation.


11. Intégration du système

Après avoir terminé le test de conception et de simulation de tous les modules, intégrez les modules de l'ensemble du système, créez un nouveau fichier à barres de niveau supérieur, instanciez et connectez chaque module.

Le code est le suivant: data_collection_top.v

//-------------------------------------------------------------------
//https://blog.csdn.net/qq_33231534 PHF的CSDN   
//File name:           
//Last modified Date:  
//Last Version:        
//Descriptions:        
//-------------------------------------------------------------------

module data_collection_top(
    input                   clk         ,//系统时钟50MHz
    input                   rst_n       ,//系统复位
    input                   rs232_tx    ,//串口向FPGA发送数据
    input                   adc_data_din,//adc数据输出到FPGA
    input                   key_in      ,//按键输入

    output wire             dac_din     ,//dac串行数据接口控制和数据输出
    output wire             dac_sclk    ,//dac串行数据接口时钟信号
    output wire             dac_cs      ,//dac串行数据接口使能信号
    output wire             adc_din     ,//ADC控制信号,通道控制选取
    output wire             adc_sclk    ,//ADC串行数据接口时钟信号
    output wire             adc_cs      ,//ADC串行数据接口使能信号
    output wire             rs232_rx     //串口接收FPGA数据

);

wire  [  7: 0]         data_rx      ;
wire                   rx_done      ;
wire                   dac_en       ;
wire  [ 11: 0]         addr         ;
wire                   dac_done     ;
wire  [ 11: 0]         data_rom     ;
wire                   empty        ;
wire                   adc_en       ;
wire                   key_flag     ;
wire                   adc_done     ;
wire                   tx_done      ;
wire                   rdreq        ;
wire                   send_en      ;
wire  [  7: 0]         data_byte    ;
wire                   wrreq        ;
wire  [ 11: 0]         data_to_fifo ;
wire  [ 11: 0]         adc_data_out ;
wire  [ 11: 0]         fifo_data_out;

//串口接收模块
UART_Byte_Rx u_UART_Byte_Rx(
    .clk       (clk)        ,
    .rst_n     (rst_n)      ,
    .rs232_tx  (rs232_tx)   ,
    .baud_set  (3'd1)       ,

    .data_byte (data_rx)    ,
    .rx_done   (rx_done)      
);

//DAC控制模块
dac_ctrl u_dac_ctrl(
    .clk       (clk)        ,
    .rst_n     (rst_n)      ,
    .data_rx   (data_rx)    ,
    .rx_done   (rx_done)    ,
    .dac_done  (dac_done)   ,

    .addr      (addr)       ,
    .dac_en    (dac_en) 
);

//ROM模块
single_port_rom
#(.DATA_WIDTH(12), .ADDR_WIDTH(12))
u_single_port_rom(
	.addr   (addr)  ,
	.clk    (clk)   ,

	.q      (data_rom)  
);

//DAC驱动模块
dac_driver1 u_dac_driver(
    .clk        (clk)               ,
    .rst_n      (rst_n)             ,
    .dac_data_in({4'b1100,data_rom}),
    .dac_en     (dac_en)            ,

    .din        (dac_din)           ,
    .dac_sclk   (dac_sclk)          ,
    .cs         (dac_cs)            ,
    .dac_down   (dac_done)          ,
    .dac_state  ()                    
);

//ADC驱动模块
adc_driver u_adc_driver(
    .clk       (clk)            ,//系统时钟50MHz
    .rst_n     (rst_n)          ,//复位
    .channel   (3'd0)           ,//通道选择
    .adc_en    (adc_en)         ,//使能单次转换,该信号为周期有效高脉冲使能一次转换
    .dout      (adc_data_din)   ,//ADC转换结果,由ADC输给FPGA

    .din       (adc_din)        ,//ADC控制信号,通道控制选择
    .adc_sclk  (adc_sclk)       ,//ADC串行数据接口时钟信号
    .cs        (adc_cs)         ,//ADC串行数据接口使能信号
    .data_out  (adc_data_out)   ,//ADC转换结果
    .adc_done  (adc_done)       ,//转换完成信号,完成后输出一个周期高脉冲
    .adc_state ()                //ADC工作状态:0为空闲状态,1为转换状态      
);

//按键控制模块
key_ctrl u_key_ctrl(
    .clk       (clk)        ,
    .rst_n     (rst_n)      ,
    .key_flag  (key_flag)   , //按键信号
    .tran_num  (7'd100)     , //转换次数
    .adc_done  (adc_done)   ,    

    .adc_en    (adc_en)             
);

//按键消抖模块
key_filter u_key_filter(
    .clk       (clk)        ,
    .rst_n     (rst_n)      ,
    .key_in    (key_in)     ,

    .key_flag  (key_flag)   ,
    .key_state ()           
);

//FIFO控制模块
fifo_ctrl u_fifo_ctrl(
    .clk         (clk)         , //系统时钟50MHz
    .rst_n       (rst_n)       , //系统复位
    .empty       (empty)       , //fifo数据空信号
    .tx_done     (tx_done)     , //串口数据发送完成标志
    .q           (fifo_data_out)            , //从fifo读出的数据
    .adc_done    (adc_done)    ,
    .adc_data_out(adc_data_out),

    .rdreq       (rdreq)        , //fifo读使能
    .send_en     (send_en)      , //串口发送使能
    .data_byte   (data_byte)    ,  //输出发送的数据
    .wrreq       (wrreq)        ,
    .data_to_fifo(data_to_fifo) 
);

//同步FIFO模块
sync_fifo 
#(.WIDTH        (12)    ,      //缓存的数据宽度
  .DEPTH        (100)   ,      //缓存的数据深度
  .MAX_DEPTH_BIT(7))           //可设置的最大深度位数7,即最大深度为2^7-1
u_sync_fifo
(
    .clk     (clk)          , //系统时钟
    .rst_n   (rst_n)        , //系统复位
    .wrreq   (wrreq)        , //写使能
    .data    (data_to_fifo) , //写数据
    .rdreq   (rdreq)        , //读使能

    .q       (fifo_data_out)            , //读数据
    .empty   (empty)        , //空信号
    .full    ()             , //满信号
    .half    ()             , //半满信号
    .usedw   ()               //fifo中剩余数据个数    
);

//串口发送模块
Uart_Byte_Tx u_Uart_Byte_Tx(
    .clk       (clk)        ,
    .rst_n     (rst_n)      ,
    .send_en   (send_en)    ,
    .data_byte (data_byte)  ,
    .baud_set  (3'd1)       ,

    .rs232_tx  (rs232_rx)   ,
    .tx_done   (tx_done)    ,
    .uart_state()                  
);

endmodule

Après analyse et synthèse sur le logiciel quartus prime17.1, les affectations des broches sont effectuées en fonction de la connexion du circuit, comme indiqué sur la figure:

Après la compilation complète, téléchargez le fichier sof sur la carte et connectez le port de sortie A du DAC au port 1 canal de l'ADC avec une ligne DuPont pour terminer la connexion du circuit. Ensuite, ouvrez l'assistant de port série, utilisez hexadécimal pour envoyer et recevoir l'affichage, envoyez d'abord la commande pour contrôler la conversion DA vers le port série (ici réglé sur ff), de sorte que le DAC convertisse et émette le signal sinusoïdal analogique en fonction du signal sinusoïdal dans la ROM. Appuyez ensuite à nouveau sur le bouton pour contrôler la conversion ADC 100 fois, et la sortie vers le port série pour l'affichage sur le PC.

Le schéma de relaxation et de réception de son port série est le suivant:

Parmi eux, tous les 16 bits de données représentent un résultat de conversion ADC, par exemple, les premières données 06 1C, les quatre premiers bits sont tous à 0. Ceci est défini pour la commodité de l'envoi de données par le port série, le résultat d'échantillonnage ADC réel est 0x61C.

La vue RTL globale est la suivante:

 

Je suppose que tu aimes

Origine blog.csdn.net/qq_33231534/article/details/106296574
conseillé
Classement