串行数据发送器

框图

串行数据发送器_第1张图片

  • THR:发送保持寄存器

    • 定义了两种状态:空,满
    • 数据写入端口地址:00H
    • 状态读出端口地址:00H
    • 当THR不满时,可以向THR写入数据
  • TSR:发送移位寄存器

    • 一旦TSR空而THR中有数据时,THR中的数据就送到TSR
    • RSR中的数据以串行方式从TxD段发送,高位在前,低位在后
    • 在TxD端的bit流中,若连续出现5个’1‘,则在第5个’1‘之后自动插入一个’0’。注意:相邻两个字节之间也会出现5个连续的‘1’
      串行数据发送器_第2张图片
      在这里插入图片描述
  • 发送时许
    串行数据发送器_第3张图片
    串行数据发送器_第4张图片
    串行数据发送器_第5张图片
    串行数据发送器_第6张图片
    串行数据发送器_第7张图片

串行数据发送器_第8张图片

  • 代码
module p2s_transmitter (
   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

你可能感兴趣的:(fpga开发)