RS-232常见引脚信号的定义
RXD-接收数据,TXD-发送数据,DTR-数据终端准备,GND-信号地,DSR-数据设备准备好,RTS-请求发送,CTS-清除发送。
串口也称为UART。在实际应用中,通常只用TXD和RXD两个引脚,而其它的引脚都不使用。UART接口时序图
在没有数据的情况下接口处于高电平(Mark),在数据发生前先将电平置低(space)一个周期,在该周期称为起始比特(Start bit),之后开始发送第0个到最后一个比特数据。UART接口每次可以发送6位或者7位,或8位数据。在数据位之后可以有选择地发送一个校验位,可以为奇校验,也可以为偶校验,校验位后的一个比特是一个或者多个停止位,此时数据线回归到高电平,可以进行下一个比特的发送。
发送模块的功能是将数据以串行的形式发送出去,并且将每一组的串行数据加上,开始位和停止位。当byte_ready信号有效时,数据被载入移位寄存器并添加开始位(低电平)和停止位(高电平)。当byte_ready信号无效时移位寄存器开始移位操作,将数据以串行的形式发送出去。
module UART_transmitter(clk,reset,byte_ready,data,TXD);
input clk,reset;
input byte_ready; //数据载入控制
input [7:0] data;
output TXD; //串行数据
reg [9:0] shift_reg;
assign TXD = shift_reg[0];
always @ (posedge clk or negedge reset) begin
if(!reset)
shift_reg <= 10'b1111_1111_11;
else if(byte_ready)
shift_reg <= {1'b1,data,1'b0}; //加起始位与终止位
else
shift_reg <= {1'b1,shift_reg[9:1]}; //输出串行数据
end
endmodule
接收模块的功能是接收发送模块输出的串行数据,并以并行的方式将数据送入存储器。当接收模块检测到开始位(低电平)时开始接收数据,并且输入串行数据存入移位寄存器,当接收完成时将数据并行输出。
module UART_receiver(clk,reset,RXD,data_out);
parameter idle = 2'b00;
parameter receiving = 2'b01;
input clk,reset;
input RXD; //串行数据
output [7:0] data_out;
reg shift; //移位控制
reg inc_count; //计数器加控制
reg [7:0] data_out,shift_reg;
reg [3:0] count;
reg [2:0] state,nstate;
always @ (state or RXD or count) begin
shift = 0;
inc_count = 0;
nstate = state;
case(state)
idle:if(!RXD) nstate = receiving; //监测起始信号
receiving: begin
if(count==8) begin
data_out = shift_reg; //数据输出
nstate = idle;
count = 0; //计数器清零
inc_count = 0;
end
else begin
inc_count = 1;
shift = 1;
end
end
default: nstate <= idle;
endcase
end
always @ (posedge clk or negedge reset) begin
if(!reset) begin
data_out <=8'b0;
count <= 0;
state <= idle;
end
else begin
state <= nstate;
if(shift)
shift_reg <= {shift_reg[6:0],RXD}; //接收串行数据
if(inc_count)
count <= count+1;
end
end
endmodule
测试代码:
module UART_tb;
reg clk,reset,byte_ready;
reg [7:0] data;
wire [7:0] data_out;
wire serial_data;
initial begin
clk = 0;
reset = 0;
byte_ready = 0;
data = 8'b1010_1010;
#40 byte_ready = 1;
#50 reset = 1;
#170 byte_ready = 0;
#1600 byte_ready = 1;
#170 byte_ready = 0;
reset = 0;
data = 8'b1100_0011;
#40 byte_ready = 1;
#50 reset = 1;
#170 byte_ready = 0;
#1600 byte_ready = 1;
#170 byte_ready = 0;
reset = 0;
data = 8'b101_1011;
#40 byte_ready = 1;
#50 reset = 1;
#170 byte_ready = 0;
end
always begin
#80 clk = ~clk;
end
UART_transmitter n1 (.clk(clk),.reset(reset),.byte_ready(byte_ready),.data(data),.TXD(serial_data));
UART_receiver n2 (.clk(clk),.reset(reset),.RXD(serial_data),.data_out(data_out));
endmodule