USB传输ADC数据之FPGA整体工程逻辑梳理

数据流帧封装模块

这一模块的实现是相对简单的,只需要注意数据对齐就好,虽然USB传输为8位并口,但考虑到数据都是以4字节为单位,故扩展帧头为2字节,类型为1字节,长度为1字节,便于上位机进行数据的处理。
代码的主要思路是检测有效信号的上升沿,表示第一个数据到来,并且数据流是连贯的,在信号的上升沿,需要判断数据的类型以及传输长度,消耗1个时钟周期。再下一个时钟周期,则进行帧头类型长度信息的传输,故有效数据需要延迟两个时钟周期,再进行传输,并且因为需要传输帧尾,故将有效指示信号延迟3个时钟周期。
ADC数据、FFT数据的处理流程大致都是一样的,关于最大幅值和信号频率,因为是并行传输,故需要再多延迟一个时钟周期,具体的代码如下

module frame_pack(
    input               i_clk                   ,
    input               i_rst                   ,
    input   [31:0]      i_usb_adc_data          ,
    input               i_usb_adc_valid         ,
    input   [31:0]      i_usb_fft_data          ,
    input               i_usb_fft_valid         ,
    input   [31:0]      i_usb_max_pow           ,
    input   [31:0]      i_usb_max_index         ,
    input               i_usb_max_valid         ,
    input   [15:0]      i_usb_data_len          ,
    output  [31:0]      o_usb_frame_adc_data    ,
    output              o_usb_frame_adc_valid   ,
    output  [31:0]      o_usb_frame_fft_data    ,
    output              o_usb_frame_fft_valid   ,
    output  [31:0]      o_usb_frame_max_data    ,
    output              o_usb_frame_max_valid   
    );

localparam              P_FREAM_HEAD    = 8'hA5 ,
                        P_FREAM_END     = 8'hD5 ;
reg                     ri_usb_adc_valid        ;
reg                     ri_usb_fft_valid        ;
reg                     ri_usb_max_valid        ;
reg                     ri_usb_adc_valid_dly    ;
reg                     ri_usb_fft_valid_dly    ;
reg                     ri_usb_adc_valid_dly2   ;
reg                     ri_usb_fft_valid_dly2   ;
reg                     ri_usb_max_valid_dly    ;
reg                     ri_usb_max_valid_dly2   ;
reg                     ri_usb_max_valid_dly3   ;
reg     [31:0]          ri_usb_adc_data         ;
reg     [31:0]          ri_usb_fft_data         ;
reg     [31:0]          ri_usb_max_pow          ;
reg     [31:0]          ri_usb_max_index        ;
reg     [31:0]          ri_usb_adc_data_dly     ;
reg     [31:0]          ri_usb_fft_data_dly     ;
reg     [31:0]          ri_usb_max_pow_dly      ;
reg     [31:0]          ri_usb_max_index_dly    ;
reg     [31:0]          ri_usb_max_index_dly2   ;
reg     [7 :0]          r_frmae_data_type       ;
reg     [7 :0]          r_frmae_data_len        ;
reg     [31:0]          ro_usb_frame_adc_data   ;
reg                     ro_usb_frame_adc_valid  ;
reg     [31:0]          ro_usb_frame_fft_data   ;
reg                     ro_usb_frame_fft_valid  ;
reg     [31:0]          ro_usb_frame_max_data   ;
reg                     ro_usb_frame_max_valid  ;
reg                     rw_usb_adc_valid_pos    ;
reg                     rw_usb_fft_valid_pos    ;
reg                     rw_usb_max_valid_pos    ;
wire                    w_usb_adc_valid_pos     ;
wire                    w_usb_fft_valid_pos     ;
wire                    w_usb_max_valid_pos     ;

assign  w_usb_adc_valid_pos = i_usb_adc_valid & (!ri_usb_adc_valid);
assign  w_usb_fft_valid_pos = i_usb_fft_valid & (!ri_usb_fft_valid);
assign  w_usb_max_valid_pos = i_usb_max_valid & (!ri_usb_max_valid);
assign  o_usb_frame_adc_data  = ro_usb_frame_adc_data ;
assign  o_usb_frame_adc_valid = ro_usb_frame_adc_valid;
assign  o_usb_frame_fft_data  = ro_usb_frame_fft_data ;
assign  o_usb_frame_fft_valid = ro_usb_frame_fft_valid;
assign  o_usb_frame_max_data  = ro_usb_frame_max_data ;
assign  o_usb_frame_max_valid = ro_usb_frame_max_valid;
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) begin       
        ri_usb_adc_valid     <= 'd0;
        ri_usb_fft_valid     <= 'd0;
        ri_usb_max_valid     <= 'd0;
        ri_usb_adc_valid_dly <= 'd0;
        ri_usb_fft_valid_dly <= 'd0;
        ri_usb_adc_valid_dly2<= 'd0;
        ri_usb_fft_valid_dly2<= 'd0;
        ri_usb_max_valid_dly <= 'd0;
        ri_usb_max_valid_dly2<= 'd0;
        ri_usb_max_valid_dly3<= 'd0;
        ri_usb_adc_data      <= 'd0;
        ri_usb_fft_data      <= 'd0;
        ri_usb_max_pow       <= 'd0;
        ri_usb_max_index     <= 'd0;
        ri_usb_adc_data_dly  <= 'd0;
        ri_usb_fft_data_dly  <= 'd0;
        ri_usb_max_pow_dly   <= 'd0;
        ri_usb_max_index_dly <= 'd0;
        ri_usb_max_index_dly2<= 'd0;
    end
    else begin
        ri_usb_adc_valid     <= i_usb_adc_valid ;
        ri_usb_fft_valid     <= i_usb_fft_valid ;
        ri_usb_max_valid     <= i_usb_max_valid ;
        ri_usb_adc_valid_dly <= ri_usb_adc_valid;
        ri_usb_fft_valid_dly <= ri_usb_fft_valid;
        ri_usb_adc_valid_dly2<= ri_usb_adc_valid_dly;
        ri_usb_fft_valid_dly2<= ri_usb_fft_valid_dly;
        ri_usb_max_valid_dly <= ri_usb_max_valid;
        ri_usb_max_valid_dly2<= ri_usb_max_valid_dly;
        ri_usb_max_valid_dly3<= ri_usb_max_valid_dly2;
        ri_usb_adc_data      <= i_usb_adc_data  ;
        ri_usb_fft_data      <= i_usb_fft_data  ;
        ri_usb_max_pow       <= i_usb_max_pow   ;
        ri_usb_max_index     <= i_usb_max_index ;
        ri_usb_adc_data_dly  <= ri_usb_adc_data ;
        ri_usb_fft_data_dly  <= ri_usb_fft_data ;
        ri_usb_max_pow_dly   <= ri_usb_max_pow  ;
        ri_usb_max_index_dly <= ri_usb_max_index;
        ri_usb_max_index_dly2<= ri_usb_max_index_dly;
    end
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_frmae_data_type <= 'd0;
    else if(w_usb_adc_valid_pos)
        r_frmae_data_type <= 8'h01;
    else if(w_usb_fft_valid_pos)
        r_frmae_data_type <= 8'h02;
    else if(w_usb_max_valid_pos)
        r_frmae_data_type <= 8'h03;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_frmae_data_len <= 'd0;
    else if(w_usb_adc_valid_pos || w_usb_fft_valid_pos) begin
        if(i_usb_data_len == 'd2048)
            r_frmae_data_len <= 8'h01;
        else if(i_usb_data_len == 'd4096)
            r_frmae_data_len <= 8'h02;
        else if(i_usb_data_len == 'd48192)
            r_frmae_data_len <= 8'h03;
    end
    else if(w_usb_max_valid_pos)
        r_frmae_data_len <= 8'h04;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) begin
        rw_usb_adc_valid_pos <= 'd0;
        rw_usb_fft_valid_pos <= 'd0;
        rw_usb_max_valid_pos <= 'd0;
    end
    else begin
        rw_usb_adc_valid_pos <= w_usb_adc_valid_pos;
        rw_usb_fft_valid_pos <= w_usb_fft_valid_pos;
        rw_usb_max_valid_pos <= w_usb_max_valid_pos;
    end
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ro_usb_frame_adc_data <= 'd0;
    else if(rw_usb_adc_valid_pos)
        ro_usb_frame_adc_data <= {P_FREAM_HEAD,P_FREAM_HEAD,r_frmae_data_type,r_frmae_data_len};
    else if(ri_usb_adc_valid_dly)
        ro_usb_frame_adc_data <= ri_usb_adc_data_dly;
    else if(ri_usb_adc_valid_dly2)
        ro_usb_frame_adc_data <= {P_FREAM_END,P_FREAM_END,P_FREAM_END,P_FREAM_END};
    else
        ro_usb_frame_adc_data <= 'd0;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ro_usb_frame_adc_valid <= 'b0;
    else if(ri_usb_adc_valid || ri_usb_adc_valid_dly || ri_usb_adc_valid_dly2)
        ro_usb_frame_adc_valid <= 'b1;
    else
        ro_usb_frame_adc_valid <= 'b0;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ro_usb_frame_fft_data <= 'd0;
    else if(rw_usb_fft_valid_pos)
        ro_usb_frame_fft_data <= {P_FREAM_HEAD,P_FREAM_HEAD,r_frmae_data_type,r_frmae_data_len};
    else if(ri_usb_fft_valid_dly)
        ro_usb_frame_fft_data <= ri_usb_fft_data_dly;
    else if(ri_usb_fft_valid_dly2)
        ro_usb_frame_fft_data <= {P_FREAM_END,P_FREAM_END,P_FREAM_END,P_FREAM_END};
    else
        ro_usb_frame_fft_data <= 'd0;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ro_usb_frame_fft_valid <= 'b0;
    else if(ri_usb_fft_valid || ri_usb_fft_valid_dly || ri_usb_fft_valid_dly2)
        ro_usb_frame_fft_valid <= 'b1;
    else
        ro_usb_frame_fft_valid <= 'b0;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ro_usb_frame_max_data <= 'd0;
    else if(rw_usb_max_valid_pos)
        ro_usb_frame_max_data <= {P_FREAM_HEAD,P_FREAM_HEAD,r_frmae_data_type,r_frmae_data_len};
    else if(ri_usb_max_valid_dly)
        ro_usb_frame_max_data <= ri_usb_max_pow_dly;
    else if(ri_usb_max_valid_dly2)
        ro_usb_frame_max_data <= ri_usb_max_index_dly2;        
    else if(ri_usb_max_valid_dly3)
        ro_usb_frame_max_data <= {P_FREAM_END,P_FREAM_END,P_FREAM_END,P_FREAM_END};
    else
        ro_usb_frame_max_data <= 'd0;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ro_usb_frame_max_valid <= 'b0;
    else if(ri_usb_max_valid || ri_usb_max_valid_dly || ri_usb_max_valid_dly2 || ri_usb_max_valid_dly3)
        ro_usb_frame_max_valid <= 'b1;
    else
        ro_usb_frame_max_valid <= 'b0;
end

endmodule

进行仿真,验证逻辑功能的正确性

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) begin
        i_usb_adc_data  <= 'd0;
        i_usb_adc_valid <= 'd0;
        i_usb_data_len  <= 'd0;
    end
    else if(i_usb_adc_data == 'd4096) begin
        i_usb_adc_data  <= 'd4096;
        i_usb_adc_valid <= 'd0;
        i_usb_data_len  <= 'd0;
    end
    else begin
        i_usb_adc_data  <= i_usb_adc_data + 'b1;
        i_usb_adc_valid <= 'b1;
        i_usb_data_len  <= 'd4096;
    end
end

传输4096个ADC数据
在这里插入图片描述
帧头、类型、长度信息传输正确。
在这里插入图片描述
帧尾信息传输正确

传输本帧最大频率与最大幅值

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) begin
        i_usb_max_pow   <= 'd0;
        i_usb_max_index <= 'd0;
        i_usb_max_valid <= 'd0;
        i_usb_data_len  <= 'd0;
    end
    else if(i_usb_max_pow == 'd752) begin
        i_usb_max_pow   <= 'd752;
        i_usb_max_index <= 'd0;
        i_usb_max_valid <= 'd0;
        i_usb_data_len  <= 'd0;
    end
    else begin
        i_usb_max_pow   <= 'd752;
        i_usb_max_index <= 'd102;
        i_usb_max_valid <= 'd1;
        i_usb_data_len  <= 'd2;
    end
end

在这里插入图片描述
传输正确。

整体工程逻辑梳理

在这里插入图片描述
整体工程的代码文件如上所示。
其中 clk_gen模块用于输出ADC采样所需时钟。
rst_gen模块用于产生复位信号。
adc_drive模块用于接收ADC采样数据,并进行通道封装。
fft_2048x2模块用于对输入ADC数据进行FFT计算,并计算FFT的幅值,搜索每一帧的最大值与信号频率。
frame_pack模块用于对上传数据进行帧头、数据类型、数据长度、帧尾封装。
ft232h_drive模块用于搭建usb2.0驱动,并对各类上传数据与接收数据进行缓存,传输给上下游模块。
cmd_prase模块用于解析上位机发送的指令,传输给下级模块,进行指令回应。
至此,下位机工程搭建完毕,因为硬件原因,关于驱动FT232H实现FPGA与PC的通信,还需要等待一段时间。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值