JESD204B实例.v文件学习笔记

JESD204B实例.v文件学习笔记


一、 ADC_Config.v

程序代码如下:

`timescale 1ns / 1ps
//
//


module ADC_Config(   
    input  sys_clk,
    input  sys_rst,
    input  rx_sync0,
    output ADC1_PDN,
    output ADC1_RESET,
    output ADC1_SCLK,
    input  ADC1_SDOUT,
    output  ADC1_SEN,
    output  ADC1_SDIN,
    output ADC_Cfg_done,
    input rd_en
    
    );
    parameter send_total = 20;
    parameter mid_para1 = 18;
    
    
    reg [23:0]Send_data[0:send_total-1];
    reg [15:0]rd_addr;
    always@(posedge sys_clk)
    begin
         Send_data[0]  <= 24'h002920;
         Send_data[1]  <= 24'h002960;
         Send_data[2]  <= 24'h004802;
         Send_data[3]  <= 24'h020000;
         Send_data[4]  <= 24'h006100;
         Send_data[5]  <= 24'h003000;
         Send_data[6]  <= 24'h0031A0;
         Send_data[7]  <= 24'h003200;
         Send_data[8]  <= 24'h0033A0;
         Send_data[9]  <= 24'h008171;
         Send_data[10]  <= 24'h006001;
         Send_data[11]  <= 24'h020105;//JMODE 5  8bit 8lane single channel
         Send_data[12] <= 24'h02021F;
         Send_data[13] <= 24'h020403;
         Send_data[14] <= 24'h006205;
         Send_data[15] <= 24'h006101;
         Send_data[16] <= 24'h021307;
         Send_data[17] <= 24'h020001;
         Send_data[18] <= 24'h006C00;
         Send_data[19] <= 24'h006C01;
    end
    reg [8:0]dnum;
    reg [19:0]wait_cnt;
    reg [7:0]AD_Cfg_State=3;
    reg [7:0]AD_Cfg_Cnt;
    reg [7:0]AD_Cfg;
    reg AD_RESET;
    reg Cfg_EN;
    reg Cfg_SDIO;
    reg [8:0]send_num;
    reg [4:0]send_bit_num;  
    reg done;
    always@(posedge sys_clk)
    begin
       if(sys_rst)
       begin
            AD_Cfg_State <= 3;
            Cfg_EN <= 1'b1;
            Cfg_SDIO <= 1'b0;
            AD_RESET <= 1'b0;
            AD_Cfg_Cnt <= 0;
            send_num <= 0;
            send_bit_num <= 0;
            done <= 0;
            dnum <= 0;
       end 
       else 
       begin
       case(AD_Cfg_State)
           8'd3:begin
                 if(AD_Cfg_Cnt < 8'd20)
                 begin
                     AD_RESET <= 1'b1;
                     AD_Cfg_Cnt <= AD_Cfg_Cnt + 1'b1;
                     AD_Cfg_State <= 3;
                end
                else if(AD_Cfg_Cnt < 8'd200)
                begin
                     AD_RESET <= 1'b0;
                     AD_Cfg_Cnt <= AD_Cfg_Cnt + 1'b1;
                     AD_Cfg_State <= 3;
                end
                else
                begin
                      AD_RESET <= 1'b0;
                      AD_Cfg_Cnt <= 0;   
                      AD_Cfg_State <= 4;   
                      send_num <= 0;
                      send_bit_num <= 0;  
                      done <= 0;            
                end
           end
           8'd4:begin
                if(send_bit_num < 23)
                begin
                    Cfg_SDIO <= Send_data[send_num][23-send_bit_num];
                    Cfg_EN <= 1'b0;
                    send_bit_num <= send_bit_num + 1'b1;
                    AD_Cfg_State <= 4; 
                    send_num <= send_num;                      
                end
                else
                begin
                    Cfg_SDIO <= Send_data[send_num][23-send_bit_num];
                    Cfg_EN <= 1'b0;
                    send_bit_num <= 0;
                    AD_Cfg_State <= 5;  
                    send_num <= send_num + 1'b1;
                end
           end
           8'd5:begin
                 Cfg_EN <= 1'b1;
                 Cfg_SDIO <= 1'b0;
                if(send_num == mid_para1)
                begin
                    send_num <= send_num; 
                    AD_Cfg_State <= 7;
                    done <= 1;  
                end
                else if(send_num >= send_total)
                begin
                   if(sys_rst) 
                   begin
                        send_num <= 0;
                        AD_Cfg_State <= 3;
                   end
                   else
                   begin
                        send_num <= send_num;
                        AD_Cfg_State <= 5;
                   end
                end
                else
                begin
                     AD_Cfg_State <= 6; 
                end
           end
           8'd6:begin
                if(AD_Cfg_Cnt < 8'd20)
                begin
                    AD_Cfg_Cnt <= AD_Cfg_Cnt + 1'b1;
                    AD_Cfg_State <= 6; 
                end
                else begin
                    AD_Cfg_Cnt <= 0;
                    AD_Cfg_State <= 4; 
                end
           end
           8'd7:begin
                if(~rx_sync0)
                begin
                    wait_cnt <= wait_cnt + 1'b1;
                    AD_Cfg_State <= 7; 
                end
                else begin
                    wait_cnt <= 0;
                    AD_Cfg_State <= 4; 
                end
           end
       endcase
    end
    end
   
//    always@(negedge sys_clk)
//    begin
//        ADC1_SEN <= Cfg_EN;
//        ADC1_SDIN <= Cfg_SDIO;
//    end
    assign ADC1_SEN = Cfg_EN;
    assign ADC1_SDIN = Cfg_SDIO;
    assign ADC1_PDN = AD_RESET;
    assign ADC1_RESET = AD_RESET;
   assign ADC1_SCLK = ~sys_clk;
//    assign ADC1_SEN = Cfg_EN;
//    assign ADC1_SDIN = Cfg_SDIO;
    assign ADC_Cfg_done = done;
endmodule

这是一个Verilog模块ADC_Config,用于配置ADC(模数转换器)的设置。接下来,我将逐行解释这段代码的作用。

首先,简单介绍Verilog的一些基本概念。在硬件描述语言Verilog中,使用module来定义一个独立的硬件模块,模块内部可以包含输入(input)和输出(output)等端口,还可以包含参数(parameter),寄存器(reg),总线等各种硬件元素,并且使用始终触发的过程(always)来描述这些硬件元素的动态行为。

module ADC_Config(   
    input  sys_clk,
    input  sys_rst,
    input  rx_sync0,
    output ADC1_PDN,
    output ADC1_RESET,
    output ADC1_SCLK,
    input  ADC1_SDOUT,
    output  ADC1_SEN,
    output  ADC1_SDIN,
    output ADC_Cfg_done,
    input rd_en
    ); 

上面这段代码定义了一个名为ADC_Config的模块,有11个端口:

  • 输入端口:系统时钟sys_clk,系统复位信号sys_rst,接收同步信号rx_sync0,和读取使能信号rd_en
  • 输出端口:ADC的启动控制信号ADC1_PDN,ADC的复位信号ADC1_RESET,ADC的时钟信号ADC1_SCLK,ADC的使能信号ADC1_SEN,ADC的数据输入信号ADC1_SDIN,和ADC配置完成信号ADC_Cfg_done
  • 输入/输出端口:ADC的数据输出信号ADC1_SDOUT
parameter send_total = 20;
parameter mid_para1 = 18;

定义了两个参数:需要发送的总数send_total和其中一个特殊的传输信号的位置mid_para1

reg [23:0]Send_data[0:send_total-1];
reg [15:0]rd_addr;

定义了一个24比特的寄存器数组Send_data,存储需要发送的数据。定义了一个16比特的寄存器rd_addr,读取地址。

以下的代码块定义了一些必要的寄存器并初始化了寄存器Send_data,将配置数据写入到寄存器数组里。

always@(posedge sys_clk)
begin
     Send_data[0]  <= 24'h002920;
     ...
     Send_data[19] <= 24'h006C01;
end

这块代码表示在系统时钟的上升沿,将配置数据写入到Send_data数组中。

接下来的always块中,它用状态机的方式,控制配置信息从Send_data寄存器数组如何传递给ADC,主要操作是在系统时钟的上升沿根据各种条件来控制配置信息的传输流程,包括复位信号的设置,配置信息的发送,ADC的使能信号,结束信号的设置等。

以下代码块是对ADC的几个控制信号(如ADC1_SENADC1_SDINADC1_PDNADC1_RESETADC1_SCLKADC_Cfg_done)的赋值操作,这些赋值操作最后会影响到ADC的工作状态。

assign ADC1_SEN = Cfg_EN;
assign ADC1_SDIN = Cfg_SDIO;
assign ADC1_PDN = AD_RESET;
assign ADC1_RESET = AD_RESET;
assign ADC1_SCLK = ~sys_clk;
assign ADC_Cfg_done = done;

assign在Verilog中是连续赋值语句,用来驱动电路中的线(wire)。

模块结束的代码:

endmodule

表示结束模块的定义。

总结来说,这个Verilog代码块的功能主要是在给定的输入信号和状态下,将预设的配置数据通过控制通信接口传输出去配置ADC,并给出正确的控制信号和结束信号。


二、 ADC_Config2.v

程序代码如下:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2018/07/16 14:13:26
// Design Name: 
// Module Name: ADC_Config
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module ADC_Config2(   
    input  sys_clk,
    input  sys_rst,
    input  rx_sync0,
    output ADC1_PDN,
    output ADC1_RESET,
    output ADC1_SCLK,
    input  ADC1_SDOUT,
    output  ADC1_SEN,
    output  ADC1_SDIN,
    output ADC_Cfg_done,
    input rd_en
    
    );
    parameter send_total = 20;
    parameter mid_para1 = 18;
    
    
    reg [23:0]Send_data[0:send_total-1];
    reg [15:0]rd_addr;
    always@(posedge sys_clk)
    begin
         Send_data[0]  <= 24'h002920;
         Send_data[1]  <= 24'h002960;
         Send_data[2]  <= 24'h004802;
         Send_data[3]  <= 24'h020000;
         Send_data[4]  <= 24'h006100;
         Send_data[5]  <= 24'h003000;
         Send_data[6]  <= 24'h0031A0;
         Send_data[7]  <= 24'h003200;
         Send_data[8]  <= 24'h0033A0;
         Send_data[9]  <= 24'h008177;
         Send_data[10] <= 24'h006001;
         Send_data[11] <= 24'h020105;//JMODE 5  8bit 8lane single channel
         Send_data[12] <= 24'h02021F;
         Send_data[13] <= 24'h020403;
         Send_data[14] <= 24'h006205;
         Send_data[15] <= 24'h006101;
         Send_data[16] <= 24'h021307;
         Send_data[17] <= 24'h020001;
         Send_data[18] <= 24'h006C00;
         Send_data[19] <= 24'h006C01;
    end
    reg [8:0]dnum;
    reg [19:0]wait_cnt;
    reg [7:0]AD_Cfg_State=3;
    reg [7:0]AD_Cfg_Cnt;
    reg [7:0]AD_Cfg;
    reg AD_RESET;
    reg Cfg_EN;
    reg Cfg_SDIO;
    reg [8:0]send_num;
    reg [4:0]send_bit_num;  
    reg done;
    always@(posedge sys_clk)
    begin
       if(sys_rst)
       begin
            AD_Cfg_State <= 3;
            Cfg_EN <= 1'b1;
            Cfg_SDIO <= 1'b0;
            AD_RESET <= 1'b0;
            AD_Cfg_Cnt <= 0;
            send_num <= 0;
            send_bit_num <= 0;
            done <= 0;
            dnum <= 0;
       end 
       else 
       begin
       case(AD_Cfg_State)
           8'd3:begin
                 if(AD_Cfg_Cnt < 8'd20)
                 begin
                     AD_RESET <= 1'b1;
                     AD_Cfg_Cnt <= AD_Cfg_Cnt + 1'b1;
                     AD_Cfg_State <= 3;
                end
                else if(AD_Cfg_Cnt < 8'd200)  
                begin
                     AD_RESET <= 1'b0;
                     AD_Cfg_Cnt <= AD_Cfg_Cnt + 1'b1;
                     AD_Cfg_State <= 3;
                end
                else
                begin
                      AD_RESET <= 1'b0;
                      AD_Cfg_Cnt <= 0;   
                      AD_Cfg_State <= 4;   
                      send_num <= 0;
                      send_bit_num <= 0;  
                      done <= 0;            
                end
           end
           8'd4:begin
                if(send_bit_num < 23)
                begin
                    Cfg_SDIO <= Send_data[send_num][23-send_bit_num];
                    Cfg_EN <= 1'b0;
                    send_bit_num <= send_bit_num + 1'b1;
                    AD_Cfg_State <= 4; 
                    send_num <= send_num;                      
                end
                else
                begin
                    Cfg_SDIO <= Send_data[send_num][23-send_bit_num];
                    Cfg_EN <= 1'b0;
                    send_bit_num <= 0;
                    AD_Cfg_State <= 5;  
                    send_num <= send_num + 1'b1;
                end
           end
           8'd5:begin
                 Cfg_EN <= 1'b1;
                 Cfg_SDIO <= 1'b0;
                if(send_num == mid_para1)
                begin
                    send_num <= send_num; 
                    AD_Cfg_State <= 7;
                    done <= 1;  
                end
                else if(send_num >= send_total)
                begin
                   if(sys_rst) 
                   begin
                        send_num <= 0;
                        AD_Cfg_State <= 3;
                   end
                   else
                   begin
                        send_num <= send_num;
                        AD_Cfg_State <= 5;
                   end
                end
                else
                begin
                     AD_Cfg_State <= 6; 
                end
           end
           8'd6:begin
                if(AD_Cfg_Cnt < 8'd20)
                begin
                    AD_Cfg_Cnt <= AD_Cfg_Cnt + 1'b1;
                    AD_Cfg_State <= 6; 
                end
                else begin
                    AD_Cfg_Cnt <= 0;
                    AD_Cfg_State <= 4; 
                end
           end
           8'd7:begin
                if(~rx_sync0)
                begin
                    wait_cnt <= wait_cnt + 1'b1;
                    AD_Cfg_State <= 7; 
                end
                else begin
                    wait_cnt <= 0;
                    AD_Cfg_State <= 4; 
                end
           end
       endcase
    end
    end
   
//    always@(negedge sys_clk)
//    begin
//        ADC1_SEN <= Cfg_EN;
//        ADC1_SDIN <= Cfg_SDIO;
//    end
    assign ADC1_SEN = Cfg_EN;
    assign ADC1_SDIN = Cfg_SDIO;
    assign ADC1_PDN = AD_RESET;
    assign ADC1_RESET = AD_RESET;
   assign ADC1_SCLK = ~sys_clk;
//    assign ADC1_SEN = Cfg_EN;
//    assign ADC1_SDIN = Cfg_SDIO;
    assign ADC_Cfg_done = done;
endmodule

该代码块是用Verilog HDL写的一个名为ADC_Config2的模块,主要功能是配置一个模数转换器(ADC)。在数字信号处理系统中,ADC常常被用于将模拟信号转换成数字信号,以便进行处理。代码中的主要操作是通过发送一系列的配置数据来对ADC进行初始化和配置。

详细来说,每个部分的功能如下:

  1. 定义ADC_Config2模块的输入和输出端口,包括系统时钟sys_clk,系统复位sys_rst,模数转换器的控制信号如ADC1_PDN, ADC1_RESET, ADC1_SCLK, ADC1_SDOUT, ADC1_SEN, ADC1_SDIN等。
module ADC_Config2(   
    input  sys_clk,
    input  sys_rst,
    input  rx_sync0,
    output ADC1_PDN,
    output ADC1_RESET,
    output ADC1_SCLK,
    input  ADC1_SDOUT,
    output  ADC1_SEN,
    output  ADC1_SDIN,
    output ADC_Cfg_done,
    input rd_en
);
  1. 定义相关参数和寄存器,包括一些在配置过程中需要发送的数据Send_data等。
parameter send_total = 20;
parameter mid_para1 = 18;

reg [23:0]Send_data[0:send_total-1];
reg [15:0]rd_addr;
  1. 在系统时钟上升沿,定义数据Send_data的具体内容。这些数据是配置ADC所需要的。
always@(posedge sys_clk)
begin
     Send_data[0]  <= 24'h002920;
     //...
     Send_data[19] <= 24'h006C01;
end
  1. 定义与状态机相关的变量和寄存器,包括当前状态AD_Cfg_State,计数器AD_Cfg_Cnt等。
reg [8:0]dnum; // used in system reset 
reg [19:0]wait_cnt; // delay counter
reg [7:0]AD_Cfg_State=3; // the state value of FSM
reg [7:0]AD_Cfg_Cnt; // Loop counter
reg [7:0]AD_Cfg;
reg AD_RESET; // ADC reset signal
reg Cfg_EN; //   AD7671 chip enable signal
reg Cfg_SDIO; // the data to be send to ADC
reg [8:0]send_num; // the number of data that has been send
reg [4:0]send_bit_num; // the bit number of the data that has been send  
reg done; // signal that represents the finish of the sending process
  1. 定义主要的有限状态机(FSM)逻辑。FSM主要通过系统时钟的上升沿来更改状态。
always@(posedge sys_clk)
begin
   //......
   case(AD_Cfg_State)
       8'd3:begin    // State 3: initialize the AD_RESET signal. 
       8'd4:begin    // State 4: Send configuration data.
       8'd5:begin    // State 5: Check if all configuration data has been sent.
       8'd6:begin    // State 6: Delay for next data to send.
       8'd7:begin    // State 7: Wait for the rx_sync0 signal before sending the next data.
   endcase
end
end
  1. 定义输出信号与寄存器的关系。当时钟下降沿时,更新输出信号的值。
assign ADC1_SEN = Cfg_EN;
assign ADC1_SDIN = Cfg_SDIO;
assign ADC1_PDN = AD_RESET;
assign ADC1_RESET = AD_RESET;
assign ADC1_SCLK = ~sys_clk; //system clock inversion
assign ADC_Cfg_done = done;
endmodule

以上就是这段代码的逐行解析。总的来说,这个模块在时序逻辑上,主要是一个有限状态机,相对复杂。但结构清晰,通过状态变量转换来实现ADC的配置过程。


三、 ADC_DATA_Align.v

程序代码如下:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2018/10/17 15:28:25
// Design Name: 
// Module Name: ADC_DATA_Align
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module ADC_DATA_Align(
    input adc_clk,
    input adc_dvalid,
    input [255:0]adc_data,
    output [255:0]adc_dout,
    output reg adc_dvalid_out

    );
    
    reg [7:0]adc_d0,adc_d1,adc_d2,adc_d3,adc_d4,adc_d5,adc_d6,adc_d7;
    reg [7:0]adc_d8,adc_d9,adc_d10,adc_d11,adc_d12,adc_d13,adc_d14,adc_d15;
    reg [7:0]adc_d16,adc_d17,adc_d18,adc_d19,adc_d20,adc_d21,adc_d22,adc_d23;
    reg [7:0]adc_d24,adc_d25,adc_d26,adc_d27,adc_d28,adc_d29,adc_d30,adc_d31;
    assign adc_dout = {
   adc_d31,adc_d30,adc_d29,adc_d28,adc_d27,adc_d26,adc_d25,adc_d24,
                       adc_d23 ,adc_d22,adc_d21,adc_d20,adc_d19,adc_d18,adc_d17,adc_d16,
                       adc_d15,adc_d14,adc_d13,adc_d12,adc_d11,adc_d10,adc_d9,adc_d8,
                       adc_d7,adc_d6,adc_d5,adc_d4,adc_d3,adc_d2,adc_d1,adc_d0};
    always@(posedge adc_clk)
    begin
        adc_dvalid_out <= adc_dvalid;
        adc_d1  <= ~adc_data[7:0];
        adc_d9  <= ~adc_data[15:8];
        adc_d17 <= ~adc_data[23:16];
        adc_d25 <= ~adc_data[31:24];
        
        adc_d3  <= ~adc_data[39:32];
        adc_d11 <= ~adc_data[47:40];
        adc_d19 <= ~adc_data[55:48];
        adc_d27 <= ~adc_data[63:56];
        
        adc_d5  <= ~adc_data[71:64];
        adc_d13 <= ~adc_data[79:72];
        adc_d21 <= ~adc_data[87:80];
        adc_d29 <= ~adc_data[95:88];
        
        adc_d7  <= ~adc_data[103:96];
        adc_d15 <= ~adc_data[111:104];
        adc_d23 <= ~adc_data[119:112];
        adc_d31 <= ~adc_data[127:120];
        
        adc_d0  <= ~adc_data[135:128];
        adc_d8  <= ~adc_data[143:136];
        adc_d16 <= ~adc_data[151:144];
        adc_d24 <= ~adc_data[159:152];
        
        adc_d2  <= ~adc_data[167:160];
        adc_d10 <= ~adc_data[175:168];
        adc_d18 <= ~adc_data[183:176];
        adc_d26 <= ~adc_data[191:184];
        
        adc_d4  <= ~adc_data[199:192];
        adc_d12 <= ~adc_data[207:200];
        adc_d20 <= ~adc_data[215:208];
        adc_d28 <= ~adc_data[223:216];
        
        adc_d6  <= ~adc_data[231:224];
        adc_d14 <= ~adc_data[239:232];
        adc_d22 <= ~adc_data[247:240];
        adc_d30 <= ~adc_data[255:248];
    end
   
endmodule

这个模块的作用是接收一个256位的ADC数据输入,按照一定的方法重新排列数据,然后输出。然后每个8位数据单元执行一个按位取反操作。输入和输出的控制都在ADC的时钟adc_clk上升沿触发。

以下是代码的逐行审阅与注释

module ADC_DATA_Align(
    input adc_clk, // ADC的数据时钟
    input adc_dvalid, // ADC的数据有效信号
    input [255:0]adc_data, // 256位的ADC数据
    output [255:0]adc_dout, // 输出的256位数据
    output reg adc_dvalid_out // 输出的数据有效信号
    );

// 定义32个8位寄存器,用于存储经过取反处理后的256位的ADC数据
reg [7:0]adc_d0,adc_d1,adc_d2,adc_d3,adc_d4,adc_d5,adc_d6,adc_d7;
reg [7:0]adc_d8,adc_d9,adc_d10,adc_d11,adc_d12,adc_d13,adc_d14,adc_d15;
reg [7:0]adc_d16,adc_d17,adc_d18,adc_d19,adc_d20,adc_d21,adc_d22,adc_d23;
reg [7:0]adc_d24,adc_d25,adc_d26,adc_d27,adc_d28,adc_d29,adc_d30,adc_d31;

// 将32个寄存器按照指定的顺序组合成256位的数据
assign adc_dout = {adc_d31,adc_d30,adc_d29,adc_d28,adc_d27,adc_d26,adc_d25,adc_d24,
                   adc_d23 ,adc_d22,adc_d21,adc_d20,adc_d19,adc_d18,adc_d17,adc_d16,
                   adc_d15,adc_d14,adc_d13,adc_d12,adc_d11,adc_d10,adc_d9,adc_d8,
                   adc_d7,adc_d6,adc_d5,adc_d4,adc_d3,adc_d2,adc_d1,adc_d0};

// 在adc_clk的上升沿触发,进行数据处理
always@(posedge adc_clk)
begin
    // 原始的ADC数据有效信号直接复制到输出
    adc_dvalid_out <= adc_dvalid;
    
    // 把原始的256位数据进行分割,并分别取反,然后赋值给32个8位的寄存器
    // 注意这里的顺序是自定义的,并没有按照连续的顺序取数据
    adc_d1  <= ~adc_data[7:0];
    adc_d9  <= ~adc_data[15:8];
    adc_d17 <= ~adc_data[23:16];
    adc_d25 <= ~adc_data[31:24];
    
    adc_d3  <= ~adc_data[39:32];
    adc_d11 <= ~adc_data[47:40];
    adc_d19 <= ~adc_data[55:48];
    adc_d27 <= ~adc_data[63:56];
    
    adc_d5  <= ~adc_data[71:64];
    adc_d13 <= ~adc_data[79:72];
    adc_d21 <= ~adc_data[87:80];
    adc_d29 <= ~adc_data[95:88];
    
    adc_d7  <= ~adc_data[103:96];
    adc_d15 <= ~adc_data[111:104];
    adc_d23 <= ~adc_data[119:112];
    adc_d31 <= ~adc_data[127:120];
    
    adc_d0  <= ~adc_data[135:128];
    adc_d8  <= ~adc_data[143:136];
    adc_d16 <= ~adc_data[151:144];
    adc_d24 <= ~adc_data[159:152];
    
    adc_d2  <= ~adc_data[167:160];
    adc_d10 <= ~adc_data[175:168];
    adc_d18 <= ~adc_data[183:176];
    adc_d26 <= ~adc_data[191:184];
    
    adc_d4  <= ~adc_data[199:192];
    adc_d12 <= ~adc_data[207:200];
    adc_d20 <= ~adc_data[215:208];
    adc_d28 <= ~adc_data[223:216];
    
    adc_d6  <= ~adc_data[231:224];
    adc_d14 <= ~adc_data[239:232];
    adc_d22 <= ~adc_data[247:240];
    adc_d30 <= ~adc_data[255:248];
end
   
endmodule

总的来说,这个模块就是对ADC的256位数据按照一定的规则进行取反和重新排列,然后输出。


四、 DataPacket_module.v

程序代码如下:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2019/05/23 14:08:15
// Design Name: 
// Module Name: DataPacket_module
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module DataPacket_module(
    input adc_clk,
    input [3:0]Bw_para,
    input [31:0]sample_num,
    input sys_rst,
    input [255:0]adc1_Idout_t1,
    input [255:0]adc1_Qdout_t1,
    input [255:0]adc1_Idout_t2,
    input [255:0]adc1_Qdout_t2,
    input [255:0]adc1_Idout_t3,
    input [255:0]adc1_Qdout_t3,
    input  adc_valid_t1,
    input  adc_valid_t2,
    input  adc_valid_t3,
    input rd_clk,
    output [255:0]rd_dout,
    input  rd_en,
    output pack_aempty
    );
    reg [511:0]BW3600M_Din;
    reg BW3600M_Wen;
    reg BW3600M_Ren;
    wire  BW3600M_aempty;
    wire[255:0]  BW3600M_dout;
    reg BW3600M_dvalid;
    always@(posedge adc_clk)
    begin
        BW3600M_Wen <= adc_valid_t1;
        BW3600M_Din <= {
   
                        adc1_Qdout_t1[127:120],adc1_Idout_t1[127:120],
                        adc1_Qdout_t1[119:112],adc1_Idout_t1[119:112],
                        adc1_Qdout_t1[111:104],adc1_Idout_t1[111:104],
                        adc1_Qdout_t1[103:96],adc1_Idout_t1[103:96],
                        adc1_Qdout_t1[95:88],adc1_Idout_t1[95:88],
                        adc1_Qdout_t1[87:80],adc1_Idout_t1[87:80],
                        adc1_Qdout_t1[79:72],adc1_Idout_t1[79:72],
                        adc1_Qdout_t1[71:64],adc1_Idout_t1[71:64],
                        adc1_Qdout_t1[63:56],adc1_Idout_t1[63:56],
                        adc1_Qdout_t1[55:48],adc1_Idout_t1[55:48],
                        adc1_Qdout_t1[47:40],adc1_Idout_t1[47:40],
                        adc1_Qdout_t1[39:32],adc1_Idout_t1[39:32],
                        adc1_Qdout_t1[31:24],adc1_Idout_t1[31:24],
                        adc1_Qdout_t1[23:16],adc1_Idout_t1[23:16],
                        adc1_Qdout_t1[15:8],adc1_Idout_t1[15:8],
                        adc1_Qdout_t1[7:0],adc1_Idout_t1[7:0],
                        adc1_Qdout_t1[255:248],adc1_Idout_t1[255:248],
                        adc1_Qdout_t1[247:240],adc1_Idout_t1[247:240],
                        adc1_Qdout_t1[239:232],adc1_Idout_t1[239:232],
                        adc1_Qdout_t1[231:224],adc1_Idout_t1[231:224],
                        adc1_Qdout_t1[223:216],adc1_Idout_t1[223:216],
                        adc1_Qdout_t1[215:208],adc1_Idout_t1[215:208],
                        adc1_Qdout_t1[207:200],adc1_Idout_t1[207:200],
                        adc1_Qdout_t1[199:192],adc1_Idout_t1[199:192],
                        adc1_Qdout_t1[191:184],adc1_Idout_t1[191:184],
                        adc1_Qdout_t1[183:176],adc1_Idout_t1[183:176],
                        adc1_Qdout_t1[175:168],adc1_Idout_t1[175:168],
                        adc1_Qdout_t1[167:160],adc1_Idout_t1[167:160],
                        adc1_Qdout_t1[159:152],adc1_Idout_t1[159:152],
                        adc1_Qdout_t1[151:144],adc1_Idout_t1[151:144],
                        adc1_Qdout_t1[143:136],adc1_Idout_t1[143:136],
                        adc1_Qdout_t1[135:128],adc1_Idout_t1[135:128]};
    end
    always@(posedge rd_clk)
    begin
        if(~BW3600M_aempty)
        begin
            BW3600M_Ren <= 1;
            BW3600M_dvalid <= 1;
        end
        else
        begin
            BW3600M_Ren <= 0;
            BW3600M_dvalid <= 0;
        end
    end
    fifo_generator_4 inst_BW3600M(
      .rst(sys_rst),                    // input wire rst
      .wr_clk(adc_clk),              // input wire wr_clk
      .rd_clk(rd_clk),              // input wire rd_clk
      .din(BW3600M_Din),                    // input wire [511 : 0] din
      .wr_en(BW3600M_Wen),                // input wire wr_en
      .rd_en(BW3600M_Ren),                // input wire rd_en
      .dout(BW3600M_dout),                  // output wire [255 : 0] dout
      .full(),                  // output wire full
      .almost_full(),    // output wire almost_full
      .empty(),                // output wire empty
      .almost_empty(BW3600M_aempty),  // output wire almost_empty
      .wr_rst_busy(),    // output wire wr_rst_busy
      .rd_rst_busy()    // output wire rd_rst_busy
    );
  
       reg [255:0]BW1200M_Din;
       reg BW1200M_Wen;
       reg BW1200M_Ren;
       wire  BW1200M_aempty;
       wire[255:0]  BW1200M_dout;
       reg BW1200M_dvalid;
       always@(posedge adc_clk)
       begin
           BW1200M_Wen <= adc_valid_t2;
           BW1200M_Din <= {
   
                           adc1_Qdout_t2[247:240],adc1_Idout_t2[247:240],
                           adc1_Qdout_t2[231:224],adc1_Idout_t2[231:224],
                           adc1_Qdout_t2[215:208],adc1_Idout_t2[215:208],
                           adc1_Qdout_t2[199:192],adc1_Idout_t2[199:192],
                           adc1_Qdout_t2[183:176],adc1_Idout_t2[183:176],
                           adc1_Qdout_t2[167:160],adc1_Idout_t2[167:160],
                           adc1_Qdout_t2[151:144],adc1_Idout_t2[151:144],
                           adc1_Qdout_t2[135:128],adc1_Idout_t2[135:128],
                           adc1_Qdout_t2[119:112],adc1_Idout_t2[119:112],
                           adc1_Qdout_t2[103:96],adc1_Idout_t2[103:96],
                           adc1_Qdout_t2[87:80],adc1_Idout_t2[87:80],
                           adc1_Qdout_t2[71:64],adc1_Idout_t2[71:64],
                           adc1_Qdout_t2[55:48],adc1_Idout_t2[55:48],
                           adc1_Qdout_t2[39:32],adc1_Idout_t2[39:32],
                           adc1_Qdout_t2[23:16],adc1_Idout_t2[23:16],
                           adc1_Qdout_t2[7:0],adc1_Idout_t2[7:0]};
       end
       always@(posedge rd_clk)
       begin
           if(~BW1200M_aempty)
           begin
               BW1200M_Ren <= 1;
               BW1200M_dvalid <= 1;
           end
           else
           begin
               BW1200M_Ren <= 0;
               BW1200M_dvalid <= 0;
           end
       end
  
     fifo_generator_0 inst_BW1200M (
          .rst(sys_rst),                    // input wire rst
          .wr_clk(adc_clk),              // input wire wr_clk
          .rd_clk(rd_clk),              // input wire rd_clk
          .din(BW1200M_Din),                    // input wire [255 : 0] din
          .wr_en(BW1200M_Wen),                // input wire wr_en
          .rd_en(BW1200M_Ren),                // input wire rd_en
          .dout(BW1200M_dout),                  // output wire [255 : 0] dout
          .full(),                  // output wire full
          .almost_full(),    // output wire almost_full
          .empty(),                // output wire empty
          .almost_empty(BW1200M_aempty),  // output wire almost_empty
          .wr_rst_busy(),    // output wire wr_rst_busy
          .rd_rst_busy()    // output wire rd_rst_busy
        );

    reg [511:0]BW2400M_Din;
    reg BW2400M_Wen;
    reg BW2400M_Ren;
    wire  BW2400M_aempty;
    wire[255:0]  BW2400M_dout;
    reg BW2400M_dvalid;
    always@(posedge adc_clk)
    begin
        BW2400M_Wen <= adc_valid_t3;
        BW2400M_Din <= {
   
                        adc1_Qdout_t3[127:120],adc1_Idout_t3[127:120],
                        adc1_Qdout_t3[119:112],adc1_Idout_t3[119:112],
                        adc1_Qdout_t3[111:104],adc1_Idout_t3[111:104],
                        adc1_Qdout_t3[103:96],adc1_Idout_t3[103:96],
                        adc1_Qdout_t3[95:88],adc1_Idout_t3[95:88],
                        adc1_Qdout_t3[87:80],adc1_Idout_t3[87:80],
                        adc1_Qdout_t3[79:72],adc1_Idout_t3[79:72],
                        adc1_Qdout_t3[71:64],adc1_Idout_t3[71:64],
                        adc1_Qdout_t3[63:56],adc1_Idout_t3[63:56],
                        adc1_Qdout_t3[55:48],adc1_Idout_t3[55:48],
                        adc1_Qdout_t3[47:40],adc1_Idout_t3[47:40],
                        adc1_Qdout_t3[39:32],adc1_Idout_t3[39:32],
                        adc1_Qdout_t3[31:24],adc1_Idout_t3[31:24],
                        adc1_Qdout_t3[23:16],adc1_Idout_t3[23:16],
                        adc1_Qdout_t3[15:8],adc1_Idout_t3[15:8],
                        adc1_Qdout_t3[7:0],adc1_Idout_t3[7:0],
                        adc1_Qdout_t3[255:248],adc1_Idout_t3[255:248],
                        adc1_Qdout_t3[247:240],adc1_Idout_t3[247:240],
                        adc1_Qdout_t3[239:232],adc1_Idout_t3[239:232],
                        adc1_Qdout_t3[231:224],adc1_Idout_t3[231:224],
                        adc1_Qdout_t3[223:216],adc1_Idout_t3[223:216],
                        adc1_Qdout_t3[215:208],adc1_Idout_t3[215:208],
                        adc1_Qdout_t3[207:200],adc1_Idout_t3[207:200],
                        adc1_Qdout_t3[199:192],adc1_Idout_t3[199:192],
                        adc1_Qdout_t3[191:184],adc1_Idout_t3[191:184],
                        adc1_Qdout_t3[183:176],adc1_Idout_t3[183:176],
                        adc1_Qdout_t3[175:168],adc1_Idout_t3[175:168],
                        adc1_Qdout_t3[167:160],adc1_Idout_t3[167:160],
                        adc1_Qdout_t3[159:152],adc1_Idout_t3[159:152],
                        adc1_Qdout_t3[151:144],adc1_Idout_t3[151:144],
                        adc1_Qdout_t3[143:136],adc1_Idout_t3[143:136],
                        adc1_Qdout_t3[135:128],adc1_Idout_t3[135:128]};
    end
    always@(posedge rd_clk)
    begin
        if(~BW2400M_aempty)
        begin
            BW2400M_Ren <= 1;
            BW2400M_dvalid <= 1;
        end
        else
        begin
            BW2400M_Ren <= 0;
            BW2400M_dvalid <= 0;
        end
    end
    fifo_generator_4 inst_BW2400M(
      .rst(sys_rst),                    // input wire rst
      .wr_clk(adc_clk),              // input wire wr_clk
      .rd_clk(rd_clk),              // input wire rd_clk
      .din(BW2400M_Din),                    // input wire [511 : 0] din
      .wr_en(BW2400M_Wen),                // input wire wr_en
      .rd_en(BW2400M_Ren),                // input wire rd_en
      .dout(BW2400M_dout),                  // output wire [255 : 0] dout
      .full(),                  // output wire full
      .almost_full(),    // output wire almost_full
      .empty(),                // output wire empty
      .almost_empty(BW2400M_aempty),  // output wire almost_empty
      .wr_rst_busy(),    // output wire wr_rst_busy
      .rd_rst_busy()    // output wire rd_rst_busy
    );
  reg pack_wen;
  reg [255:0]pack_din;
  always@(posedge rd_clk)
  begin
    case(Bw_para)
        4'd4:begin
            pack_wen <= BW3600M_dvalid;  
            pack_din <= BW3600M_dout;
        end
        4'd3:begin
            pack_wen <= BW2400M_dvalid;  
            pack_din <= BW2400M_dout;
        end
        4'd2:begin
            pack_wen <= BW1200M_dvalid;  
            pack_din <= BW1200M_dout;
        end
        default:begin
            pack_wen <= BW3600M_dvalid;  
            pack_din <= BW3600M_dout;
        end
    endcase
  end
  fifo_generator_8 inst_pack (
    .clk(rd_clk),                   // input wire clk
    .srst(sys_rst),                 // input wire srst
    .din(pack_din),                    // input wire [255 : 0] din
    .wr_en(pack_wen),                // input wire wr_en
    .rd_en(rd_en),                // input wire rd_en
    .dout(rd_dout),                  // output wire [255 : 0] dout
    .full(),                  // output wire full
    .empty(),                // output wire empty
    .almost_empty(pack_aempty),  // output wire almost_empty
    .almost_full(),  // output wire almost_empty
    .wr_rst_busy(),    // output wire wr_rst_busy
    .rd_rst_busy()    // output wire rd_rst_busy
  );
  
      ila_4 inst_packet (
      .clk(rd_clk), // input wire clk
      .probe0(Bw_para), // input wire [3:0]  probe0  
      .probe1(pack_wen), // input wire [0:0]  probe1 
      .probe2(BW3600M_aempty), // input wire [0:0]  probe2 
      .probe3(BW3600M_Ren), // input wire [0:0]  probe3 
      .probe4(adc_valid_t1), // input wire [0:0] probe4 
      .probe5(BW3600M_Ren), // input wire [0:0] probe5 
      .probe6(BW3600M_aempty), // input wire [0:0] probe6 
      .probe7(BW3600M_Ren), // input wire [0:0]  probe7 
      .probe8(BW3600M_aempty), // input wire [0:0]  probe8 
      .probe9(BW3600M_Ren), // input wire [0:0]  probe9 
      .probe10(rd_en), // input wire [0:0]  probe12 
      .probe11(pack_aempty)
  );
endmodule

解释1:

这是一个较复杂的Verilog模块,名为DataPacket_module,需要对输入数据进行带宽分类的处理和包装。它采用了数据有效信号(valid signal)控制的设计方式,处理带宽包含3600M,2400M和1200M的数据。根据控制输入信号Bw_para,选择3600M, 2400M, 1200M其中一种带宽下的数据,传送给一个FIFO生成器(inst_pack),从而执行打包处理。再通过读取时钟rd_clk,将数据从数据出口dout读取出来。这个模块的功能实现主要基于FIFO(first-in first-out)原则。

具体来看每部分:

在module的输入参数中:

  • 输入端包括一个adc_clk(数据采集时钟),一个四位的参数Bw_para(控制数据带宽的参数),一个32位的参数sample_num,还有一个复位信号sys_rst以及各种各样对应不同采集时刻的数据接口和数据有效信号。
  • 输出端包含一个[255:0]位的数据接口rd_dout,一位长度的读取使能信号rd_en和一个包空信号pack_aempty。

我们可以把这个模块分成三个部分,分别针对3600M、1200M和2400M的带宽对数据进行处理,然后通过一个FIFO生成器进行处理和打包。

每个部分都有类似的代码结构:

  1. 有一个always模块,这个模块在adc_clk(这可能是ADC转换的时钟)上升沿触发,更新对应带宽的写控制信号(Wen),并将输入的数据按照一定的方式填入到Din中。在这个例子中,模块将数据打包为16位IQ数据(8位为I数据,8位为Q数据),总共为512位或256位。

  2. 另一个always模块是在rd_clk(读取数据的时钟)的上升沿触发,它根据FIFO的阿尔莫斯特空(almost empty)信号来设置对应带宽的读控制信号(Ren)和数据有效控制信号(dvalid),如果FIFO不空,则启动读操作并声明数据有效,否则停止读操作并声明数据无效。

  3. 实例化一个FIFO生成器。FIFO的输入包括复位信号、写时钟、读时钟、数据输入、写使能、读使能、数据输出、阿尔莫斯特空信号等接口。在每个周期,输入的数据根据写使能信号是否有效,被放入FIFO,然后再根据读使能信号是否有效,从FIFO中取出。

最后,主要有两个部分:

一个是根据Bw_para选择包装哪一个带宽的数据,这也是一个在rd_clk上升沿触发的always模块。

另一个是一个被命名为inst_pack的FIFO生成器,它将根据Bw_para选择的数据进行打包处理。

这个模块同样使用了一个逻辑分析器来对一些重要的信号进行采样和调试。

总的来说,这是一个对不同带宽数据进行处理和打包的模块,其中,每个不同带宽数据首先经过自己对应的部分进行预处理(如控制信号生成等),然后根据参数选择一种带宽的数据,交给FIFO生成器进行处理和打包。

解释2:

这段Verilog代码基本上是一个处理并打包不同带宽数据的模块。以下是每一部分的细节解析和注释:

一段一段看对代码的理解效果会更好。

首先分析起始的输入输出部分,以下的这些则是该模块的输入与输出:

module DataPacket_module (
    input adc_clk,                              // 输入,基础ADC时钟信号
    input [3:0]Bw_para,                         // 输入,带宽参数
    input [31:0]sample_num,                     // 输入,采样数量
    input sys_rst,                              // 输入,系统复位信号
    input [255:0]adc1_Idout_t1,                 // 输入,ADC输出I通道数据
    input [255:0]adc1_Qdout_t1,                 // 输入,ADC输出Q通道数据
    input [255:0]adc1_Idout_t2,                 // 输入,ADC输出I通道数据
    input [255:0]adc1_Qdout_t2,                 // 输入,ADC输出Q通道数据
    input [255:0]adc1_Idout_t3,                 // 输入,ADC输出I通道数据
    input [255:0]adc1_Qdout_t3,                 // 输入,ADC输出Q通道数据
    input adc_valid_t1,                         // 输入,ADC有效数据信号t1
    input adc_valid_t2,                         // 输入,ADC有效数据信号t2
    input adc_valid_t3,                         // 输入,ADC有效数据信号t3
    input rd_clk,                               // 输入,数据读取时钟
    output [255:0]rd_dout,                      // 输出,数据读出口
    input rd_en,                                // 输入,数据读取使能信号
    output pack_aempty                          // 输出,数据读出口为空信号
);

然后模块内部包含几个子模块,这边我们以3600M带宽处理部分为例进行走读。

首先定义3600M带宽处理所需的相关寄存器和信号:

    reg [511:0]BW3600M_Din;             // 3600M带宽数据输入
    reg BW3600M_Wen;                    // 3600M带宽数据写使能
    reg BW3600M_Ren;                    // 3600M带宽数据读取使能
    wire  BW3600M_aempty;               // 3600M带宽数据是否为empty的状态信号
    wire[255:0]  BW3600M_dout;          // 3600M带宽数据输出
    reg BW3600M_dvalid;                 // 3600M带宽数据是否有效

接着是处理输入数据和输出数据的部分:

    always@(posedge adc_clk)
    begin
        BW3600M_Wen <= adc_valid_t1;
        BW3600M_Din <= {
                        adc1_Qdout_t1[127:120],adc1_Idout_t1[127:120],
                        adc1_Qdout_t1[119:112],adc1_Idout_t1[119:112],
                        // ...省略部分类似代码...
                        adc1_Qdout_t1[135:128],adc1_Idout_t1[135:128]};
    end
    always@(posedge rd_clk)
    begin
        if(~BW3600M_aempty)
        begin
            BW3600M_Ren <= 1;
            BW3600M_dvalid <= 1;
        end
        else
        begin
            BW3600M_Ren <= 0;
            BW3600M_dvalid <= 0;
        end
    end

这两部分代码确保了在每个ADC时钟上升沿,如果数据有效,就把ADC的Q通道和I通道数据打包进Din字段,而在每个数据读取时钟上升沿,如果数据不为空,则设置Ren和dvalid字段。

再来看FIFO生成器的实例:

    fifo_generator_4 inst_BW3600M(
      .rst(sys_rst),                    // 输入,系统复位信号
      .wr_clk(adc_clk),                 // 输入,写入信号的时钟
      .rd_clk(rd_clk),                  // 输入,读取信号的时钟
      .din(BW3600M_Din),                // 输入,数据写入数据
      .wr_en(BW3600M_Wen),              // 输入,数据写入使能信号
      .rd_en(BW3600M_Ren),              // 输入,数据读取使能信号
      .dout(BW3600M_dout),              // 输出,数据读出数据
      .full(),                          // 输出,FIFO满信号
      .almost_full(),                   // 输出,FIFO几乎满的信号
      .empty(),                         // 输出,FIFO空信号
      .almost_empty(BW3600M_aempty),    // 输出,FIFO几乎空的信号
      .wr_rst_busy(),                   // 输出,写入复位忙标志
      .rd_rst_busy()                    // 输出,读取复位忙标志
    );

这个是FIFO库组件的一个实例,基本用于缓存采集的数据,这样可以在ADC和读取者之间建立一个异步的桥梁,当然这个模块的一个重要作用也是能够容纳在连续ADC周期中,可能存在的并行有效的AD数据。

对应的1200M和2400M带宽处理部分实现逻辑和上述3600M部分基本一致,只是在数据打包和读取上有一些不同,这个依据实际的需求和ADC的参数来进行调整。

接下来的部分是根据带宽参数选择读取不同的带宽数据:

  always@(posedge rd_clk)
  begin
    case(Bw_para)
        4'd4:begin
            pack_wen <= BW3600M_dvalid;  
            pack_din <= BW3600M_dout;
        end
        4'd3:begin
            pack_wen <= BW2400M_dvalid;  
            pack_din <= BW2400M_dout;
        end
        4'd2:begin
            pack_wen <= BW1200M_dvalid;  
            pack_din <= BW1200M_dout;
        end
        default:begin
            pack_wen <= BW3600M_dvalid;  
            pack_din <= BW3600M_dout;
        end
    endcase
  end

这段代码的职责就是对Bw_para进行判断,并根据其值来选择来自哪种带宽的FIFO数据作为pack_din,并同步设定pack_wen的使能信号。

下面的另一个FIFO生成器负责根据带宽参数选择数据进行打包:

  fifo_generator_8 inst_pack (
    .clk(rd_clk),                   // 输入,数据读取时钟
    .srst(sys_rst),                 // 输入,系统复位信号
    .din(pack_din),                 // 输入,待打包的数据
    .wr_en(pack_wen),               // 输入,写入使能信号
    .rd_en(rd_en),                  // 输入,读取使能信号
    .dout(rd_dout),                 // 输出,读出的数据
    .full(),                        // 输出,满的状态信号
    .empty(),                       // 输出,空的状态信号
    .almost_empty(pack_aempty),     // 输出,几乎为空的状态信号
    .almost_full(),                 // 输出,几乎满的状态信号
    .wr_rst_busy(),                 // 输出,写入复位忙标志
    .rd_rst_busy()                  // 输出,读取复位忙标志
  );

这个FIFO生成器是用来收集选择的数据并准备输出。

最后代码中实例化了一个用于逻辑分析器的模块,用于debug和状态监控:

  ila_4 inst_packet (
  .clk(rd_clk),                   // 输入,时钟信号
  .probe0(Bw_para),               // 输入,带宽参数信息
  .probe1(pack_wen),              // 输入,打包数据写入使能信号
  .probe2(BW3600M_aempty),        // 输入,3600M带宽状态信号
  .probe3(BW3600M_Ren),           // 输入,3600M带宽数据读取使能信号
  .probe4(adc_valid_t1),          // 输入,ADC有效数据信号t1
  .probe5(BW3600M_Ren),           // 输入,3600M带宽数据读取使能信号
  .probe6(BW3600M_aempty),        // 输入,3600M带宽状态信号
  .probe7(BW3600M_Ren),           // 输入,3600M带宽数据读取使能信号
  .probe8(BW3600M_aempty),        // 输入,3600M带宽状态信号
  .probe9(BW3600M_Ren),           // 输入,3600M带宽数据读取使能信号
  .probe10(rd_en),                // 输入,数据读取使能信号
  .probe11(pack_aempty)           // 输入,打包数据几乎为空的状态信号
  );

以上就是对整个代码的详细解析。这个模块的作用就是对不同的ADC数据,进行分流处理,然后根据带宽参数对数据进行打包并输出。


五、 FIR_Module.v

程序代码如下:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2019/03/04 11:33:36
// Design Name: 
// Module Name: FIR_Module
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module FIR_Module(
    input adc_clk,
    input [255:0]adc_Idin,
    input [255:0]adc_Qdin,
    input adc_valid_in,
    input prf,
    output  adc_valid_out,
    output  adc_valid_out2,
    output  adc_valid_out3,
    output  [255:0]adc_FIR_Idout,
    output  [255:0]adc_FIR_Qdout,
    output  [255:0] adc_FIR_Idout_1200M,
    output  [255:0] adc_FIR_Qdout_1200M,
    output  [255:0] adc_FIR_Idout_2400M,
    output  [255:0] adc_FIR_Qdout_2400M
    );
    reg prf_r1;
    reg prf_r2;
    reg prf_r3;
    reg prf_fall;
    reg prf_fall_r1;
    reg prf_fall_r2;
    reg prf_fall_r3;
    reg prf_fall_r4;
    reg prf_fall_r5;
    reg prf_fall_r6;
    reg prf_rst;
    always@(posedge adc_clk)
    begin
        prf_r1 <= prf;
        prf_r2 <= prf_r1;
        prf_r3 <= prf_r2;
        prf_fall <= (~prf_r2) && prf_r3;
        prf_fall_r1 <= prf_fall;
        prf_fall_r2 <= prf_fall_r1;
        prf_fall_r3 <= prf_fall_r2;
        prf_fall_r4 <= prf_fall_r3;
        prf_fall_r5 <= prf_fall_r4;
        prf_fall_r6 <= prf_fall_r5;
        prf_rst <= prf_fall || prf_fall_r1 || prf_fall_r2 || prf_fall_r3 || prf_fall_r4 || prf_fall_r5 || prf_fall_r6;
    end
  
    wire [1023:0]adc1_Idout_FIR_tmp;
    wire [1023:0]adc1_Qdout_FIR_tmp;
    wire adc1_valid_Iout_tmp;
    wire adc1_valid_Qout_tmp;
    
    wire [1023:0]adc2_Idout_FIR_tmp;
    wire [1023:0]adc2_Qdout_FIR_tmp;
    wire adc2_valid_Iout_tmp;
    wire adc2_valid_Qout_tmp;
    
    wire [1023:0]adc3_Idout_FIR_tmp;
    wire [1023:0]adc3_Qdout_FIR_tmp;
    wire adc3_valid_Iout_tmp;
    wire adc3_valid_Qout_tmp;
    fir_compiler_0 inst_fir_I (
      .aresetn(~prf_rst),                        // input wire aresetn
      .aclk(adc_clk),                              // input wire aclk
      .s_axis_data_tvalid(adc_valid_in),  // input wire s_axis_data_tvalid
      .s_axis_data_tready(),  // output wire s_axis_data_tready
      .s_axis_data_tdata(adc_Idin),    // input wire [255 : 0] s_axis_data_tdata
      .m_axis_data_tvalid(adc1_valid_Iout_tmp),  // output wire m_axis_data_tvalid
      .m_axis_data_tdata(adc1_Idout_FIR_tmp)    // output wire [1023 : 0] m_axis_data_tdata
    );
    fir_compiler_0 inst_fir_Q (
     .aresetn(~prf_rst),                        // input wire aresetn
     .aclk(adc_clk),                              // input wire aclk
     .s_axis_data_tvalid(adc_valid_in),  // input wire s_axis_data_tvalid
     .s_axis_data_tready(),  // output wire s_axis_data_tready
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值