FPGA SPI协议读取TW-29开发板编码器信息

本项目通过spi协议读取TW29的64位包得到编码器信息,目前关于spi的例子大部分都是8位宽,位宽较短,本工程64位宽包含信息较多,且采用计数器逻辑巧妙,通过singaltap检验。

可读取编码器旋转的圈数与位置信息,实现25位细分,在超精密控制领域有着重要的作用,以下是项目的框架图与代码以及验证。

module  spi_rd_ctrl
(
    input   wire            sys_clk     ,
    input   wire            sys_rst_n   ,
    input   wire            key_flag    ,
    input   wire            miso		,
	
    output  reg             cs_n        ,
    output  reg             sck         ,
    output  reg             mosi
);

parameter   CNT_MAX = 9'd275,    
			CNT_MAX1 = 7'd64;    //64位
parameter   WREN_IN = 64'B0_0_0_100_00_00000000000000000000000000000000000000000000000000000000;//读指令60 59 58 为4

parameter   IDLE  = 4'B0001,
			WREN  = 4'B0010;

reg     [3:0]   state   ;
reg     [8:0]   cnt_clk ;//修改,0-275,276
reg     [6:0]   cnt_byte;//0-64,
reg     [1:0]   cnt_sck ;
reg     [1:0]   cnt_sck_a ;

reg     [63:0]  data/*synthesis noprune*/;
reg     [63:0]  data_reg/*synthesis noprune*/;

reg     [11:0]  RC/*synthesis noprune*/;//圈数/4095  42:31  
reg     [24:0]  NR/*synthesis noprune*/;//脉冲计数值/33554432  30:6 25位

//按键按下,进入写状态
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        state   <=  IDLE;
	else    if(key_flag == 1'b1)
        state   <=  WREN;

一个周期系统时钟计数276个,cnt_clk
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_clk <=  9'd0;
	else	if(state == WREN && cnt_clk < CNT_MAX)
		cnt_clk <= cnt_clk + 1'b1;
    else    if(cnt_clk == CNT_MAX)
        cnt_clk <=  9'd0;


//片选,根据案件按下拉低,系统时钟计数拉低
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cs_n    <=  1'b1;
    else    if(key_flag == 1'b1)//按键按下,拉低,进入写
        cs_n    <=  1'b0;
    else    if(cnt_clk == 9'd264)//写结束,拉高,等待时间
        cs_n    <=  1'b1;
    else    if(cnt_clk == 9'd275)//等待结束,拉低,进入下一个周期
        cs_n    <=  1'b0;

//cnt_sck_a,系统时钟分频计数,0123		
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_sck_a <=  2'd0;
    else    if(state == WREN )
        cnt_sck_a <=  cnt_sck_a + 1'b1;

//cnt_sck,系统时钟分频计数,0123		只有在写入的时候工作3-259
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_sck <=  2'd0;
    else    if(cnt_clk >= 9'd3 &&cnt_clk <= 9'd258)
        cnt_sck <=  cnt_sck + 1'b1;
//sck信号
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        sck <=  1'b0;
    else    if(cnt_sck == 2'd0)
        sck <=  1'b0;
    else    if(cnt_sck == 2'd2)
        sck <=  1'b1;


//0-68		
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_byte <=  7'd0;
    else    if(cnt_sck == 2'd2)
        cnt_byte <=  cnt_byte + 1'b1;
	else    if(cnt_byte == CNT_MAX1 )
        cnt_byte <=  7'd0;
		
//写入指令		
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        mosi    <=  1'b0;
    else    if(cnt_sck == 2'd0 &&(cnt_clk >= 9'd3 && cnt_clk <= 9'd256))
        mosi    <=  WREN_IN[63 - cnt_byte];

//data读取信号
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        data <=  1'b0;
    else    if(cnt_sck == 2'd0 &&(cnt_clk >= 9'd3 && cnt_clk <= 9'd256))
        data    <=  {data[63:0],miso};

//data_reg传递信号
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        data_reg <=  1'b0;
    else    if(cnt_clk == 9'd260)
        data_reg    <=  data;
		
			
//读取脉冲计数值32位4095
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        RC <=  1'b0;
    else    if(cnt_clk == 9'd260)
        RC <=  data[42:31];			
//读取NR 25位
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        NR <=  1'b0;
    else    if(cnt_clk == 9'd260)
        NR <=  data[30:6];		
		
endmodule

右图为IC-HAUS官方软件,显示编码器的位置信息,验证通过。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值