原创 带FIFO的UART TX & baud_gen

2012-11-12 18:00 1592 11 11 分类: FPGA/CPLD

module uart_tx(
     clk,
     rst,
     data_in,
     en,
     txd,
     txd_busy
     );

  input      clk;
  input      rst;
  input[7:0] data_in;
  input     en;
 
  output txd;
  reg    txd;

  output txd_busy;
  reg    txd_busy;
 
  reg[7:0] data_buff;
 
  parameter[3:0]IDLE =4'b0000,
              START=4'b0001,
                S0   =4'b0011,
                S1   =4'b0111,
                S2   =4'b0110,
                S3   =4'b0100,
                S4   =4'b1100,
                S5   =4'b1010,
                S6   =4'b1110,
              STOP =4'b1111;
 
  reg[3:0] state;
  always@(posedge clk)
  if(rst)
    state<=IDLE;
  else
    case(state)
      IDLE:
          begin
           if(en)
            begin
            data_buff<=data_in;
            txd<=1'b0;
            txd_busy<=1'b1;
            state<=START;
            end
           else
            begin
            txd<=1'b1;
            txd_busy<=1'b0;
            state<=IDLE;
            end
          end
      START:
          begin
          txd<=data_buff[0];
          state<=S0;
          end
      S0:
          begin
          txd<=data_buff[1];
          state<=S1;
          end
      S1:
          begin
          txd<=data_buff[2];
          state<=S2;
          end
      S2:
          begin
          txd<=data_buff[3];
          state<=S3;
          end
      S3:
          begin
          txd<=data_buff[4];
          state<=S4;
          end
      S4:
          begin
          txd<=data_buff[5];
          state<=S5;
          end
      S5:
          begin
          txd<=data_buff[6];
          state<=S6;
          end
      S6:
          begin
          txd<=data_buff[7];
          state<=STOP;
          end
      STOP:
          begin
          txd<=1'b1;
          txd_busy<=1'b0;
          state<=IDLE;
          end
    endcase

endmodule

 

 

module baud_gen(
                clk,
                rst,
               
                baud_sel,
               
                tx_clk,
                rx_clk
                );
  parameter TX_BAUD_9600   = 13'd5208,//50MHz/9600;              
            TX_BAUD_19200  = 13'd2604,//50MHz/19200;
            TX_BAUD_115200 = 13'd433; //50MHz/115200;
           
  parameter TX_BAUD_9600_HALF   = 13'd2604,//50MHz/9600;               
            TX_BAUD_19200_HALF  = 13'd1302,//50MHz/19200;
            TX_BAUD_115200_HALF = 13'd4206; //50MHz/115200;

  parameter RX_BAUD_9600   = 13'd325,//50MHz/9600;         
            RX_BAUD_19200  = 13'd163,//50MHz/19200;       
            RX_BAUD_115200 = 13'd27; //50MHz/115200;
                
  parameter RX_BAUD_9600_HALF   = 13'd163,//50MHz/9600;   
            RX_BAUD_19200_HALF  = 13'd82,//50MHz/19200;  
            RX_BAUD_115200_HALF = 13'd13; //50MHz/115200;

           
  input clk;
  input rst;
  input [1:0] baud_sel;
 
  output tx_clk;
  output rx_clk;
 
  reg    tx_clk;
  reg    rx_clk; 
  //------------------------------------------------------TX CLK 
  reg [12:0] cont1;
  reg [12:0] duty1;
  always @(posedge clk)
  begin
    if(rst)
      begin
        cont1 <= 13'd0;
        duty1 <= 13'd0;
      end
    else
      case(baud_sel)
      2'd0:begin
        cont1 <= TX_BAUD_9600;
        duty1 <= TX_BAUD_9600_HALF;
      end
      2'd1:begin
        cont1 <= TX_BAUD_19200;
        duty1 <= TX_BAUD_19200_HALF;
      end
      2'd2:begin
        cont1 <= TX_BAUD_115200;
        duty1 <= TX_BAUD_115200_HALF;
      end
      default:begin
        cont1 <= TX_BAUD_9600;
        duty1 <= TX_BAUD_9600_HALF;
      end
      endcase
  end
 
  reg [12:0] cnt1;
  always @(posedge clk)
  begin
    if(rst)
      cnt1 <= 13'd0;
    else if(cnt1 == cont1-1)
      cnt1 <= 13'd0;
    else
      cnt1 <= cnt1 + 1'b1;
  end
 
  always @(posedge clk)
  begin
    if(rst)
      tx_clk <= 1'b0;
    else if (cnt1 <duty1)
      tx_clk <= 1'b1;
    else
      tx_clk <= 1'b0;
  end
             
  //------------------------------------------------------RX CLK 
  reg [8:0] cont2;
  reg [8:0] duty2;
  always @(posedge clk)
  begin
    if(rst)
      begin
        cont2 <= 9'd0;
        duty2 <= 9'd0;
      end
    else
      case(baud_sel)
      2'd0:begin
        cont2 <= RX_BAUD_9600;
        duty2 <= RX_BAUD_9600_HALF;
      end
      2'd1:begin
        cont2 <= RX_BAUD_19200;
        duty2 <= RX_BAUD_19200_HALF;
      end
      2'd2:begin
        cont2 <= RX_BAUD_115200;
        duty2 <= RX_BAUD_115200_HALF;
      end
      default:begin
        cont2 <= RX_BAUD_9600;
        duty2 <= RX_BAUD_9600_HALF;
      end
      endcase
  end
 
  reg [8:0] cnt2;
  always @(posedge clk)
  begin
    if(rst)
      cnt2 <= 9'd0;
    else if(cnt2 == cont2-1)
      cnt2 <= 9'd0;
    else
      cnt2 <= cnt2 + 1'b1;
  end
 
  always @(posedge clk)
  begin
    if(rst)
      rx_clk <= 1'b0;
    else if (cnt2 <duty2)
      rx_clk <= 1'b1;
    else
      rx_clk <= 1'b0;
  end
endmodule

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
11
关闭 站长推荐上一条 /1 下一条