框图
-
THR:发送保持寄存器
- 定义了两种状态:空,满
- 数据写入端口地址:00H
- 状态读出端口地址:00H
- 当THR不满时,可以向THR写入数据
-
TSR:发送移位寄存器
- 一旦TSR空而THR中有数据时,THR中的数据就送到TSR
- RSR中的数据以串行方式从TxD段发送,高位在前,低位在后
- 在TxD端的bit流中,若连续出现5个’1‘,则在第5个’1‘之后自动插入一个’0’。注意:相邻两个字节之间也会出现5个连续的‘1’
-
发送时许
- 代码
module p2s_tramsmitter (
RST,CLK2M,CS,FS,WR,RD,A0,D,TxD
);
input RST,CLK2M,CS,WR,RD,FS;
input A0;
inout [7:0] D;
output TxD;
reg TxD;
wire [7:0] D;
reg [7:0] THR_Status,THR,TSR,R_Shifter;
// R_Shifter 最低为TxD_1;
reg [2:0] Count8;
reg [2:0] Count5;
reg [4:0] Count32;
reg TSR_Shift_EN;
reg Mux_Sel1,Mux_Sel2;
reg TxD_2;
reg Load_EN;
reg THR_Read;
// 移位寄存器,load操作为:每当移完一个字节的数据并且THR不空时,
// 就从THR加载一个数据
// 在TSR_Shift_EN信号有效时,TSR做移位操作
always @(posedge RST or posedge CLK2M) begin
if (RST)
TSR <= 8'b00000000;
else if (Count8 ==3'b000&&THR_Status[0] == 1) begin
TSR <= THR;
end else if (TSR_Shift_EN == 1'b1)
TSR <= {TSR[6:0],1'b0};
end
//连续5个‘1’的检测及插‘0’。
always @(posedge RST or posedge CLK2M) begin
if (RST)
Count5 = 3'b100;
else if (TSR[7] == 1'b0)
Count5 = 3'b100;
else
Count5 = Count5 - 1;
end
always @(TSR or Mux_Sel1) begin
if (Mux_Sel1)
TxD_2 = 1'b0;
else
TxD_2 = TSR[7];
end
always @(Count5) begin
if (Count5 == 3'b000)
Mux_Sel1 = 1'b1;
else
Mux_Sel1 = 1'b0;
end
//在发送5个连续的‘1’之后要插入一个‘0’,此时TSR不移位。
// always @(Count5) begin
// if (Count5 == 3'b000)
// TSR_Shift_EN = 1'b0;
// else
// TSR_Shift_EN = 1'b1;
// end 等价于
always @(Mux_Sel1) begin
TSR_Shift_EN = ~Mux_Sel1;
end
//正常数据与发送7EH的处理
always @(Mux_Sel1 or TxD or R_Shifter) begin
if (Mux_Sel2)
TxD = R_Shifter[7];
else
TxD = TxD_2;
end
always @(posedge RST or posedge CLK2M) begin
if (RST)
R_Shifter = 8'b01111110;
else if (Load_EN)
R_Shifter = 8'b01111110;//7EH
else
R_Shifter = {R_Shifter[6:0],R_Shifter[7]};
end
always @(posedge RST or posedge CLK2M) begin
if (RST)
Count32 = 5'b11111;
else if (~FS)
Count32 = 5'b11111;
else if (TSR_Shift_EN)
Count32 = Count32 - 1;
end
// 对TSR移位32次,即进入空闲态,因此Count32对TSR_Shift_EN进行计数
always @(Count32) begin
if (Count32 == 5'b00000)
Load_EN = 1'b1;
else
Load_EN = 1'b0;
end
always @(Load_EN) begin
Mux_Sel2 = Load_EN;
end
always @(posedge RST or posedge CLK2M) begin
if (RST)
THR = 8'b00000000;
else if (CS == 1'b0&&WR == 1'b0&&A0 == 1'b0)
THR = D;
end
//THR_Status是一个状态信号,由于该状态最终可以被处理器通过总线读取,因此可以将它设置为
//8bits,当THR中有数据时为00000001,否则为00000000;
// 该信号应该是寄存器信号,无论THR中是否有数据,只要TSR发出一个读信号,那么在
// 读信号有效的下一个时钟沿,该信号为空
always @(posedge RST or posedge CLK2M) begin
if (RST)
THR_Status = 8'b00000000;
else if (WR == 1'b0 && THR_Read == 1'b1 &&A0 == 1'b0)
THR_Status = 8'b00000001;
else if (WR == 1'b1 && THR_Read == 1'b0)
THR_Status = 8'b00000000;
end
always @(Count8) begin
if (Count8 == 3'b000)
THR_Read = 1'b0;
else
THR_Read = 1'b1;
end
always @(posedge RST or posedge CLK2M) begin
if (RST)
Count8 = 3'b000;
else if (~FS)
Count8 = 3'b111;
else if (TSR_Shift_EN)
Count8 = Count8 - 1;
end
assign D = (RD == 1'b0 &&A0 == 1'b0)?THR_Status:8'bzzzzzzzz;
endmodule