多个IC之间的同步问题及串并转换问题

系统同步

两个IC之间的通信,但是两个IC之间通信的时钟由同一个时钟源发出,要考虑的信号的建立时间与保持时间延迟,时钟上也要考虑到两个时钟的时钟抖动和时钟偏斜。

系统同步电路图

 

源同步

两个IC之间的通信,前一个IC不仅给后一个IC数据信号也给后一个IC时钟信号,后一个IC的接受数据就是以接受到的时钟信号为同步进行接受,要调整转发时钟的输出时间,数据线长度一定要和走线长度相匹配。

源同步电路图

 

自同步

两个IC之间通信,数据和时钟信息都在一个信息流中发出,后一个IC要根据接受到的数据流对数据流进行解析,一般用作高速串行传输中,比如serdes aurora类的

自同步的发出端要完成并串转换,将并行数据转换为串行数据流发出,接收端完成串并转换将串行数据流转换为并行数据流发出,并同时在数据流内部完成时钟数据恢复。

自同步电路图

 

并串转换实现:

verilog design example
// 并串转换,使用组合逻辑将高位赋值给串行输出,可以取最高位或者最低位输出,要看移位寄存器;
//高位输出,先高位后低位
assign out = left_shift[7];
//需要8个时钟周期完成一个8位信号的并串转换;
always@(posedge clk or negedge rstn)
begin
    if(!rstn)
        left_shift <= 8'b0;
    else if (en)
        left_shift <= data_out;
    else
        left_shift <= {left_shift[6:0],1'b0};
end



-------------------------------------低位输出-----------------------------------
//低位并串转换采用右移寄存器实现
assign out = right_shift[0];
//需要8个时钟周期完成一个8位信号的并串转换;
always@(posedge clk or negedge rstn)
begin
    if(!rstn)
        right_shift <= 8'b0;
    else if (en)
        right_shift <= data_out;
    else
        right_shift <= {1'b0,left_shift[7:1]};
end



串并转换实现:

简单的串转并

verilog desigen example
//简单的串转并变换如下:
always@(posedge clk)
    dout <= {dout[6:0],din};//高位先发的情况
    // dout <= {din,dout[7:1]}; //低位先发的情况

//串并转换,转换成N位的并行数据需要N个时间,实际使用时作用的是一帧一帧数据,如果单独的通过串并转换可能并非是一帧数据,也就是说以8位为1组完成串并转换,如果数据连续发送这时候可以通过利用一组乒乓模式完成串并转换,当一帧数据发送完毕时乒一帧数据的寄存器归零,乓一帧数据的寄存器开始发送,当然如果数据不是连续发送则可以通过一帧数据发送完毕将寄存器归零等待下次发送
下面模拟一下连续发送模式下的乒乓转换模式,可以使用状态机完成也可以使用两组时序逻辑块完成

module pingpang(
input clk,
input rstn,
input en,
input din,
output [7:0] dout
    );
reg [2:0] state,n_state;
reg [3:0] cnt;
reg cnt_en;
reg done;
reg [7:0] dout_reg;
parameter idle = 3'b001,
            ping = 3'b010,
            pang = 3'b100; 
    always@(posedge clk or negedge rstn)
        begin
            if(~rstn)
                state <= idle;
            else 
                state <= n_state;
        end
    always@(posedge clk)
        begin
            if(cnt_en)
                cnt   <= cnt+1;
            else
                cnt   <= 4'd0;
        end 
    always@(posedge clk or negedge rstn)
        begin
            if(~rstn)
                done <= 1'b0;
            else if (cnt == 4'd7)
                done <= 1'b1;
            else
                done <= 1'b0;
        end
        
    always@(*)
        begin
            if(~rstn)
                n_state <= idle;
            else
                  case(state)
                    idle: 
                        begin
                            if(en)
                                begin
                                n_state <= ping;
                                cnt_en  <= 1'b1;
                                end
                            else
                                begin
                                n_state <= idle;
                                cnt_en   <= 1'b0;
                                end
                        end
                    ping:
                         begin
                             if(!en)
                                begin
                                n_state  <= idle;
                                cnt_en   <= 1'b0;
                                end
                             else if (cnt == 4'd7)
                                begin
                                n_state   <= pang;
                                cnt_en    <= 1'b0;
                                end
                             else
                                begin
                                n_state   <= ping;
                                cnt_en    <= 1'b1;
                                end
                         end
                    pang:
                         begin
                             if(!en)
                                begin
                                n_state  <= idle;
                                cnt_en   <= 1'b0;
                                end
                             else if(cnt == 4'd7)
                                begin
                                n_state   <= ping;
                                cnt_en    <= 1'b0;
                                end
                             else
                                begin
                                n_state   <= pang;
                                cnt_en    <= 1'b1;
                                end
                         end
                    default:
                        begin
                                n_state   <= idle;
                                cnt_en    <= 1'b0;
                        end
                endcase
        end
    always@(posedge clk or negedge rstn)
        begin
            if(~rstn)
            dout_reg <= 8'b0;
            else if(en)
            dout_reg[cnt] <= din;
            else
            dout_reg <= dout_reg;
        end
    assign dout = (done)?dout_reg:dout;

endmodule

连续传输模式下的串转并tb如下

module tb_pingpang(

    );
// pingpang Parameters
parameter PERIOD = 10    ;
parameter idle  = 3'b001;

// pingpang Inputs
reg   clk                                  = 0 ;
reg   rstn                                 = 0 ;
reg   en                                   = 0 ;
reg   din                                  = 0 ;

// pingpang Outputs
wire  [7:0]  dout                          ;    


initial
begin
    forever #(PERIOD/2)  clk=~clk;
end

initial
begin
    #(PERIOD*2) rstn  =  1;
end

pingpang #(
    .idle ( idle ))
 u_pingpang (
    .clk                     ( clk         ),
    .rstn                    ( rstn        ),
    .en                      ( en          ),
    .din                     ( din         ),

    .dout                    ( dout  [7:0] )
);

initial
begin
    #(PERIOD*5) en <= 1'b1;
end
initial
begin
    #(45)din <= 1;
    #(PERIOD)   din <= 1;
    #(PERIOD)   din <= 0;
    #(PERIOD)   din <= 1;
    #(PERIOD)   din <= 1;
    #(PERIOD)   din <= 0;
    #(PERIOD)   din <= 0;
    #(PERIOD)   din <= 1;
  //一帧
    #(PERIOD)   din <= 0;
    #(PERIOD)   din <= 1;
    #(PERIOD)   din <= 0;
    #(PERIOD)   din <= 0;
    #(PERIOD)   din <= 0;
    #(PERIOD)   din <= 0;
    #(PERIOD)   din <= 1;
    #(PERIOD)   din <= 0;
  //一帧
    #(PERIOD)   din <= 1;
    #(PERIOD)   din <= 1;
    #(PERIOD)   din <= 0;
    #(PERIOD)   din <= 0;
    #(PERIOD)   din <= 0;
    #(PERIOD)   din <= 0;
    #(PERIOD)   din <= 1;
end
endmodule

自同步过程中的时钟恢复通过锁相环合成与生成输入串行数据流的相匹配的时钟

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值