2010-12-10

[ZT][UART]FPGA串口小程序

作者见注释

`timescale 1ns/1ns

module UART(rst_n,clk50M,txd);
input  rst_n,clk50M;
output txd;


reg    txd_start;
reg    [7:0] txd_data;
wire   txd_busy;
async_transmitter async_transmitter(
                    .rst_n(rst_n),
                    .clk(clk50M),
                    .txd_start(txd_start),
                    .txd_data(txd_data),
                    .txd_busy(txd_busy),
                    .txd(txd)
);

always@(negedge rst_n,posedge clk50M)
  begin
    if(!rst_n)
      begin
        txd_data<=8'h0;
        txd_start<=1'b0;
      end
    else
      if((txd_busy==1'b0) &&(txd_start==1'b0))
        begin
          txd_start<=1'b1;
          txd_data<=txd_data+8'h1;
        end
      else
        txd_start<=1'b0;
  end

endmodule


/*
作者:小鱼有水
本设计只限于学习,欢迎大家拍砖
*/
`timescale 1ns/1ns

module async_transmitter(rst_n,clk,txd_start,txd_data,txd_busy,txd);
input  rst_n,clk;
input  txd_start;
input  [7:0] txd_data;
output txd_busy;
output txd;

//时钟分频系数,本设计波特率选取的是19200,数据位为8位,停止位为1位
parameter clk_prescaler1 = 162;
parameter clk_prescaler2 = 15;
reg    [7:0] cnt1;
reg    [3:0] cnt2;
reg    flag1,flag2;
reg    txd_busy;
reg    txd;

parameter idle = 2'b00;        //空闲
parameter send_start = 2'b01;  //发送起始位
parameter send_byte = 2'b10;   //发送数据字节
parameter send_stop = 2'b11;   //发送停止位
reg    [1:0] cur_state;

reg    [7:0] shift_reg;        //移位寄存器,存储要发送的数据
reg    [2:0] shift_cnt;        //发送计数器,表明当前要发送一个字节的哪一位

//产生串口发送时钟
always@(negedge rst_n,posedge clk)
  begin
    if(!rst_n)
      begin
        cnt1<=8'd0;
        flag1<=1'b0;
      end
    else
      begin
        if(cnt1==clk_prescaler1)
          begin
            cnt1<=8'd0;
            flag1<=1'b1;
          end
        else
          begin
            cnt1<=cnt1+8'd1;
            flag1<=1'b0;
          end
      end
  end

always@(negedge rst_n,posedge clk)
  begin
    if(!rst_n)
      begin
        cnt2<=4'd0;
        flag2<=1'b0;
      end
    else
      begin
        if(flag1==1'b1)
          begin
            if(cnt2==clk_prescaler2)
              begin
                cnt2<=4'd0;
                flag2<=1'b1;
              end
            else
              begin
                cnt2<=cnt2+4'd1;
              end
          end
        else
          flag2<=1'b0;
      end
  end

//发送数据
always@(negedge rst_n,posedge clk)
  begin
    if(!rst_n)
      begin
        txd<=1'b1;
        cur_state<=idle;
        shift_cnt<=3'd0;
        txd_busy<=1'b0;
      end
    else
      begin
        if(flag2==1'b1)
          begin
            case(cur_state)
              idle:
                begin
                  txd<=1'b1;
                  txd_busy<=1'b0;
                end
              send_start:
                begin
                  txd<=1'b0;
                  cur_state<=send_byte;
                end
              send_byte:
                begin
                  txd<=shift_reg[shift_cnt];
                  if(shift_cnt==3'h7)
                    begin
                      shift_cnt<=3'h0;
                      cur_state<=send_stop;
                    end
                  else
                    begin
                      shift_cnt<=shift_cnt+3'h1;
                    end
                end
              send_stop:
                begin
                  txd<=1'd1;
                  cur_state<=idle;
                end
              default:
                begin
                  cur_state<=idle;
                  txd<=1'd1;
                  txd_busy<=1'b0;
                end
            endcase
          end

        if(txd_start==1'b1)
          begin
            shift_reg<=txd_data;
            cur_state<=send_start;
            txd_busy<=1'b1;
          end
      end
  end

endmodule

本文地址:http://114er.blogspot.com/2010/12/ztuartfpga.html
原创文章如转载,请注明链接: 转自Welcome Funny Guys

0 评论: