赞
踩
这次工作中接触到了AD9528这个亚诺半导体的时钟发生芯片,可以产生多路同步的时钟。这个时钟使用spi接口进行相应的配置。后面记录自己如何针对这个过程进行相应FPGA代码编写。
具体我们在项目中使用了,五路时钟,我们的配置要求如下所示:
官网中有相应的可以下载的上位机软件,可以进行相应的配置,配置之后就可以知道相应的需要配置的寄存器参数是什么。
这个是咨询厂家之后的基本配置方法,具体的配置原理,要详细的阅读datasheet,具体的就是OUT1 OUT2两个时钟需要使用从PLL2 divider中产生的时钟
具体需要配置的寄存器如下:
针对这个时序图,我们就开始展开代码编写了:
- // -----------------------------------------------------------------------------
- // Copyright (c) 2014-2023 All rights reserved
- // -----------------------------------------------------------------------------
- // Author : xibo wu (Gatsby)
- // File : spi.v
- // Create : 2023-10-25 16:16:08
- // Revise : 2023-10-27 13:46:23
- // Editor : sublime text3, tab size (4)
- // -----------------------------------------------------------------------------
-
-
-
- module spi_module
- (
- input i_clk , // 全局时钟100MHz
- input i_rst_n , // 复位信号,低电平有效
-
- // 四线标准SPI信号定义
- input i_spi_miso , // SPI串行输入,用来接收从机的数据
- output o_spi_sck , // SPI时钟
- output o_spi_cs , // SPI片选信号
- output o_spi_mosi // SPI输出,用来给从机发送数据
- );
-
-
-
- //-------parameter--------//
- parameter TX_IDLE = 4'b0001;
- parameter TX_HEADER = 4'b0010;
- parameter TX_PAYLOAD = 4'b0100;
- parameter TX_END = 4'b1000;
-
-
- //-----parameter_reg-------//
- //---form “addr_data”------//
- parameter REG_1 = 24'h0104_01;
- parameter REG_2 = 24'h0100_01;
- parameter REG_3 = 24'h0102_01;
- parameter REG_4 = 24'h0204_01;
- parameter REG_5 = 24'h0201_14;
- parameter REG_6 = 24'h010A_02;
- parameter REG_7 = 24'h0208_13;
- parameter REG_8 = 24'h0501_E0;
- parameter REG_9 = 24'h0502_3F;
- parameter REG_10 = 24'h0302_11;
- parameter REG_11 = 24'h030E_23;
- parameter REG_12 = 24'h0303_00;
- parameter REG_13 = 24'h0305_05;
- parameter REG_14 = 24'h0308_05;
-
- //---------regs-----------//
- reg [4:0] tx_bit_sel;
- reg wr_en;
- reg [3:0] clk_cnt;
- reg cs_n_t;
- reg sck_t = 1'b0;
- reg [4:0] reg_cnt = 5'd14; //此处还不明确后续需要更改
- reg mosi_t;
- reg [23:0] reg_cfg; //可变的寄存器写入配置数值
-
- //--------debug-----------//
- reg [23:0] reg_debug;
-
-
-
-
-
- reg [3:0] cur_state;
- reg [3:0] nxt_state;
- reg skip_en;
-
-
-
- //-------assign----------//
- assign o_spi_sck = sck_t;
- assign o_spi_cs = cs_n_t;
- assign o_spi_mosi = mosi_t;
-
-
-
- //---------debug-----------//
-
-
- always @(posedge i_clk or negedge i_rst_n) begin
- if (i_rst_n == 1'b0) begin
- reg_debug <= 24'b0;
- end else if(cs_n_t == 1'b0 && clk_cnt == 'd1) begin
- reg_debug <= {reg_debug[22:0],mosi_t};
- end else begin
- reg_debug <= reg_debug;
- end
- end
- //---------main------------//
- always @(posedge i_clk or negedge i_rst_n) begin
- if (i_rst_n == 1'b0) begin
- clk_cnt <= 4'b0;
- end else if(clk_cnt == 'd3) begin
- clk_cnt <= 'd0;
- end else begin
- clk_cnt <= clk_cnt + 4'd1;
- end
- end
-
- //要在sck上升沿之前把数据准备好
- always @(posedge i_clk or negedge i_rst_n) begin
- if (i_rst_n == 1'b0) begin
- wr_en <= 1'b0;
- end else if(clk_cnt == 'd2) begin
- wr_en <= 1'b1;
- end else begin
- wr_en <= 1'b0;
- end
- end
-
- always @(posedge i_clk or negedge i_rst_n) begin
- if (i_rst_n == 1'b0) begin
- sck_t <= 1'b0;
- end else if(clk_cnt == 'd1 && cs_n_t == 1'b0) begin
- sck_t <= 1'b1;
- end else if(clk_cnt == 'd3 && cs_n_t == 1'b0) begin
- sck_t <= 1'b0;
- end else begin
- sck_t <= sck_t;
- end
- end
-
-
- // 寄存器数据配置单元 j
-
- always @(posedge i_clk or posedge i_rst_n) begin
- if (i_rst_n == 1'b0) begin
- reg_cfg <= REG_1;
- end else begin
- case(reg_cnt)
- 5'd14 : reg_cfg <= REG_1 ;
- //中间后续填充相应的寄存器数值
- 5'd13 : reg_cfg <= REG_2 ;
- 5'd12 : reg_cfg <= REG_3 ;
- 5'd11 : reg_cfg <= REG_4 ;
- 5'd10 : reg_cfg <= REG_5 ;
- 5'd9 : reg_cfg <= REG_6 ;
- 5'd8 : reg_cfg <= REG_7 ;
- 5'd7 : reg_cfg <= REG_8 ;
- 5'd6 : reg_cfg <= REG_9 ;
- 5'd5 : reg_cfg <= REG_10;
- 5'd4 : reg_cfg <= REG_11;
- 5'd3 : reg_cfg <= REG_12;
- 5'd2 : reg_cfg <= REG_13;
- 5'd1 : reg_cfg <= REG_14;
- default:;
- endcase
- end
- end
-
-
- always @(posedge i_clk or negedge i_rst_n) begin
- if (i_rst_n == 1'b0) begin
- cur_state <= TX_IDLE;
- end else begin
- cur_state <= nxt_state;
- end
- end
-
- always @(*) begin
- nxt_state = TX_IDLE;
- case (cur_state)
- TX_IDLE : begin
- if (skip_en) begin
- nxt_state = TX_HEADER;
- end else begin
- nxt_state = TX_IDLE;
- end
- end
- TX_HEADER : begin
- if (skip_en) begin
- nxt_state = TX_PAYLOAD;
- end else begin
- nxt_state = TX_HEADER;
- end
- end
-
- TX_PAYLOAD : begin
- if (skip_en) begin
- nxt_state = TX_END;
- end else begin
- nxt_state = TX_PAYLOAD;
- end
- end
-
- TX_END : begin
- if (skip_en) begin
- nxt_state = TX_IDLE;
- end else begin
- nxt_state = TX_END;
- end
- end
-
- default : nxt_state = TX_IDLE;
- endcase
- end
-
- always @(posedge i_clk or negedge i_rst_n) begin
- if (i_rst_n == 1'b0) begin
- skip_en <= 1'b0;
- cs_n_t <= 1'b1;
- tx_bit_sel <= 5'd0;
- end else begin
- skip_en <= 1'b0;
- case (nxt_state)
- TX_IDLE : begin
- if(reg_cnt != 'd0) begin
- skip_en <= 1'b1;
- end else begin
- cs_n_t <= 1'b1;
- end
- end
- TX_HEADER : begin
- cs_n_t <= 1'b0;
- if (wr_en == 1'b1) begin
- tx_bit_sel <= tx_bit_sel + 'd1;
- cs_n_t <= 1'b0;
- case(tx_bit_sel)
- 5'd0 : mosi_t <= reg_cfg[23]; //读写位
- 5'd1 : mosi_t <= reg_cfg[22]; //空
- 5'd2 : mosi_t <= reg_cfg[21]; //空
- 5'd3 : mosi_t <= reg_cfg[20]; //addr[12]
- 5'd4 : mosi_t <= reg_cfg[19]; //addr[11]
- 5'd5 : mosi_t <= reg_cfg[18]; //addr[10]
- 5'd6 : mosi_t <= reg_cfg[17]; //addr[9]
- 5'd7 : mosi_t <= reg_cfg[16]; //addr[8]
- 5'd8 : mosi_t <= reg_cfg[15]; //addr[7]
- 5'd9 : mosi_t <= reg_cfg[14]; //addr[6]
- 5'd10 : mosi_t <= reg_cfg[13]; //addr[5]
- 5'd11 : mosi_t <= reg_cfg[12]; //addr[4]
- 5'd12 : mosi_t <= reg_cfg[11]; //addr[3]
- 5'd13 : mosi_t <= reg_cfg[10]; //addr[2]
- 5'd14 : mosi_t <= reg_cfg[9]; //addr[1]
- 5'd15 : begin
- mosi_t <= reg_cfg[8]; //addr[0]
- tx_bit_sel <= 'd0;
- skip_en <= 1'b1;
- end
- endcase
- end
- end
-
- TX_PAYLOAD : begin
- cs_n_t <= 1'b0;
- if (wr_en == 1'b1) begin
- tx_bit_sel <= tx_bit_sel + 'd1;
- case(tx_bit_sel)
- 5'd0 : mosi_t <= reg_cfg[7]; //data[7]
- 5'd1 : mosi_t <= reg_cfg[6]; //data[6]
- 5'd2 : mosi_t <= reg_cfg[5]; //data[5]
- 5'd3 : mosi_t <= reg_cfg[4]; //data[4]
- 5'd4 : mosi_t <= reg_cfg[3]; //data[3]
- 5'd5 : mosi_t <= reg_cfg[2]; //data[2]
- 5'd6 : mosi_t <= reg_cfg[1]; //data[1]
- 5'd7 : begin
- mosi_t <= reg_cfg[0]; //data[0]
- tx_bit_sel <= 'd0;
- skip_en <= 1'b1;
- end
- endcase
- end
- end
-
- TX_END : begin
- if(reg_cnt != 'd0) begin
- reg_cnt <= reg_cnt - 1'd1;
- skip_en <= 1'b1;
- end
- end
- default :;
- endcase
- end
- end
-
-
- endmodule

仿真结果如下:
该文章仅用来交流,有错误欢迎各位指正。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。