Verilog UART

并转串——串转并

要求:并行输入1 byte,串行输出,无数据时输出高电平,输出格式1100+8bit+奇偶校验+0011(停止位)

串行输入,并行输出,检测是否奇偶校验错误,是否有帧传输错误

传输每bit数据占16个clock周期

//transmitter.v
module transmitter(in_clk,
                in_resetn,
                in_Data,
                in_DataEnable,
                out_NextData,
                out_Bit
                );
input in_clk;
input in_resetn;
input in_DataEnable;
input [7:0] in_Data;
output out_NextData;
output out_Bit;

parameter IDLE=16,STOP1=10,STOP2=11,STOP3=12,STOP4=13,START1=14,START2=15,START=1,D1=1,D2=2,D3=3,D4=4,D5=5,D6=6,D7=7,D8=8,PARITY=9;
reg [3:0] st, next_st;
reg [3:0] ClkCounter;
reg [8:0] StoredData;
reg out_NextData;
reg out_Bit;
reg oBit;

always @(posedge in_clk or negedge in_resetn)
if(!in_resetn)
    st <= IDLE;
else
    st <= next_st;

always @(posedge in_clk or negedge in_resetn)
   if(!in_resetn)
      ClkCounter <= 0;
   else
      ClkCounter <= ClkCounter + 1;

always @(ClkCounter or st or in_DataEnable)
   if(ClkCounter != 0)
       next_st =st;
   else
case(st)
    IDLE: if(in_DataEnable) next_st = STOP3;
    STOP3: next_st = STOP4;
    STOP4: next_st =START1;
    START1: next_st = START2;
    START2: next_st = D1;
    D1: next_st = D2;
    D2: next_st = D3;
    D3: next_st =D4;
    D4:next_st = D5;
    D5: next_st =D6;
    D6: next_st = D7;
    D7: next_st =D8;
    D8: next_st = PARITY;
    PARITY: next_st = STOP1;
    STOP1:next_st = STOP2;
    STOP2: next_st = STOP3;
    STOP3: next_st = STOP4;
    default: next_st = STOP3;
      endcase

always @(posedge in_clk or negedge in_resetn)
     if(!in_resetn)
        StoredData <= 0;
     else if(in_DataEnable)
        StoredData <= {in_Data,^in_Data};

always @(st or StoredData)
   case(st)
    IDLE: oBit=1;
        STOP1,STOP2: oBit = 0;
        STOP3,STOP4: oBit = 1;
        START1,START2:oBit = 0;
        D1:oBit = StoredData[8];
        D2:oBit = StoredData[7];
        D3:oBit = StoredData[6];
        D4:oBit = StoredData[5];
        D5:oBit = StoredData[4];
        D6:oBit = StoredData[3];
        D7:oBit = StoredData[2];
        D8:oBit = StoredData[1];
        PARITY:oBit = StoredData[0];
        default: oBit = 1;
    endcase
always @(posedge in_clk or negedge in_resetn)
if(!in_resetn)
    out_Bit <= 1;
else
    out_Bit <= oBit;

always @(st)
   if(st==STOP4)
      out_NextData =1;
   else
      out_NextData =0;

endmodule

//receiver.v
module receiver(in_clk,
              in_resetn,
              in_bit,
              out_Data,
              out_DataEnable,
              out_ParityError,
              out_FrameError
              );
input in_clk;
input in_resetn;
input in_bit;
output [7:0] out_Data;

output out_DataEnable;
output out_ParityError;
output out_FrameError;
reg [63:0] DetectSequence;
reg [3:0] ClkCounter;
reg [3:0] st, next_st;
reg [7:0] out_Data;
reg [7:0] store_data;
reg      Parity;
reg      Frame;
reg      out_DataEnable;
reg      out_ParityError;
reg      out_FrameError;

parameter IDLE=0, D1=1,D2=2,D3=3,D4=4,D5=5,D6=6,D7=7,D8=8,PARITY=9,STOP1=10,STOP2=11,STOP3=12,STOP4=13;

//detect
always @(posedge in_clk or negedge in_resetn)
   if(!in_resetn)
      DetectSequence <= 0;
   else
      DetectSequence <= { DetectSequence [62:0],in_bit};
assign DetectNewFrame = DetectSequence == 64'hFFFFFFFF00000000;

always @(posedge in_clk or negedge in_resetn)
   if(!in_resetn)
      ClkCounter <= 0;
   else if (DetectNewFrame)
      ClkCounter <= 0;
   else
      ClkCounter <= ClkCounter + 1'b1;

always @(posedge in_clk or negedge in_resetn)
   if(!in_resetn)
       st <= IDLE;
   else
       st <= next_st;

always @(ClkCounter or st or DetectNewFrame)
   if(ClkCounter != 0)
       next_st <= st;
   else
      case(st)
        IDLE: if (DetectNewFrame) next_st = D1;
        D1: next_st = D2;
        D2: next_st = D3;
        D3: next_st =D4;
        D4:next_st = D5;
        D5: next_st =D6;
        D6: next_st = D7;
        D7: next_st =D8;
        D8: next_st = PARITY;
        PARITY: next_st = STOP1;
        STOP1:next_st = STOP2;
        STOP2: next_st = STOP3;
        STOP3: next_st = STOP4;
        STOP4: next_st = IDLE;
        default: next_st = IDLE;
        endcase

always @(posedge in_clk or negedge in_resetn)
if(!in_resetn)
   begin
      out_Data=0;
      Parity=0;
      out_FrameError=0;
   end
else if(ClkCounter ==8)
    case(st)
      D1: store_data[7]=in_bit;
      D2: store_data[6]=in_bit;
      D3: store_data[5]=in_bit;
      D4: store_data[4]=in_bit;
      D5: store_data[3]=in_bit;
      D6: store_data[2]=in_bit;
      D7: store_data[1]= in_bit;
      D8:
         begin
         store_data[0]=in_bit;
         out_Data[7:0] = store_data[7:0];
        end
      PARITY: Parity=in_bit;
      STOP1: if(!in_bit) out_FrameError =1;
               else out_FrameError = 0;
      STOP2: if(!in_bit) out_FrameError =1;
               else out_FrameError = 0;
      STOP3: if(in_bit) out_FrameError =1;
               else out_FrameError = 0;
      STOP4: if(in_bit) out_FrameError =1;
               else out_FrameError = 0;
    endcase

always @(st or in_bit or Parity or out_Data)
   if((st == STOP4) & (in_bit))
     begin
        out_DataEnable = 1;
        out_ParityError = (Parity != ^out_Data);
     end
   else
     begin
        out_DataEnable = 0;
        out_ParityError = 0;
     end
endmodule

//test.v
module testbench1();
   
reg Clk,Reset;
wire BitWire;
reg [3:0] ClkCounter;
reg in_DataEnable;
reg [7:0] in_Data;
wire [7:0] out_Data;

//connect transmitter and receiver
transmitter DUT1(.in_clk(Clk),
                 .in_resetn(Reset),
                 .in_Data(in_Data),
                 .in_DataEnable(in_DataEnable),
                 .out_NextData(NextData),
                 .out_Bit(BitWire)
                 );
receiver DUT2(.in_clk(Clk),
              .in_resetn(Reset),
              .in_bit(BitWire),
              .out_Data(out_Data),
              .out_DataEnable(out_DataEnable),
              .out_ParityError(out_ParityError),
              .out_FrameError(out_FrameErrror)
              );

initial
   begin
     $dumpfile("uart.vcd");
     $dumpvars;
     $dumpon;
     Clk = 1'b0;
     Reset = 1'b0;
     #100 Reset=1'b1;
   end

always #5
   Clk <= !Clk;

always @(posedge Clk or negedge Reset)
   if(!Reset)
      ClkCounter <= 0;
   else
      ClkCounter <= ClkCounter + 1;

always @(posedge Clk or negedge Reset )
if(!Reset)
      begin
      in_Data=8'b0;
      in_DataEnable =1'b0;
      end
   else
   begin
   if((NextData) & (ClkCounter == 0))
     begin
     in_Data=$random;
     in_DataEnable =1'b1;
     $display("Issue data %h", in_Data);
     end
   else
     begin
     //in_Data=8'b0;
     in_DataEnable =1'b0;
     end
   end

always @(posedge Clk)
if(out_DataEnable)
begin
     if(out_ParityError)
        $display("Parity Error");
     else if (out_FrameErrror)
        $display("Frame Error");
     else
        $display("Receiver data %h", out_Data);
end

endmodule

posted on 2010-01-29 09:48  fpga_hjh  阅读(906)  评论(0编辑  收藏  举报

导航