发一个自己写的串口程序,波特率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;
endreg [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
文章评论(0条评论)
登录后参与讨论