吃饱没事做之——用Verilog实现串口发送

串口协议,很容易理解,所以就由这个来上手。

串口分为三部分,至少我自己想实现的只有三部分。

起始状态、发数据状态还有停止位状态。

在这里起始位一位,停止位一位,数据位8位,没有奇偶校验。

本来加多了一个状态init,最后看到别人的那种可以一直发的,然后就把它注释掉了。

于是在这基础上,就选择用状态机了,其实用计数器更好一点。但都写一半就懒得改了。

本来想设置data变了就发串口的。最后还是注释掉了。

不会英语所以随便打了。。

贴代码:

module uart(
    input wire clk,
    input wire rst_n,
    input wire [7:0] data,
    output reg tx,
    input  wire fork_flag,
    output wire ok,
    output reg [3:0] bit
);
localparam init  = 'b0011;
localparam start = 'b0001;
localparam stop  = 'b0010;
localparam write = 'b0000;

reg [3:0]staus;

// wire data_flag;
// reg [7:0]data_d1;
// reg write_flag;
// always @(posedge clk or negedge rst_n)
// begin
//     if(!rst_n)
//     begin
//         data_d1 <= 8'b0;
//         write_flag <= 0;
//     end
//     else if(!data_flag)
//     begin
//         if(data_d1 != data)
//         begin
//             write_flag <= 1;
//         end
//         else
//         begin
//             write_flag <= 0;
//         end
//     end
//     else
//     begin
//         data_d1 <= data;
//     end
// end

assign data_flag = staus == write;
assign ok = bit == 8;
assign write_flag = fork_flag;

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
    begin
        staus <= stop;
    end
    // else if(staus == stop)
    // begin
    //     staus <= init;
    // end
    else if(staus == start)
    begin
        staus <= write;
    end
    else if(bit == 7)
    begin
        staus <= stop;
    end
    else if(write_flag & staus == stop)
    begin
        staus <= start;
    end
    else if((staus != stop) & (staus != write) & (staus != start))
    begin
        staus <= stop;
    end
    else 
    begin
        staus <= staus;
    end
end


always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
    begin
        tx <= 1;
        bit <= 0;
    end
    else
    begin
        case(staus)
            // init:
            // begin
            //     tx <= 1;
            //     bit <= bit;
            // end
            start:
            begin
                tx <= 0;
                bit <= 0;
            end
            write:
            begin
                tx <= data[bit];
                bit <= bit + 1;
            end
            stop:
            begin
                tx <= 1;
                bit <= 0;
            end
            default:
            begin
                tx <= tx;
                bit <= bit;
            end
        endcase
    end
end

endmodule

testbench:

`timescale  1ns / 1ns

module tb_uart;

// usat Parameters
parameter PERIOD  = 10;


// uart Inputs
reg   clk                                  = 0 ;
reg   rst_n                                = 0 ;
reg   [7:0]  data                          = 0 ;

wire ok;
reg fork_flag;

// uart Outputs
wire  tx                                   ;
wire  [3:0]  bit                           ;


initial
begin
    clk = 0;
    forever #(PERIOD/2)  clk=~clk;
end

initial
begin
    rst_n = 0;
    #(PERIOD*2) rst_n  =  1;
end

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
    begin
        data <= 8'hFF;
        fork_flag <= 1;
    end
    else if(ok)
    begin
        data <= data - 1;
        fork_flag <= 1;
    end
    else
    begin
        fork_flag <= 0;
        data <= data;
    end
end

uart  u_uart (
    .clk                     ( clk          ),
    .rst_n                   ( rst_n        ),
    .data                    ( data   [7:0] ),
    .ok                      (  ok       ) ,
    .fork_flag (1),
    .tx                      ( tx           ),
    .bit                     ( bit    [3:0] )
);

// initial
// begin

//     $finish;
// end

endmodule

在这里插入图片描述
ff的数据从发送到停止位:
在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值