임베디드랜드

 

여기 우리가 만들려는 리시버 그림이 있다.

 

이놈의 동작방식:

  • RxD로 부터 들어오는 신호를 조립한다.
  • 1바이트가 다 받아지는중엔, 'data'버스가 나타나고, 다 받은후엔 'data_ready'가 나타난다.
'data'는 'data_ready'가 나타날때 유효하다. 휴식기간중엔 새로운 데이터가 섞여 올수도 있으므로 사용치 않는다.
 


fpga4fun.com 의 FPGA interface projects 섹션에 serial interface 부분이 있다. 그 RS-232 부분의 번역본이다.
이문서의 원본은 http://www.fpga4fun.com/SerialInterface4.html 에서 찾을수 있다. from 후니유.

공부를 위한 목적으로 번역을 하였기때문에 오역,맘대로의역이 있어도 내맘이다 ㅋㅋ

Oversampling

비동기 리시버는 어찌되었던 입력신호와 함께 동기적으로 받게된다.(이는 전송중에 사용된 클럭을 이용한다는 것은 아니지만)

  • 새 데이터가 온다고 판단되면(start bit) 전송율주파수배만큼 신호를 오버샘플링해야한다.
  • start bit 가 탐지되면, 우리가 데이터를 받기위해서 알려진 전송률로 샘플링하게 된다.
리시버는 전통적으로 전송률에 비해 16배정도 오버 샘플링한다. 여기서는 8배정도로 하기로 한다. 115200 baud에서,921600Hz의 샘플링율을 가진다.
Baud8Tick을 921600 로 한다.

The Design

먼저 입력 RxD 신호는 우리 클럭과 상관이 없다.
오버샘플링하기 위해서 두개의 D-플립플롭을 사용했고 그것을 우리 클럭과 동기화를 시켰다.

reg [1:0] RxD_sync;
always @(posedge clk) if(Baud8Tick) RxD_sync <= {RxD_sync[0], RxD};

데이터를 필터하고, RxD 라인의 순간적 피크등의 값은 스타트비트로 인식하지 않는다.

reg [1:0] RxD_cnt;
reg RxD_bit;
always @(posedge clk)
if(Baud8Tick)
begin
if(RxD_sync[1] && RxD_cnt!=2'b11) RxD_cnt <= RxD_cnt + 1;
else
if(~RxD_sync[1] && RxD_cnt!=2'b00) RxD_cnt <= RxD_cnt - 1;
if(RxD_cnt==2'b00) RxD_bit <= 0;
else
if(RxD_cnt==2'b11) RxD_bit <= 1;
end

스테이트 머신은 각비트를 받아내며, 'start' 비트를 찾아낸다.

reg [3:0] state;
always @(posedge clk)
if(Baud8Tick)
case(state)
  4'b0000: if(~RxD_bit) state <= 4'b1000; // start bit found?
  4'b1000: if(next_bit) state <= 4'b1001; // bit 0
  4'b1001: if(next_bit) state <= 4'b1010; // bit 1
  4'b1010: if(next_bit) state <= 4'b1011; // bit 2
  4'b1011: if(next_bit) state <= 4'b1100; // bit 3
  4'b1100: if(next_bit) state <= 4'b1101; // bit 4
  4'b1101: if(next_bit) state <= 4'b1110; // bit 5
  4'b1110: if(next_bit) state <= 4'b1111; // bit 6
  4'b1111: if(next_bit) state <= 4'b0001; // bit 7
  4'b0001: if(next_bit) state <= 4'b0000; // stop bit
  default: state <= 4'b0000;
endcase

다음 비트로 가기 위해서 'next_bit'를 사용한다.

reg [2:0] bit_spacing;
always @(posedge clk)
if(state==0)
  bit_spacing <= 0;
else
if(Baud8Tick)
  bit_spacing <= bit_spacing + 1;
wire next_bit = (bit_spacing==7);

마지막으로 시프트레지스터 오는 데이터비트를 수집하게 된다.

reg [7:0] RxD_data;
always @(posedge clk) if(Baud8Tick && next_bit && state[3]) RxD_data <= {RxD_bit, RxD_data[7:1]};

Links

다음은 트랜스미터와 리시버모듈의 사용방법에 관한 포스트다. 여기를...

Posted by suvisor