在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 216|回复: 4

[求助] spi client端,读取sclk信号时,为什么都没有考虑过亚稳态问题啊

[复制链接]
发表于 前天 17:17 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
请教大佬,spi client端,读取sclk信号时,为什么都没有考虑过亚稳态问题啊,百思不得其解

按我从课本上学的知识,这里显然应该打2拍吧
发表于 昨天 09:20 | 显示全部楼层
也不一定采SCLK(因为相对于接收方可能是2分频,甚至不分频),可能直接用SCLK驱动接收处理数据的cell,接收完成后,SCLK域发出握手,传输数据
 楼主| 发表于 昨天 11:22 | 显示全部楼层


蕾兹曼 发表于 2025-5-28 09:20
也不一定采SCLK(因为相对于接收方可能是2分频,甚至不分频),可能直接用SCLK驱动接收处理数据的cell,接 ...


谢谢!我看网上所有的实现,也都是这么做的,spi client的时钟是master传过来的,简简单单的同步电路,处理很简单。但是总感觉别扭,有点被 "入侵" 的感觉,自己的电路,怎么被别人使用呢:),而且所有教材上都没有着重提过这种用法,全部都是一个模块,都有自己独立的clk,这种用法,就是一个模块有两个clk了,不仔细分辨,有点混乱的感觉
发表于 昨天 14:10 | 显示全部楼层
本帖最后由 蕾兹曼 于 2025-5-28 14:13 编辑


erwang 发表于 2025-5-28 11:22
谢谢!我看网上所有的实现,也都是这么做的,spi client的时钟是master传过来的,简简单单的同步电路,处 ...


其实打拍对SCLK和mosi打拍也不是不行,就是要求sclk的频率起码要低于slave的工作时钟1/4。1/2时序可能会有不好的地方,具体也不知道(可能是难以满足全双工要求?打了两拍之后,原始输入就到了下一个SCLK周期)。公司前辈说的1/4可以打拍处理
 楼主| 发表于 昨天 14:39 | 显示全部楼层


蕾兹曼 发表于 2025-5-28 14:10
其实打拍对SCLK和mosi打拍也不是不行,就是要求sclk的频率起码要低于slave的工作时钟1/4。1/2时序可能会有 ...


这个对CDC友好,感觉上更正统,就是要检测sclk的边沿,稍感麻烦点

我找到个例子




  1. `include "defines.v"
  2. module SPI_SLAVE(
  3.     input   wire                        clk         ,
  4.     input   wire                        rst_n       ,
  5.     input   wire                        mosi        ,
  6.     input   wire                        sclk        ,
  7.     input   wire                        tx_finish   ,
  8.     input   wire                        start       ,
  9.     input   wire                        ss_n        ,

  10.     output  wire    [`DATA_WIDTH-1:0]   data_o      ,
  11.     //output  wire                        miso        ,
  12.     output  wire                        r_finish
  13. );
  14.     parameter       IDLE    =   4'b0001     ,
  15.                     RV_DATA =   4'b0010     ,
  16.                     FINISH  =   4'b0100     ;

  17.     wire                        sclk_posedge        ;
  18.     wire                        sclk_negedge        ;
  19.     wire                        dec_pos_or_neg_sample;
  20.     //wire                        sclk_posedge        ;
  21.     //wire                        sclk_negedge        ;


  22.     reg                         sclk_dly            ;
  23.     reg     [`DATA_WIDTH-1:0]   data_shift_pos      ;
  24.     reg     [`DATA_WIDTH-1:0]   data_shift_neg      ;
  25.     reg     [3:0]               state               ;
  26.     reg     [3:0]               nx_state            ;
  27.     reg     [3:0]               cnt_sclk_pos        ;
  28.     reg     [3:0]               cnt_sclk_neg        ;
  29.     wire    [3:0]               num_sample_data     ;

  30.     assign  sclk_posedge = ((sclk == 1'b1) && (sclk_dly == 1'b0)) ? 1'b1 : 1'b0;
  31.     assign  sclk_negedge = ((sclk == 1'b0) && (sclk_dly == 1'b1)) ? 1'b1 : 1'b0;
  32.     assign  dec_pos_or_neg_sample = (`CPOL == `CPHA) ? 1'b1 : 1'b0;
  33.     //assign  sclk_posedge = ((sclk == 1'b1) && (sclk_dly == 1'b0)) ? 1'b1 : 1'b0;
  34.     //assign  sclk_negedge = ((sclk == 1'b0) && (sclk_dly == 1'b1)) ? 1'b1 : 1'b0;
  35.     assign  num_sample_data = (dec_pos_or_neg_sample) ? cnt_sclk_pos : cnt_sclk_neg;
  36.    
  37.     always @(posedge clk or negedge rst_n) begin
  38.         sclk_dly <= sclk;
  39.     end

  40.     always @(posedge clk or negedge rst_n) begin
  41.         if(!rst_n) begin
  42.             state <= IDLE;
  43.         end
  44.         else begin
  45.             state <= nx_state;
  46.         end
  47.     end

  48.     always @(*) begin
  49.         nx_state <= IDLE;
  50.         case(state)
  51.             IDLE: nx_state <= start ? RV_DATA :IDLE;
  52.             RV_DATA: begin
  53.                 if((num_sample_data == 7) && (dec_pos_or_neg_sample) && (sclk_posedge) && (!ss_n)) begin
  54.                     nx_state <= FINISH;
  55.                 end
  56.                 else if((num_sample_data == 7) && (~dec_pos_or_neg_sample) && (sclk_negedge) && (!ss_n)) begin
  57.                     nx_state <= FINISH;
  58.                 end
  59.                 else begin
  60.                     nx_state <= RV_DATA;
  61.                 end
  62.             end
  63.             FINISH: nx_state <= IDLE;
  64.         endcase
  65.     end


  66.     always @(posedge clk or negedge rst_n) begin
  67.         if(!rst_n) begin
  68.             cnt_sclk_pos <= 4'd0;
  69.         end
  70.         else if((state == FINISH)) begin
  71.             cnt_sclk_pos <= 4'd0;
  72.         end
  73.         else if(sclk_posedge) begin
  74.             cnt_sclk_pos <= cnt_sclk_pos + 1'b1;
  75.         end
  76.         else begin
  77.             cnt_sclk_pos <= cnt_sclk_pos;
  78.         end
  79.     end

  80.     always @(posedge clk or negedge rst_n) begin
  81.         if(!rst_n) begin
  82.             cnt_sclk_neg <= 4'd0;
  83.         end
  84.         else if (state == FINISH) begin
  85.             cnt_sclk_neg <= 4'd0;
  86.         end
  87.         else if (sclk_negedge) begin
  88.             cnt_sclk_neg <= cnt_sclk_neg + 1'b1;
  89.         end
  90.         else begin
  91.             cnt_sclk_neg <= cnt_sclk_neg;
  92.         end
  93.     end

  94.     always @(posedge clk or negedge rst_n) begin
  95.         if(!rst_n) begin
  96.             data_shift_pos <= {`DATA_WIDTH{1'b0}};
  97.         end
  98.         else if((state == RV_DATA) && (sclk_posedge)) begin
  99.             data_shift_pos <= {mosi, data_shift_pos[`DATA_WIDTH-1:1]};
  100.         end
  101.         else if (state == FINISH) begin
  102.             data_shift_pos <= {`DATA_WIDTH{1'b0}};
  103.         end
  104.         else begin
  105.             data_shift_pos <= data_shift_pos;
  106.         end
  107.     end

  108.     always @(posedge clk or negedge rst_n) begin
  109.         if(!rst_n) begin
  110.             data_shift_neg <= {`DATA_WIDTH{1'b0}};
  111.         end
  112.         else if((state == RV_DATA) && (sclk_negedge)) begin
  113.             data_shift_neg <= {mosi, data_shift_neg[`DATA_WIDTH-1:1]};
  114.         end
  115.         else if(state == FINISH) begin
  116.             data_shift_neg <= {`DATA_WIDTH{1'b0}};
  117.         end
  118.         else begin
  119.             data_shift_neg <= data_shift_neg;
  120.         end
  121.     end

  122.     //assign data_o = dec_pos_or_neg_sample ? data_shift_pos : data_shift_neg;

  123.     assign  data_o = (state == FINISH) ? (dec_pos_or_neg_sample ? data_shift_pos : data_shift_neg): {`DATA_WIDTH{1'b0}};
  124.     assign  r_finish = (state == FINISH);




  125. endmodule



复制代码


您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /1 下一条

X

小黑屋| 手机版| 关于我们| 联系我们| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2025-5-29 05:40 , Processed in 0.017260 second(s), 7 queries , Gzip On, MemCached On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表