mengjinzhe的个人空间 https://blog.eetop.cn/1793905 [收藏] [复制] [分享] [RSS]

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

UART串口回环测试 Verilog实现(FPGA测试成功)

已有 692 次阅读| 2022-7-14 16:32 |系统分类:芯片设计| 简单串口回环

一次Trig写入一个byte 发出去一个byte,如果再增加一个FIFO就好了
module UART_TX 
#(  
    parameter BAUDRATE = 115200,
    parameter FREQ_CLK = 50000000
)(
    TX_DOUT,
    TX_DONE,
    TX_ACTIVE,
    
    CLK,
    RSTB,
    
    TX_DIN,
    TX_TRIG

);

output reg          TX_DOUT;
output reg          TX_DONE;
output reg          TX_ACTIVE;
                    
input  wire         CLK;
input  wire         RSTB;
input  wire         TX_TRIG;
input  wire  [7:0]  TX_DIN;

reg [15:0] DIV_CNT;
reg [3:0]  BIT_INDEX;
reg [7:0]  TX_DATA_REG;
reg [2:0]  TX_PST;
reg [2:0]  TX_NST;
reg        DIV_CNT_INC;
reg        DIV_CNT_CLR;
reg        BIT_INDEX_INC;
reg        BIT_INDEX_CLR;
reg        DATA_ONE;
reg        DATA_ZERO;
reg        TX_TRIG_1P;
reg        TX_TRIG_2P;
reg        TX_TRIG_3P;
reg        TX_EN;
wire       TX_TRIG_RISE;
wire       TX_1bit;

parameter    NCPB = FREQ_CLK/BAUDRATE; //NUMBER_CLK_PER_BIT
parameter    TX_IDLE  = 3'b000;
parameter    TX_START = 3'b001;
parameter    TX_DATA  = 3'b010;
parameter    TX_STOP  = 3'b011;
parameter    TX_FINISH  = 3'b100;

always@(posedge CLK or negedge RSTB)begin
    if(!RSTB)begin
        TX_PST    <= TX_IDLE;
        TX_DONE   <= 1'b0;
        TX_ACTIVE <= 1'b0;
  end else if(TX_TRIG_RISE)begin
    TX_PST    <= TX_IDLE;
        TX_DONE   <= 1'b0;
        TX_ACTIVE <= 1'b0;
    end else begin
        TX_PST    <= TX_NST;
        TX_DONE   <= (TX_NST == TX_FINISH);
        TX_ACTIVE <= (|TX_PST[1:0]);
    end
end

always@(posedge CLK or negedge RSTB)begin
    if(!RSTB)begin
        TX_DATA_REG <= 8'h00;
    end else begin
        TX_DATA_REG <= TX_DIN;
    end
end

always@(posedge CLK or negedge RSTB)begin
    if(!RSTB)begin
        TX_DOUT <= 1'b0;
    end else if(DATA_ONE) begin
        TX_DOUT <= 1'b1;
    end else if(DATA_ZERO) begin
        TX_DOUT <= 1'b0;
    end 
end

always@(posedge CLK or negedge RSTB)begin
    if(!RSTB)begin
        DIV_CNT <= 16'h00;
    end else if(DIV_CNT_INC) begin
        DIV_CNT <= DIV_CNT + 1'b1;
    end else if(DIV_CNT_CLR) begin
        DIV_CNT <= 16'h00;
    end 
end

always@(posedge CLK or negedge RSTB)begin
    if(!RSTB)begin
        BIT_INDEX <= 4'h0;
    end else if(BIT_INDEX_INC) begin
        BIT_INDEX <= BIT_INDEX + 1'b1;
    end else if(BIT_INDEX_CLR) begin
        BIT_INDEX <= 16'h00;
    end 
end

always@(posedge CLK or negedge RSTB)begin
    if(!RSTB)begin
        {TX_TRIG_1P,TX_TRIG_2P,TX_TRIG_3P} <= 3'b0;
    end else begin
        {TX_TRIG_1P,TX_TRIG_2P,TX_TRIG_3P} <= {TX_TRIG,TX_TRIG_1P,TX_TRIG_2P};
    end
end

assign TX_TRIG_RISE = TX_TRIG_2P & !TX_TRIG_3P;

always@(posedge CLK or negedge RSTB)begin
    if(!RSTB)begin
        TX_EN <= 1'b0;
    end else if(TX_DONE) begin
        TX_EN <= 1'b0;
    end else if(TX_TRIG_RISE)begin
        TX_EN <= 1'b1;
    end

end

assign TX_1bit = DIV_CNT >= NCPB; 
always@(*) begin
    TX_NST        = TX_PST;
    DIV_CNT_INC   = 1'b0;
    DIV_CNT_CLR   = 1'b0;
    BIT_INDEX_INC = 1'b0;
    BIT_INDEX_CLR = 1'b0;
    DATA_ONE      = 1'b0;
    DATA_ZERO     = 1'b0;

    case(TX_PST) 
        TX_IDLE : begin
            DATA_ONE = 1'b1;
            if(TX_EN)
                TX_NST = TX_START;
            else 
                TX_NST = TX_IDLE;
        end

        TX_START : begin
            DATA_ZERO = 1'b1;
            if(DIV_CNT <= NCPB )begin
                DIV_CNT_INC = 1'b1;
            end else begin
                DIV_CNT_CLR = 1'b1;
                TX_NST      = TX_DATA;
            end
        end

        TX_DATA : begin
            if(TX_DATA_REG[BIT_INDEX])
                DATA_ONE  = 1'b1;
            else
                DATA_ZERO = 1'b1; 
            
            if(DIV_CNT <= NCPB )begin
                DIV_CNT_INC = 1'b1;
            end else begin
                DIV_CNT_CLR   = 1'b1;
                if(BIT_INDEX != 3'h7)begin
                    BIT_INDEX_INC = 1'b1;
                end else begin
                    BIT_INDEX_CLR = 1'b1;
          TX_NST = TX_STOP;
                end
                
            end
        end

        TX_STOP : begin
            DATA_ONE = 1'b1;
            if(DIV_CNT <= NCPB )begin
                DIV_CNT_INC = 1'b1;
            end else begin
                DIV_CNT_CLR = 1'b1;
                TX_NST      = TX_FINISH;
            end
        end

        TX_FINISH : begin
            DATA_ONE  = 1'b1;
            DIV_CNT_CLR = 1'b1;
            BIT_INDEX_CLR = 1'b1;
            TX_NST = TX_IDLE;
        end
    default : TX_NST = TX_IDLE;
    endcase

end

endmodule
module UART_RX 
#(  
    parameter BAUDRATE = 115200,
    parameter FREQ_CLK = 50000000
)(
    RX_DOUT,
    RX_VALID,
    RX_ACTIVE,
    
    CLK,
    RSTB,
    
    RX_DIN,
    RX_TRIG

);

output reg  [7:0]    RX_DOUT;
output reg           RX_VALID;
output reg           RX_ACTIVE;
    
input  wire          CLK;
input  wire          RSTB;
input  wire          RX_TRIG;
input  wire          RX_DIN;

reg [15:0] DIV_CNT;
reg [7:0]  RX_DATA_REG;
reg [3:0]  BIT_INDEX;
reg [2:0]  RX_PST;
reg [2:0]  RX_NST;
reg        DIV_CNT_INC;
reg        DIV_CNT_CLR;
reg        BIT_INDEX_INC;
reg        BIT_INDEX_CLR;
reg        BIT_WRITE;
reg        BIT_CLR;
reg        RX_TRIG_1P;
reg        RX_TRIG_2P;
reg        RX_TRIG_3P;
reg        RX_EN;
wire       RX_TRIG_RISE;

reg        RX_DIN_1P;
reg        RX_DIN_2P;

parameter    NCPB = FREQ_CLK/BAUDRATE; //NUMBER_CLK_PER_BIT
parameter    RX_IDLE  = 3'b000;
parameter    RX_START = 3'b001;
parameter    RX_DATA  = 3'b010;
parameter    RX_STOP  = 3'b011;
parameter    RX_DONE  = 3'b100;

always@(posedge CLK or negedge RSTB)begin
    if(!RSTB)begin
        RX_PST     <= RX_IDLE;
        RX_VALID   <= 1'b0;
        RX_ACTIVE  <= 1'b0;
    end else begin
        RX_PST    <= RX_NST;
        RX_VALID  <= (RX_PST == RX_DONE);
        RX_ACTIVE <= (|RX_PST[1:0]);
    end
end

always@(posedge CLK or negedge RSTB)begin
    if(!RSTB)begin
        {RX_DIN_1P,RX_DIN_2P} <= 2'b0;
    end else begin
        {RX_DIN_1P,RX_DIN_2P} <= {RX_DIN,RX_DIN_1P};
    end
end

always@(posedge CLK or negedge RSTB)begin
    if(!RSTB)begin
        RX_DATA_REG <= 8'h00;
    end else if(BIT_WRITE) begin
        RX_DATA_REG[BIT_INDEX] <= RX_DIN_2P;
    end else if(BIT_CLR) begin
        RX_DATA_REG <= 8'h00;
    end 
end

always@(posedge CLK or negedge RSTB)begin
    if(!RSTB)begin
        RX_DOUT <= 8'h00;
    end else if(RX_VALID)begin
        RX_DOUT <= RX_DATA_REG;
    end 
end

always@(posedge CLK or negedge RSTB)begin
    if(!RSTB)begin
        DIV_CNT <= 16'h00;
    end else if(DIV_CNT_INC) begin
        DIV_CNT <= DIV_CNT + 1'b1;
    end else if(DIV_CNT_CLR) begin
        DIV_CNT <= 16'h00;
    end 
end

always@(posedge CLK or negedge RSTB)begin
    if(!RSTB)begin
        BIT_INDEX <= 4'h0;
    end else if(BIT_INDEX_INC) begin
        BIT_INDEX <= BIT_INDEX + 1'b1;
    end else if(BIT_INDEX_CLR) begin
        BIT_INDEX <= 16'h00;
    end 
end

always@(posedge CLK or negedge RSTB)begin
    if(!RSTB)begin
        {RX_TRIG_1P,RX_TRIG_2P,RX_TRIG_3P} <= 3'b0;
    end else begin
        {RX_TRIG_1P,RX_TRIG_2P,RX_TRIG_3P} <= {RX_TRIG,RX_TRIG_1P,RX_TRIG_2P};
    end
end

assign RX_TRIG_RISE = RX_TRIG_2P & !RX_TRIG_3P;

always@(posedge CLK or negedge RSTB)begin
    if(!RSTB)begin
        RX_EN <= 1'b0;
    end else if(RX_VALID) begin
        RX_EN <= 1'b0;
    end else if(RX_TRIG_RISE)begin
        RX_EN <= 1'b1;
    end

end
always@(*) begin
    RX_NST        = RX_PST;
    DIV_CNT_INC   = 1'b0;
    DIV_CNT_CLR   = 1'b0;
    BIT_INDEX_INC = 1'b0;
    BIT_INDEX_CLR = 1'b0;
    BIT_WRITE     = 1'b0;
    BIT_CLR       = 1'b0;

    case(RX_PST) 
        RX_IDLE : begin

            if(RX_EN && !RX_DIN_2P)
                RX_NST = RX_START;
            else 
                RX_NST = RX_IDLE;
        end

        RX_START : begin
            if(DIV_CNT < (NCPB/2 + 1'b1) )begin
                DIV_CNT_INC = 1'b1;
            end else begin
                DIV_CNT_CLR = 1'b1;
                if(!RX_DIN_2P)
                    RX_NST  = RX_DATA;
                else
                    RX_NST  = RX_IDLE;
            end
        end

        RX_DATA : begin
            if(DIV_CNT < NCPB )begin
                DIV_CNT_INC = 1'b1;
            end else begin
                DIV_CNT_CLR   = 1'b1;
                BIT_WRITE     = 1'b1;
                if(BIT_INDEX < 3'h7)begin
                    BIT_INDEX_INC = 1'b1;
                end else begin
                    BIT_INDEX_CLR = 1'b1;
                    BIT_CLR  = 1'b1;
                    RX_NST = RX_STOP;
                end
            end
        end

        RX_STOP : begin
            if(DIV_CNT < NCPB )begin
                DIV_CNT_INC = 1'b1;
            end else begin
                if(RX_DIN_2P)
                    RX_NST      = RX_DONE;
                else
                    RX_NST      = RX_IDLE;
            end
        end

        RX_DONE : begin
            DIV_CNT_CLR = 1'b1;
            BIT_INDEX_CLR = 1'b1;
            RX_NST = RX_IDLE;
        end
    default : RX_NST = RX_IDLE;
    endcase

end

endmodule
module UART_TOP(
  TX_DOUT,
  TX_ACTIVE,
  TX_DONE,
  RX_VALID,
  RX_ACTIVE,
  
  CLK,
  RSTB,
  RX_DIN,
  TX_TRIG,
  RX_TRIG
);

output  TX_DOUT;
output  TX_ACTIVE;
output  TX_DONE;
output  RX_VALID;
output  RX_ACTIVE;

input  CLK;
input  RSTB;
input  RX_DIN;

input  TX_TRIG;
input  RX_TRIG;

wire [7:0] RX_DOUT;


UART_RX U_UART_RX(
    .RX_DOUT(RX_DOUT),
    .RX_VALID(RX_VALID),
    .RX_ACTIVE(RX_ACTIVE),
    
    .CLK(CLK),
    .RSTB(RSTB),
    
    .RX_DIN(RX_DIN),
    .RX_TRIG(RX_TRIG)

);

UART_TX U_UART_TX(
    .TX_DOUT(TX_DOUT),
    .TX_DONE(TX_DONE),
    .TX_ACTIVE(TX_ACTIVE),
    
    .CLK(CLK),
    .RSTB(RSTB),
    
    .TX_DIN(RX_DOUT),
    .TX_TRIG(TX_TRIG)

);
endmodule



点赞

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 0

    关注
  • 0

    粉丝
  • 0

    好友
  • 0

    获赞
  • 0

    评论
  • 10

    访问数
关闭

站长推荐 上一条 /1 下一条

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-5-17 22:59 , Processed in 0.026176 second(s), 14 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部