CLK(1)——fixed-clock

本文详细介绍了Linux内核中固定时钟和固定分频因子时钟的概念,以及它们在设备节点如CAN节点中的配置。通过分析相关驱动函数,展示了如何初始化和使用这些时钟。同时,提供了相关驱动源代码,如`clk_osc24m`和`clk_pll_periph0x2`,展示了如何将pll时钟作为固定分频因子时钟的源。

简析内核中固定时钟及相关时钟的定义和初始化:

参考链接:
https://blog.youkuaiyun.com/zgtzqzg2020/article/details/109220048
https://www.freesion.com/article/4436438726/

can节点中配置的24M的固定时钟:

clk_osc24m: osc24m {
	#clock-cells = <0>;
	compatible = "allwinner,fixed-clock";
	clock-frequency = <24000000>;
	clock-output-names = "osc24m";
};

can0: can@0 {
	compatible = "microchip,mcp2515";
	pinctrl-names = "default";
	clocks = <&clk_osc24m>;
	status = "okay";
};
相关文件:
linux-4.9/drivers/clk/sunxi/clk-sunxi.c
linux-4.9/drivers/clk/sunxi/clk-sun50iw9.c
linux-4.9/include/linux/clk-provider.h

pll-clock和fixed-factor-clock(固定分频因子时钟),可以看到clk_pll_periph0x2使用clk_pll_periph0作为其时钟源:

clk_pll_periph0: pll_periph0 {
                        #clock-cells = <0>;
                        compatible = "allwinner,pll-clock";
                        assigned-clocks = <&clk_pll_periph0>;
                        assigned-clock-rates = <600000000>;
                        lock-mode = "new";
                        clock-output-names = "pll_periph0";
                };

clk_pll_periph0x2: pll_periph0x2 {
                        #clock-cells = <0>;
                        compatible = "allwinner,fixed-factor-clock";
                        clocks = <&clk_pll_periph0>;
                        clock-mult = <2>;
                        clock-div = <1>;
                        clock-output-names = "pll_periph0x2";
                };
固定时钟驱动函数:
static void __init of_sunxi_fixed_clk_setup(struct device_node *node)
{
        struct clk *clk;
        const char *clk_name = node->name;
        u32 rate;

        if (of_property_read_u32(node, "clock-frequency", &rate))
                return;

        if (of_property_read_string(node, "clock-output-names", &clk_name)) {
                pr_err("%s:get clock-output-names failed in %s node\n",
                                                __func__, node->full_name);
                return;
        }

        clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT, rate);
        if (!IS_ERR(clk)) {
                clk_register_clkdev(clk, clk_name, NULL);
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
        }
}

固定分频因子时钟驱动函数:
static void __init of_sunxi_fixed_factor_clk_setup(struct device_node *node)
{
        struct clk *clk;
        const char *clk_name = node->name;
        const char *parent_name;
        u32 div, mult;

        if (of_property_read_u32(node, "clock-div", &div)) {
                pr_err("%s Fixed factor clock <%s> must have a clock-div property\n",
                        __func__, node->name);
                return;
        }

        if (of_property_read_u32(node, "clock-mult", &mult)) {
                pr_err("%s Fixed factor clock <%s> must have a clokc-mult property\n",
                        __func__, node->name);
                return;
        }

        if (of_property_read_string(node, "clock-output-names", &clk_name)) {
                pr_err("%s:get clock-output-names failed in %s node\n",
                                                __func__, node->full_name);
                return;
        }
        parent_name = of_clk_get_parent_name(node, 0);

        clk = clk_register_fixed_factor(NULL, clk_name, parent_name, 0,
                                        mult, div);
        if (!IS_ERR(clk)) {
                clk_register_clkdev(clk, clk_name, NULL);
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
        }
}

CLK_OF_DECLARE(sunxi_clocks_init, "allwinner,clk-init", of_sunxi_clocks_init);
CLK_OF_DECLARE(sunxi_fixed_clk, "allwinner,fixed-clock", of_sunxi_fixed_clk_setup);
CLK_OF_DECLARE(sunxi_pll_clk, "allwinner,pll-clock", of_sunxi_pll_clk_setup);
CLK_OF_DECLARE(sunxi_fixed_factor_clk, "allwinner,fixed-factor-clock", of_sunxi_fixed_factor_clk_setup);
CLK_OF_DECLARE(sunxi_cpu_clk, "allwinner,cpu-clock", of_sunxi_cpu_clk_setup);
CLK_OF_DECLARE(sunxi_periph_clk, "allwinner,periph-clock", of_sunxi_periph_clk_setup);
CLK_OF_DECLARE(periph_cpus_clk, "allwinner,periph-cpus-clock", of_sunxi_periph_cpus_clk_setup);
#define CLK_OF_DECLARE(name, compat, fn) OF_DECLARE_1(clk, name, compat, fn)

TBC

//ad9361 top module ad9361_top( DDR_0_addr, DDR_0_ba, DDR_0_cas_n, DDR_0_ck_n, DDR_0_ck_p, DDR_0_cke, DDR_0_cs_n, DDR_0_dm, DDR_0_dq, DDR_0_dqs_n, DDR_0_dqs_p, DDR_0_odt, DDR_0_ras_n, DDR_0_reset_n, DDR_0_we_n, FIXED_IO_0_ddr_vrn, FIXED_IO_0_ddr_vrp, FIXED_IO_0_mio, FIXED_IO_0_ps_clk, FIXED_IO_0_ps_porb, FIXED_IO_0_ps_srstb, //spi config spi_csn, spi_clk, spi_mosi, spi_miso, en_agc, enable, resetb, txnrx , sync_in , ctrl_in, tx_clk_out_n, tx_clk_out_p, tx_frame_out_n, tx_frame_out_p, tx_data_out_n, tx_data_out_p, rx_clk_in_n, rx_clk_in_p, rx_frame_in_n, rx_frame_in_p , rx_data_in_n, rx_data_in_p, //test pin //TEST, //LED test led, // LED4 to LED1, 1 on, 0 off clk, // FPGA PL clock, 50 MHz rst_n // FPGA reset pin ); inout [14:0]DDR_0_addr; inout [2:0]DDR_0_ba; inout DDR_0_cas_n; inout DDR_0_ck_n; inout DDR_0_ck_p; inout DDR_0_cke; inout DDR_0_cs_n; inout [3:0]DDR_0_dm; inout [31:0]DDR_0_dq; inout [3:0]DDR_0_dqs_n; inout [3:0]DDR_0_dqs_p; inout DDR_0_odt; inout DDR_0_ras_n; inout DDR_0_reset_n; inout DDR_0_we_n; inout FIXED_IO_0_ddr_vrn; inout FIXED_IO_0_ddr_vrp; inout [53:0]FIXED_IO_0_mio; inout FIXED_IO_0_ps_clk; inout FIXED_IO_0_ps_porb; inout FIXED_IO_0_ps_srstb; output spi_csn; output spi_clk; output spi_mosi; input spi_miso; //ad9361 control signal output en_agc; output enable; output resetb; output txnrx; output sync_in; output [3:0] ctrl_in; //data port tx chanel output tx_clk_out_n; output tx_clk_out_p; output tx_frame_out_n; output tx_frame_out_p; output [5:0]tx_data_out_n; output [5:0]tx_data_out_p; //data port rx channel input rx_clk_in_n; input rx_clk_in_p; input rx_frame_in_n; input rx_frame_in_p; input [5:0]rx_data_in_n; input [5:0]rx_data_in_p; //test pin // output [3:0] TEST; //led stream test output reg [3:0] led; input clk; input rst_n; wire [31:0]gpio_o; assign txnrx = gpio_o[0]; assign enable = gpio_o[1]; assign resetb = gpio_o[2]; assign sync_in = gpio_o[3]; assign en_agc = gpio_o[4]; assign ctrl_in = gpio_o[8:5]; //***********************************AD9361驱动***********************************// wire data_clk, adc_d1q1_valid; wire [11:0] adc_data_d1, adc_data_q1; design_1_wrapper inst_design_1_wrapper ( .DDR_0_addr (DDR_0_addr), .DDR_0_ba (DDR_0_ba), .DDR_0_cas_n (DDR_0_cas_n), .DDR_0_ck_n (DDR_0_ck_n), .DDR_0_ck_p (DDR_0_ck_p), .DDR_0_cke (DDR_0_cke), .DDR_0_cs_n (DDR_0_cs_n), .DDR_0_dm (DDR_0_dm), .DDR_0_dq (DDR_0_dq), .DDR_0_dqs_n (DDR_0_dqs_n), .DDR_0_dqs_p (DDR_0_dqs_p), .DDR_0_odt (DDR_0_odt), .DDR_0_ras_n (DDR_0_ras_n), .DDR_0_reset_n (DDR_0_reset_n), .DDR_0_we_n (DDR_0_we_n), .FIXED_IO_0_ddr_vrn (FIXED_IO_0_ddr_vrn), .FIXED_IO_0_ddr_vrp (FIXED_IO_0_ddr_vrp), .FIXED_IO_0_mio (FIXED_IO_0_mio), .FIXED_IO_0_ps_clk (FIXED_IO_0_ps_clk), .FIXED_IO_0_ps_porb (FIXED_IO_0_ps_porb), .FIXED_IO_0_ps_srstb (FIXED_IO_0_ps_srstb), .GPIO_O_0 (gpio_o), .SPI0_MISO_I_0 (spi_miso), .SPI0_MOSI_O_0 (spi_mosi), .SPI0_SCLK_O_0 (spi_clk), .SPI0_SS_O_0 (spi_csn), .rx_clk_in_n_0 (rx_clk_in_n), .rx_clk_in_p_0 (rx_clk_in_p), .rx_data_in_n_0 (rx_data_in_n), .rx_data_in_p_0 (rx_data_in_p), .rx_frame_in_n_0 (rx_frame_in_n), .rx_frame_in_p_0 (rx_frame_in_p), .tx_clk_out_n_0 (tx_clk_out_n), .tx_clk_out_p_0 (tx_clk_out_p), .tx_data_out_n_0 (tx_data_out_n), .tx_data_out_p_0 (tx_data_out_p), .tx_frame_out_n_0 (tx_frame_out_n), .tx_frame_out_p_0 (tx_frame_out_p), .data_clk(data_clk), .adc_d1q1_valid(adc_d1q1_valid), .adc_data_d1(adc_data_d1), .adc_data_q1(adc_data_q1) ); //***********************************LEO接收通道***********************************// //wire clk_102_4; //CHn_LEO CHn_LEO( // .clk(data_clk), //51.2M // .rst(1'b0), // .ad_datai(adc_data_d1), // .adc_d1q1_valid(adc_d1q1_valid), // .ad_dataq(adc_data_q1), // .clk_102_4(clk_102_4) // ); //***********************************ILA测试***********************************// ila_top ila_top( //.clk(data_clk), .clk(data_clk),//clk=50MHz .probe0(data_clk), .probe1(adc_d1q1_valid), .probe2(adc_data_d1), .probe3(adc_data_q1)); ////***********************************TEST pins***********************************// //assign TEST[0] = data_clk; //assign TEST[1] = clk_102_4; //assign TEST[2] = 1'b0; //assign TEST[3] = clk; //******************************LED stream test**********************************// reg [31:0] cnt; reg [1:0] led_on_number; //clock input 50000000 parameter CLOCK_FREQ =50000000; parameter COUNTER_MAX_CNT=CLOCK_FREQ/2-1;//change time 0.5s always @(posedge clk, negedge rst_n) begin if(!rst_n) begin cnt <= 32'd0; led_on_number <= 2'd0; end else begin cnt <= cnt + 1'b1; if(cnt == COUNTER_MAX_CNT) begin//计数0.5s cnt <= 32'd0; led_on_number <= led_on_number + 1'b1; end end end always @(led_on_number) begin case(led_on_number) 0: led <= 4'b0001; 1: led <= 4'b0010; 2: led <= 4'b0100; 3: led <= 4'b1000; endcase end //******************************LED stream test**********************************// endmodule 这是原有的ad9361top文件,预计在这个文件上修改
最新发布
11-12
非常棒!你已经有一个完整的 AD9361 顶层模块(`ad9361_top`),它通过 `design_1_wrapper` 实例化了包含 ZYNQ PS 和 PL 逻辑的系统设计,并且已经能接收 AD9361 的 JESD204B-like 差分数据(实际是 LVDS 并行接口)并输出为 `adc_data_d1/q1`。 现在你的目标是:**在当前这个顶层设计的基础上,增加将 AD9361 接收到的 I/Q 数据通过 AXI DMA 写入 DDR 的功能**。 我们将基于你现有的代码进行 **最小侵入式修改**,逐步添加: - AXI DMA 所需的 AXI4-Stream 接口 - 数据打包成 32bit 流 - 连接到 AXI DMA IP(已在 Block Design 中配置好) - 确保时钟域同步(使用 `data_clk`) --- ## ✅ 修改目标总结 | 功能 | 实现方式 | |------|---------| | 获取 AD9361 数据 | 使用 `adc_data_d1`, `adc_data_q1`, `adc_d1q1_valid`, `data_clk` | | 打包为 AXI-Stream | 组合 I/Q → 32bit tdata,valid 对齐 | | 连接 AXI DMA | 添加 `s_axis_s2mm_*` 信号到 wrapper 或引出 | | 存储至 DDR | 由 AXI DMA 自动完成 | | 验证 | ILA 抓波形 + PS 软件读取 | --- # 🔧 第一步:确认 Block Design 中已配置 AXI DMA 请确保你在 Vivado 的 `design_1` 中已经做了以下事情: ### ✔️ 必须存在的 IP 和连接: ```text ZYNQ7 Processing System └─ S_AXI_HP0_FPD → 连接到 AXI DMA 的 M_AXI_S2MM AXI DMA (启用 S2MM) └─ s_axis_s2mm_tvalid, tready, tdata[31:0], tlast └─ s2mm_introut → IRQ_F2P[0] ``` > 如果没有,请回到 Vivado 编辑 BD,添加 AXI DMA IP 并正确连接 HP0 和中断。 导出后生成 `design_1_wrapper.v`,你会看到这些端口被暴露出来。 --- # 🔧 第二步:修改 `ad9361_top` 模块 —— 添加 AXI-Stream 到 DMA 我们将在 `ad9361_top` 中新增一个 AXI4-Stream 发送模块,把 `adc_data_d1/q1` 打包后送给 AXI DMA。 --- ### ✅ 修改后的完整 `ad9361_top`(关键部分更新) ```verilog module ad9361_top( // --- 原有端口(DDR, FIXED_IO, SPI, AD9361 IOs)--- DDR_0_addr, DDR_0_ba, DDR_0_cas_n, DDR_0_ck_n, DDR_0_ck_p, DDR_0_cke, DDR_0_cs_n, DDR_0_dm, DDR_0_dq, DDR_0_dqs_n, DDR_0_dqs_p, DDR_0_odt, DDR_0_ras_n, DDR_0_reset_n, DDR_0_we_n, FIXED_IO_0_ddr_vrn, FIXED_IO_0_ddr_vrp, FIXED_IO_0_mio, FIXED_IO_0_ps_clk, FIXED_IO_0_ps_porb, FIXED_IO_0_ps_srstb, // SPI config spi_csn, spi_clk, spi_mosi, spi_miso, // AD9361 control en_agc, enable, resetb, txnrx, sync_in, ctrl_in, // TX data (output) tx_clk_out_n, tx_clk_out_p, tx_frame_out_n, tx_frame_out_p, tx_data_out_n, tx_data_out_p, // RX data (input) rx_clk_in_n, rx_clk_in_p, rx_frame_in_n, rx_frame_in_p, rx_data_in_n, rx_data_in_p, // LED & Test led, clk, rst_n // --- 新增:AXI DMA S2MM 接口(可选引出,若未自动包含)--- // 若 design_1_wrapper 未自动带出 s_axis_s2mm,则需要手动添加如下端口: // s_axis_s2mm_tready, // s_axis_s2mm_tvalid, // s_axis_s2mm_tdata, // s_axis_s2mm_tlast ); // --- 原始 inout / input / output 声明 --- inout [14:0] DDR_0_addr; inout [2:0] DDR_0_ba; inout DDR_0_cas_n; inout DDR_0_ck_n; inout DDR_0_ck_p; inout DDR_0_cke; inout DDR_0_cs_n; inout [3:0] DDR_0_dm; inout [31:0] DDR_0_dq; inout [3:0] DDR_0_dqs_n; inout [3:0] DDR_0_dqs_p; inout DDR_0_odt; inout DDR_0_ras_n; inout DDR_0_reset_n; inout DDR_0_we_n; inout FIXED_IO_0_ddr_vrn; inout FIXED_IO_0_ddr_vrp; inout [53:0] FIXED_IO_0_mio; inout FIXED_IO_0_ps_clk; inout FIXED_IO_0_ps_porb; inout FIXED_IO_0_ps_srstb; // SPI output spi_csn; output spi_clk; output spi_mosi; input spi_miso; // Control output en_agc; output enable; output resetb; output txnrx; output sync_in; output [3:0] ctrl_in; // TX output tx_clk_out_n; output tx_clk_out_p; output tx_frame_out_n; output tx_frame_out_p; output [5:0]tx_data_out_n; output [5:0]tx_data_out_p; // RX input rx_clk_in_n; input rx_clk_in_p; input rx_frame_in_n; input rx_frame_in_p; input [5:0]rx_data_in_n; input [5:0]rx_data_in_p; // LED output reg [3:0] led; input clk; // FPGA 50MHz clock input rst_n; wire [31:0] gpio_o; assign txnrx = gpio_o[0]; assign enable = gpio_o[1]; assign resetb = gpio_o[2]; assign sync_in = gpio_o[3]; assign en_agc = gpio_o[4]; assign ctrl_in = gpio_o[8:5]; // --- 来自 design_1_wrapper 的 AD9361 数据输出 --- wire data_clk; // 数据有效时钟(例如 51.2MHz) wire adc_d1q1_valid; // 数据有效标志 wire [11:0] adc_data_d1; // I 通道(12bit) wire [11:0] adc_data_q1; // Q 通道(12bit) // --- AXI4-Stream to AXI DMA (S2MM) --- wire s_axis_s2mm_tready; reg s_axis_s2mm_tvalid; reg [31:0] s_axis_s2mm_tdata; reg s_axis_s2mm_tlast; // --- 可选:ILA 监控信号 --- wire probe_clk = data_clk; wire probe_valid = adc_d1q1_valid; wire [11:0] probe_i = adc_data_d1; wire [11:0] probe_q = adc_data_q1; //***********************************AD9361驱动***********************************// design_1_wrapper inst_design_1_wrapper ( // --- DDR and PS Connections --- .DDR_0_addr (DDR_0_addr), .DDR_0_ba (DDR_0_ba), .DDR_0_cas_n (DDR_0_cas_n), .DDR_0_ck_n (DDR_0_ck_n), .DDR_0_ck_p (DDR_0_ck_p), .DDR_0_cke (DDR_0_cke), .DDR_0_cs_n (DDR_0_cs_n), .DDR_0_dm (DDR_0_dm), .DDR_0_dq (DDR_0_dq), .DDR_0_dqs_n (DDR_0_dqs_n), .DDR_0_dqs_p (DDR_0_dqs_p), .DDR_0_odt (DDR_0_odt), .DDR_0_ras_n (DDR_0_ras_n), .DDR_0_reset_n (DDR_0_reset_n), .DDR_0_we_n (DDR_0_we_n), .FIXED_IO_0_ddr_vrn (FIXED_IO_0_ddr_vrn), .FIXED_IO_0_ddr_vrp (FIXED_IO_0_ddr_vrp), .FIXED_IO_0_mio (FIXED_IO_0_mio), .FIXED_IO_0_ps_clk (FIXED_IO_0_ps_clk), .FIXED_IO_0_ps_porb (FIXED_IO_0_ps_porb), .FIXED_IO_0_ps_srstb (FIXED_IO_0_ps_srstb), // --- GPIO 控制 AD9361 --- .GPIO_O_0 (gpio_o), // --- SPI Interface --- .SPI0_MISO_I_0 (spi_miso), .SPI0_MOSI_O_0 (spi_mosi), .SPI0_SCLK_O_0 (spi_clk), .SPI0_SS_O_0 (spi_csn), // --- AD9361 Data IOs --- .rx_clk_in_n_0 (rx_clk_in_n), .rx_clk_in_p_0 (rx_clk_in_p), .rx_data_in_n_0 (rx_data_in_n), .rx_data_in_p_0 (rx_data_in_p), .rx_frame_in_n_0 (rx_frame_in_n), .rx_frame_in_p_0 (rx_frame_in_p), .tx_clk_out_n_0 (tx_clk_out_n), .tx_clk_out_p_0 (tx_clk_out_p), .tx_data_out_n_0 (tx_data_out_n), .tx_data_out_p_0 (tx_data_out_p), .tx_frame_out_n_0 (tx_frame_out_n), .tx_frame_out_p_0 (tx_frame_out_p), // --- 输出 ADC 数据和时钟 --- .data_clk(data_clk), .adc_d1q1_valid(adc_d1q1_valid), .adc_data_d1(adc_data_d1), .adc_data_q1(adc_data_q1), // --- AXI DMA S2MM 接口(必须与 wrapper 中一致)--- .s_axis_s2mm_tready(s_axis_s2mm_tready), .s_axis_s2mm_tvalid(s_axis_s2mm_tvalid), .s_axis_s2mm_tdata(s_axis_s2mm_tdata), .s_axis_s2mm_tlast(s_axis_s2mm_tlast) ); //****************************** 数据打包为 AXI-Stream ******************************// // // 在 data_clk 域中将 I/Q 数据打包发送给 AXI DMA // always @(posedge data_clk or negedge rst_n) begin if (!rst_n) begin s_axis_s2mm_tvalid <= 0; s_axis_s2mm_tdata <= 0; s_axis_s2mm_tlast <= 0; end else begin s_axis_s2mm_tvalid <= adc_d1q1_valid; // 数据有效时置 valid s_axis_s2mm_tdata <= {adc_data_q1, adc_data_d1}; // 高16位=Q, 低16位=I s_axis_s2mm_tlast <= 1'b0; // 单样本模式,不标记帧结束(可选) end end //****************************** ILA 测试 ******************************// ila_top ila_top_inst ( .clk(probe_clk), .probe0(probe_clk), .probe1(probe_valid), .probe2(probe_i), .probe3(probe_q), .probe4(s_axis_s2mm_tvalid), .probe5(s_axis_s2mm_tready), .probe6(s_axis_s2mm_tdata[15:0]), .probe7(s_axis_s2mm_tdata[31:16]) ); //****************************** LED stream test ******************************// reg [31:0] cnt; reg [1:0] led_on_number; parameter CLOCK_FREQ = 50000000; parameter COUNTER_MAX_CNT = CLOCK_FREQ/2 - 1; // 0.5s always @(posedge clk or negedge rst_n) begin if (!rst_n) begin cnt <= 0; led_on_number <= 0; end else begin cnt <= cnt + 1; if (cnt == COUNTER_MAX_CNT) begin cnt <= 0; led_on_number <= led_on_number + 1; end end end always @(*) begin case(led_on_number) 0: led = 4'b0001; 1: led = 4'b0010; 2: led = 4'b0100; 3: led = 4'b1000; default: led = 4'b0001; endcase end endmodule ``` --- ## ✅ 关键说明 | 模块 | 作用 | |------|------| | `data_clk` | AD9361 提供的数据采样时钟(如 51.2MHz),所有 ADC 数据在此时钟下有效 | | `adc_d1q1_valid` | 表示当前周期数据有效(通常每个周期都有效) | | `{adc_data_q1, adc_data_d1}` | 组合成 24bit,但 AXI DMA 宽度为 32bit,高位补零自动处理 | | `tready` | 由 AXI DMA 提供,表示是否可以接收数据;若 `tready=0`,可能造成背压(建议加 FIFO) | --- ## ⚠️ 注意事项 1. **AXI DMA 数据宽度匹配** - 确保 AXI DMA 的 `S2MM Data Width = 32 bit` - 否则需用 `Axis Register Slice` 或 `DataWidthConverter` 2. **建议加入 AXIS FIFO 缓冲** ```verilog axis_data_fifo_0 fifo_inst ( .s_axis_tvalid(adc_d1q1_valid), .s_axis_tdata({adc_data_q1, adc_data_d1}), .s_axis_tready(), .m_axis_tvalid(s_axis_s2mm_tvalid), .m_axis_tdata(s_axis_s2mm_tdata), .m_axis_tlast(s_axis_s2mm_tlast), .m_axis_tready(s_axis_s2mm_tready), .s_axis_aresetn(rst_n), .s_axis_aclk(data_clk), .m_axis_aclk(data_clk) ); ``` 可防止 DMA 暂停时丢失数据。 3. **ILA 探测建议信号**: - `data_clk`, `adc_d1q1_valid`, `adc_data_d1/q1` - `s_axis_s2mm_tvalid`, `tready`, `tdata` - 观察握手是否成功 4. **PS 软件必须启动 DMA S2MM 传输** - 否则 PL 发送数据也不会被写入 DDR - 参考前文 Vitis 裸机代码中的 `XAxiDma_SimpleTransfer(...)` --- ## ✅ 验证步骤 1. **综合 → 实现 → 生成比特流** 2. **导出硬件到 Vitis** 3. **编写裸机程序启动 DMA 接收** 4. **运行后通过串口打印 DDR 数据** 5. **使用 ILA 抓取数据流是否连续** ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值