原创 串口verilog程序

2010-12-24 11:26 3651 8 8 分类: FPGA/CPLD

发一个自己写的串口程序,波特率115200,一位起始位,8个数据位,一个停止位


接收采用8倍过采样。


下面有4个module,uart是顶层模块,uart_rx是接收模块,uart_tx是发送模块,uart_tx_controller是控制模块。


程序结果是:接收到上位机发过来的字符后,返回“Received data:”+接收到的字符


如接收到“A”,则返回“Received data:A”


用的是器件是EP1C6Q240C8,50M晶振


/*******************************************************************
*Project Name  :uart
*Module  Name :uart
*Target Device :EP1C6Q240C8
*Clkin   :50M
*Desisgner  :kang
*Date    :2010-12-03
*Version   :1.00
*Descriprion :uart
*Additional Comments :baud rate default is 115200bps
*******************************************************************/
module uart(
//input signals
input   clk,
input   rst,
input   rs232_rx,
//input [7:0] dat_tx,
//output signals
//output [7:0] dat_rx,
output  rs232_tx
    );


wire ack_receive;   
wire [7:0] dat_rx;    
//uart_tx_controller    
uart_tx_controller U1_uart_tx(
       //input signals
       .clk(clk),
       .rst(rst),
       .ack_receive(ack_receive),
       .dat_receive(dat_rx),
       //output signals
        .rs232_tx(rs232_tx) 
         );    
    
//uart_rx
uart_rx U2_uart_rx(
     //input signals
     .clk(clk),
     .rst(rst),
     .rs232_rx(rs232_rx),
     //output signals
     .dat_receive(dat_rx),
     .ack_receive(ack_receive)
     );
    
endmodule


/*******************************************************************
*Project Name  :uart
*Module  Name :uart_rx
*Target Device :EP1C6Q240C8
*Clkin   :50M
*Desisgner  :kang
*Date    :2010-12-02
*Version   :1.00
*Descriprion :uart receive
*Additional Comments :baud rate default is 115200bps
*******************************************************************/
module uart_rx(
//input signals
input    clk,
input    rst,
input    rs232_rx,
//output signals
output [7:0]   dat_receive,
output    ack_receive
     );


parameter BAUD_115200_NUM=11'd434; //434=(50M)/115200
parameter BAUD_8SAMP_NUM=6'd54;


//transmit machine
parameter IDLE=2'd0,   //default
    RECEIVE=2'd1,
    END=2'd2;
wire downedge_rs232_rx;
reg [1:0] rx_state;
/**********************************************************************
*baud rate produce
*this block produce the clk of baud rate
*counter_baud is to divide the frequency by BAUD_115200_NUM
**********************************************************************/


//counter_baud
reg [10:0] counter_baud;
always @(posedge clk or negedge rst)
 begin
 if(!rst) counter_baud<=0;
 else if(counter_baud>=BAUD_115200_NUM) counter_baud<=0;
 else if(downedge_rs232_rx&&(rx_state==IDLE)) counter_baud<=0;
 else counter_baud<=counter_baud+1'b1;
 end


//clk_baud
reg clk_baud;
always @(posedge clk or negedge rst)
 begin
 if(!rst) clk_baud<=0;
 else if(counter_baud>=BAUD_115200_NUM) clk_baud<=1'b1;
 else clk_baud<=1'b0;
 end
/**********************************************************************
*baud rate 8 sample
*this block produce the clk of baud rate 8 sample
*counter_baud is to divide the frequency by BAUD_8SAMP_NUM
**********************************************************************/
reg [5:0] counter_sampclk;
always @(posedge clk or negedge rst)
 begin
 if(!rst) counter_sampclk<=0;
 else if(clk_baud) counter_sampclk<=0;
 else if(counter_sampclk==BAUD_8SAMP_NUM) counter_sampclk<=0;
 else counter_sampclk<=counter_sampclk+1'b1;
 end


//clk_samp
reg clk_samp;
always @(posedge clk or negedge rst)
 begin
 if(!rst) clk_samp<=0;
 else if(counter_sampclk==BAUD_8SAMP_NUM) clk_samp<=1'b1;
 else clk_samp<=1'b0;
 end


/***********************************************************************
*check the downedge of rs232_rx
*when the downedge appears, the receive state machine begins to work
***********************************************************************/
reg [1:0] save_rs232_rx;
always @(posedge clk or negedge rst)
 begin
 if(!rst) save_rs232_rx<=0;
 else save_rs232_rx<={save_rs232_rx[0],rs232_rx};
 end
assign downedge_rs232_rx=(save_rs232_rx==2'b10);
 
/***********************************************************************
*receive state machine
*in this block, we use oversampling
*take 8 samples and check the data,
*if fours and more are same,we make it the right data
***********************************************************************/     
reg [7:0] dat_rx;


reg [3:0] rx_counter;
reg [3:0] counter_receiveh;
reg [3:0] counter_receivel;
always @(posedge clk or negedge rst)
 begin
 if(!rst)
  begin
  rx_state<=0;
  rx_counter<=0;
  dat_rx<=0;
  counter_receiveh<=0;
  counter_receivel<=0;
  end
 else
  begin
  case(rx_state)
  IDLE:
   begin
   if(downedge_rs232_rx)
    begin
    rx_state<=RECEIVE;
    rx_counter<=0;
    dat_rx<=0;
    counter_receiveh<=0;
    counter_receivel<=0;
    end
   else rx_state<=IDLE;
   end
  RECEIVE:
   begin
   if(rx_counter>4'd9) rx_state<=END;
   if(clk_baud) rx_counter<=rx_counter+1'b1;
   if((rx_counter>=4'd1)&&(rx_counter<=4'd8))
    begin
    if(clk_baud)
     begin
     counter_receiveh<=0;
     counter_receivel<=0;
     if(counter_receiveh>counter_receivel) dat_rx<={1'b1,dat_rx[7:1]};
     else if(counter_receiveh<counter_receivel) dat_rx<={1'b0,dat_rx[7:1]};
     end
    else if(clk_samp)
     begin
     if(rs232_rx) counter_receiveh<=counter_receiveh+1'b1;
     else counter_receivel<=counter_receivel+1'b1;
     end
    end
   end
  END:rx_state<=IDLE;
  default:rx_state<=IDLE;
  endcase
  end
 end


/***********************************************************************
*dat_receive
***********************************************************************/ 
assign dat_receive=(rx_state==END)?dat_rx:dat_receive;


/***********************************************************************
*ack_receive
***********************************************************************/
assign ack_receive=(rx_state==END);


endmodule


 


/*******************************************************************
*Project Name  :uart_tx_controller
*Module  Name :uart_tx_controller
*Target Device :EP1C6Q240C8
*Clkin   :50M
*Desisgner  :kang
*Date    :2010-12-02
*Version   :1.00
*Descriprion :uart transmit controller
*Additional Comments :auto transmit every 1s, no care about ack_tx
*******************************************************************/
module uart_tx_controller(
//input signals
input        clk,
input        rst,
input        ack_receive,
input   [7:0]    dat_receive,
//output signals
output        rs232_tx 
         );



/********************************************************************
*req_tx
********************************************************************/
wire ack_tx;
reg req_tx; 
reg [4:0] tx_num;  //transmit data's counter
always @(posedge clk or negedge rst)
 begin
 if(!rst) req_tx<=0;
 else if(ack_receive) req_tx<=1'b1;
 else if(ack_tx&&(tx_num<5'd15)) req_tx<=1'b1;
 else req_tx<=1'b0;
 end
//tx_num
always @(posedge clk or negedge rst)
 begin
 if(!rst) tx_num<=0;
 else if(ack_receive) tx_num<=0;
 else if(ack_tx) tx_num<=tx_num+1'b1;
 end
 
/*******************************************************************
*dat_tx
********************************************************************/
reg [7:0] dat_tx;
always @(posedge clk or negedge rst)
  begin
    if(!rst) dat_tx<=0;
    else
  begin
  if(tx_num==5'd0) dat_tx<=8'h52;         //R
  else if(tx_num==5'd1) dat_tx<=8'h65;       //e
  else if(tx_num==5'd2) dat_tx<=8'h63;       //c
  else if(tx_num==5'd3) dat_tx<=8'h65;       //e
  else if(tx_num==5'd4) dat_tx<=8'h69;       //i
  else if(tx_num==5'd5) dat_tx<=8'h76;       //v
  else if(tx_num==5'd6) dat_tx<=8'h65;       //e
  else if(tx_num==5'd7) dat_tx<=8'h64;       //d
  else if(tx_num==5'd8) dat_tx<=8'h20;       //
  else if(tx_num==5'd9) dat_tx<=8'h64;       //d
  else if(tx_num==5'd10) dat_tx<=8'h61;       //a
  else if(tx_num==5'd11) dat_tx<=8'h54;       //t
  else if(tx_num==5'd12) dat_tx<=8'h61;       //a
  else if(tx_num==5'd13) dat_tx<=8'h3a;       //:
  else if(tx_num==5'd14) dat_tx<=dat_receive;     //dat_rx
  else if(tx_num==5'd15) dat_tx<=8'h0a;       //\n   
  end
  end


 //uart_tx
 uart_tx U1_uart_tx(
     //input signals
     .clk(clk),
     .rst(rst),
     .dat_tx(dat_tx),
     .req_tx(req_tx),
     //output signals
     .ack_tx(ack_tx),
         .rs232_tx(rs232_tx)
     );
 
endmodule
 


 


/*******************************************************************
*Project Name  :uart_tx
*Module  Name :uart_tx
*Target Device :EP1C6Q240C8
*Clkin   :50M
*Desisgner  :kang
*Date    :2010-12-02
*Version   :1.00
*Descriprion :uart transmit
*Additional Comments :baud rate default is 115200bps
*******************************************************************/
module uart_tx(
//input signals
input     clk,
input     rst,
input  [7:0] dat_tx,
input     req_tx,
//output signals
output     ack_tx,
output     rs232_tx
     );


parameter BAUD_115200_NUM=11'd434; //434=(50M)/115200


//transmit machine
parameter IDLE=2'd0,   //default
    TRANSMIT=2'd1,
    WAIT=2'd3,
    END=2'd2;


/**********************************************************************
*baud rate produce
*this block produce the clk of baud rate
*counter_baud is to divide the frequency by BAUD_115200_NUM
**********************************************************************/


//counter_baud
reg [10:0] counter_baud;
always @(posedge clk or negedge rst)
 begin
 if(!rst) counter_baud<=0;
 else if(counter_baud>=BAUD_115200_NUM) counter_baud<=0;
 else counter_baud<=counter_baud+1'b1;
 end


//clk_baud
reg clk_baud;
always @(posedge clk or negedge rst)
 begin
 if(!rst) clk_baud<=0;
 else if(counter_baud>=BAUD_115200_NUM) clk_baud<=1'b1;
 else clk_baud<=1'b0;
 end


/**********************************************************************
*transmit machine
*in the normal time, this state machine is in the idle mode
*when tx_req is vilid,the get into transmit mode
**********************************************************************/
//check the upedge of req_tx
reg [1:0] save_req_tx;
wire upedge_req_tx;
always @(posedge clk or negedge rst)
 begin
 if(!rst) save_req_tx<=0;
 else save_req_tx<={save_req_tx[0],req_tx};
 end
assign upedge_req_tx=(save_req_tx==2'b10); 


//data_transmit
reg [7:0] data_transmit;
always @(posedge clk or negedge rst)
 begin
 if(!rst) data_transmit<=0;
 else if(upedge_req_tx) data_transmit<=dat_tx;
 end


reg [1:0] tx_state;
reg [4:0] tx_counter;
reg rs232_tx_r;
always @(posedge clk or negedge rst)
 begin
 if(!rst)
  begin
  tx_state<=IDLE;
  tx_counter<=0;
  rs232_tx_r<=1'b1;
  end
 else
  begin
  case(tx_state)
  IDLE:
   begin
   rs232_tx_r<=1'b1;
   if(req_tx)
    begin
    tx_state<=TRANSMIT;
    tx_counter<=0;
    end
   else tx_state<=IDLE;
   end
  TRANSMIT:
   if(clk_baud)
   begin
   tx_counter<=tx_counter+1'b1;
   if(tx_counter>5'd9)
    begin
    tx_state<=WAIT;
    tx_counter<=0;
    end
   else if(tx_counter==5'd0) rs232_tx_r<=1'b0;
   else if(tx_counter==5'd9) rs232_tx_r<=1'b1;
   else rs232_tx_r<=data_transmit[tx_counter-1'b1];
   end
  WAIT:
   begin
   if(tx_counter==5'd4)
    begin
    tx_state<=END;
    tx_counter<=0;
    end
   else if(clk_baud) tx_counter<=tx_counter+1'b1;
   end
  END:tx_state<=IDLE;
  default:tx_state<=IDLE;
  endcase
  end
 end
 
//rs232_tx
assign rs232_tx=rs232_tx_r;
//ack_tx
assign ack_tx=(tx_state==END);


endmodule

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
8
关闭 站长推荐上一条 /3 下一条