1. 주요 포인트
1. 구조 : TTL 레벨 직렬 포트는 두 개의 신호 라인으로 연결됩니다. 하나는 수신단 RX이고 다른 하나는 송신단 TX입니다. UART는 클록 라인이없고 배선이 간단한 직렬 인터페이스입니다.
2. 타이밍 : 정보 흐름의 시간 순서. 다음 그림은 직렬 포트의 타이밍 다이어그램입니다.
직렬 데이터는 프레임 단위로 전송됩니다. 프레임의 데이터 비트, 체크 비트 및 정지 비트를 구성 할 수 있습니다. 일반적으로 데이터 비트는 체크 비트가없는 8 비트이고 정지 비트는 1 비트입니다. 데이터 프레임에는 1 + 8이 포함됩니다. + 0 + 1 = 10 비트 (비트).
유휴 상태에서 버스는 하이이고 시작 비트는 로우 레벨로 고정됩니다. 유휴 상태에서 로우 레벨이 전송되면 데이터 프레임이 전송되기 시작하고 정지 비트가 하이 레벨로 고정되어 데이터 프레임의 끝을 나타냅니다.
3. Baud rate : 데이터 전송 속도, 즉 초당 전송할 수있는 비트 수입니다. 예를 들어, 115200의 전송 속도에서 즉, 초당 최대 115200 비트의 데이터 (시작 비트, 중지 비트 및 패리티 비트 포함)를 전송할 수 있으며, 데이터의 각 비트를 유지하는 데 필요한 시간은 1s / 115200≈8.68055us입니다.
둘째, 실현
1. 아키텍처 : 송신 모듈은 주로 세 부분으로 구성됩니다. 1. 카운터를 사용하여 보드 속도 타이밍을 실현합니다. 2. 모듈 상태를 전송합니다. 3. 송신 데이터를 입력합니다.
2. Verilog 언어 설명
새 uart_tx.v 파일 만들기
module uart_tx
(
input clk,
input nrst,
input tx_en,
input [7:0]tx_data,
output tx_pin,
output tx_done
);
위에서 설명한 모듈의 포트는 클럭, 재설정, 활성화, 데이터 전송, 핀 전송 및 완료 플래그 전송입니다.
parameter INPUT_CLK = 125000000 , BUDO = 115200;
localparam B_CNT_MAX = (INPUT_CLK/BUDO)-1;//波特率计数器最大值
reg [3:0]CS; //状态
reg [10:0]b_cnt; //用来产生波特率时钟
reg [10:0]tx_buf;//包含起始位与停止位的数据缓冲区
reg r_tx_pin;
reg r_txdone;
위는 모듈의 매개 변수, 로컬 매개 변수 및 사용 된 레지스터를 정의합니다. 모듈의 기본 입력 클럭은 125MHz이고 전송 속도는 115200입니다.
//CS依据波特率计数器自增,实现状态转移
task CS_increase;
if(CS == 'd10) begin //一帧完成,复位
CS <= 'd0;
b_cnt <= 'd0;
end
else if (b_cnt == B_CNT_MAX) begin//计数满1bti的发送时间,转移到下一个bit,计数器清零
CS <= CS + 1'b1;
b_cnt <= 'd0;
end
else //计数中
b_cnt <= b_cnt + 1'b1;
endtask
위는 다른 코드에서 호출되는 태스크를 정의하고 상태 천이를 실현하기 위해 보레이트 카운터에 따라 상태 레지스터 CS의 자체 증가를 실현합니다. 이 섹션은 전송 속도 타이밍과 상태 전환의 두 부분을 결합합니다.
always @(posedge clk) begin
if (!nrst) begin//复位
CS <= 'd0;
b_cnt <= 'd0;
tx_buf <= 'd0;
r_tx_pin <= 1'b1;
r_txdone <= 1'b1;
end
else if (tx_en) begin
//状态转移
CS_increase;
//各状态输出
if (CS == 'd0) begin
r_txdone <= 1'b0;//开始发送,发送完成标志置0
tx_buf <= {2'b11,tx_data,1'b0};
end
else if (CS == 'd10) begin
r_txdone <= 1'b1;//发送完成标志置1
tx_buf <= tx_buf;
end
else begin //正在发送数据位、停止位
r_txdone <= 1'b0;
tx_buf <= tx_buf;
end
r_tx_pin <= tx_buf[CS];//输出引脚数据更新
end
else
r_tx_pin <= 1'b1;
end
위의 부분은 송신 모듈의 주요 구조로, 클럭 상승 에지 이후에 리셋이 있는지 감지합니다. (nrst = 0 일 때 리셋) 리셋 태스크가없고 송신 모듈이 활성화되면 두 가지 태스크가 완료됩니다 : 1. 상태 전이 태스크 호출 CS_increase는 상태 천이를 실현합니다 .. 2. 상태 레지스터 CS에 따라 송신 레지스터 r_tx_pin과 송신 완료 레지스터 r_txdone에 값을 할당합니다.
상태 레지스터 CS의 각 값은 TX 라인의 각 전송 상태에 해당합니다 .CS = 0이면 시작 비트 전송을 시작 함을 의미합니다.이 때 전송할 데이터를 tx_buf에 채우고 1'b0이 시작 비트이고 tx_data가 데이터입니다. , 2'b11은 1 개의 정지 비트와 1 개의 종료 상태 (또는 정지 비트와 유휴 상태)를 합칠 때 전송되는 데이터입니다.
CS = 10은 정지 비트가 전송 된 후 다음 상태를 의미하며, 이때 tx 라인은 유휴 상태로 들어가 정지 비트처럼 1을 전송합니다. 이때 전송 완료 플래그 r_txdone은 1로 설정됩니다. (다음 맨 위 파일에서 전송 완료 플래그가 1로 설정되면 tx_en이 비활성화되어 상태 레지스터 CS를 전송할 수 없게됩니다. 달성 된 효과는 r_tx_pin <= 1'b1, 즉, tx 라인 고정 출력 1)입니다.
//驱动输出声明
assign tx_pin = r_tx_pin;
assign tx_done = r_txdone;
endmodule // uart_tx
마지막으로 출력 레지스터가 출력 네트워크로 구동되고 송신 모듈 정의가 완료됩니다.
3. 테스트 파일 작성, VCS 시뮬레이션 테스트
1. 테스트 파일 작성 : 클럭 생성, 활성화 신호 관리 및 전송 포함
새 uart_tb.v 파일 생성
`timescale 1ns/1ps
module uart_tb();
reg nrst;
reg clk;
reg en_tx;
reg [7:0] tx_data;
wire tx_pin,tx_done;
reg [7:0]tx_cnt;
//实例化
uart_tx uart_tx(
.clk(clk),
.nrst(nrst),
.tx_en(en_tx),
.tx_data(tx_data),
.tx_pin(tx_pin),
.txdone(tx_done)
);
테스트를위한 uart_tb 모듈을 정의하고, 관련 신호를 정의하고, uart_tx 모듈을 인스턴스화합니다.
//产生125Mhz的时钟
initial begin
clk = 0;
forever begin
#4;
clk = ~clk;
end
end
initial begin
en_tx = 0;
tx_data = 8'b0;
tx_cnt = 'd0;
nrst = 1;
#100;
nrst = 0;//复位信号
#103;
nrst = 1;
tx_data = 'd64;
end
125MHz 클록 생성 및 각 신호의 값 초기화
//产生循环发送的信号
always @(negedge clk) begin
if (nrst) begin
if (tx_done) begin
if (en_tx)//刚刚发送完成
en_tx <= 1'b0;
else begin//发送完成一段时间
if (tx_cnt == 'd250) begin
tx_cnt <= 'd0;
en_tx <= 1'b1;//重启发送
end
else
tx_cnt <= tx_cnt + 1'b1;
end
end
else begin
en_tx <= en_tx;
tx_cnt <= tx_cnt;
end
end
end
endmodule // usart_tb
tx_done이 high로 설정되면 전송이 완료되고 en_tx가 비활성화됨을 의미합니다. 그런 다음 tx_cnt를 사용하여 카운트하고 일정 시간 후에 en_tx를 다시 활성화하고 새 프레임 전송을 시작합니다.
2. VCS 시뮬레이션
uart_tx.v 및 uart_tb.v 파일을 같은 폴더에 넣고 디렉토리 경로에서 터미널을 열고 vcs -full64 * .v -debug_all 명령을 사용하여 컴파일합니다.
그런 다음 ./simv -gui 명령을 사용하여 GUI 그래픽 인터페이스를 열고 시뮬레이션을 위해 오실로스코프에 관련 신호를 추가합니다.
시뮬레이션 파형은 그림과 같습니다. 빨간색 라인에서 tx_done 신호는 상승하고 en_tx 신호는 하강합니다. 카운터에서 계수 한 기간이 지나면 en_tx가 다시 High로 설정됩니다.