uart收发实现

1.不使用状态机

         在UART接收时,采集一帧数据的中间8位有效位,忽略开始位与停止位;在UART发送时,将发送的并行8位数据转为串行数据,并添加开始位与停止位。
        UART中的一帧数据为10位,空闲时均为高电平,在检测到开始位(低电平)之后,开始采集8位有效数据位(低位在前),再将停止位置为高电平即可。

代码如下:

1 /*波特率计数*/
2 module bsp_gen(
3 input wire sclk,
4 input wire rst_n,
5 input wire en,
6 output reg tr_data, //中点标志
7 output reg [3:0] num //发送接受的计数位数
8 );
9
10 parameter DIV_CNT = 13'd5207;//50Mhz/9600
11 reg [12:0] cnt;
12 reg flag;
13 //数据中心点进行采样
14 always @(negedge rst_n or posedge sclk) begin
15 if (!rst_n)
16 tr_data <= 1'b0;
17 else if(cnt == (DIV_CNT‐1)/2)
18 tr_data <= 1'b1;
19 else
20 tr_data <= 1'b0;
21 end // always
22
23 always @(negedge rst_n or posedge sclk) begin
24 if (!rst_n)
25 cnt <= 13'd0;
26 else if(flag == 1'b1 && cnt < DIV_CNT)
27 cnt <= cnt + 1'b1;
28 else
29 cnt <= 13'd0;
30 end // always
31
32 always @(negedge rst_n or posedge sclk) begin
33 if (!rst_n)
34 flag <= 1'b0;
35 else if(en)
36 flag <= 1'b1;
37 else if(num == 4'd10)
38 flag <= 1'b0;
39 else
40 flag <= flag;
41 end // always
42
43 always @(negedge rst_n or posedge sclk) begin
44 if (!rst_n)
45 num <= 4'd0;
46 else if(num == 4'd10)
47 num <= 4'd0;
48 else if(flag == 1'b1 && tr_data == 1'b1)
49 num <= num +1'b1;
50 else
51 num <= num;
52 end // always
53
54 endmodule
1 /*串口接收*/
2 module uart_rx(
3 input wire sclk,
4 input wire rst_n,
5 input wire tr_data,
6 input wire [3:0] num,
7 input wire rx_232,//RS232传入串口的数据
8 output wire rx_en,//使能启动接收波特率计数
9 output reg tx_en,//使能接收数据之后,开始启动发送数据模块
10 output reg [7:0] rx_data
11 );
12
13 //检测高电平转为低电平(开始位)
14 reg data_in_1,data_in_2;
15 reg [7:0] rx_data_r;
16 always @(negedge rst_n or posedge sclk) begin
17 if (!rst_n)
18 begin
19 data_in_1 <= 1'b1;
20 data_in_2 <= 1'b1;
21 end
22 else
23 begin
24 data_in_1 <= rx_232;
25 data_in_2 <= data_in_1;
26 end // else
27 end // always
28 assign rx_en = data_in_2 & (~data_in_1);//data_in的上一个时刻为高,当前时
刻为低
29
30 //串转并 (寄存器缓存数据,然后在最后发送出去)
31 always @(negedge rst_n or posedge sclk) begin
32 if (!rst_n)
33 begin
34 rx_data_r <= 'd0;
35 rx_data <= 'd0;
36 end
37 else if(tr_data == 1'b1)
38 case(num)
39 4'd0:;
40 4'd1:rx_data_r[0] <= rx_232;
41 4'd2:rx_data_r[1] <= rx_232;
42 4'd3:rx_data_r[2] <= rx_232;
43 4'd4:rx_data_r[3] <= rx_232;
44 4'd5:rx_data_r[4] <= rx_232;
45 4'd6:rx_data_r[5] <= rx_232;
46 4'd7:rx_data_r[6] <= rx_232;
47 4'd8:rx_data_r[7] <= rx_232;
48 4'd9:rx_data <= rx_data_r;
49 default:;
50 endcase
51 else
52 begin
53 rx_data_r <= rx_data_r;
54 rx_data <= rx_data;
55 end //
56
57 end // always
58
59 always @(negedge rst_n or posedge sclk) begin
60 if (!rst_n)
61 tx_en <= 1'b0;
62 else if (num == 4'd10)
63 tx_en <= 1'b1;
64 else
65 tx_en <= 1'b0;
66 end // always
67
68 endmodule



1 /*串口发送*/
2 module uart_tx(
3 input wire sclk,
4 input wire rst_n,
5 input wire tr_data,
6 input wire [3:0] num,
7 input wire [7:0] rx_data,
8 output reg send_data //发送的数据
9 );
10 //并转串
11 always @(negedge rst_n or posedge sclk) begin
12 if (!rst_n)
13 send_data <= 1'b1;
14 else if(tr_data == 1'b1)//中心点
15 case (num)
16 4'd0:begin send_data <= 1'b0; end
17 4'd1:begin send_data <= rx_data[0]; end
18 4'd2:begin send_data <= rx_data[1]; end
19 4'd3:begin send_data <= rx_data[2]; end
20 4'd4:begin send_data <= rx_data[3]; end
21 4'd5:begin send_data <= rx_data[4]; end
22 4'd6:begin send_data <= rx_data[5]; end
23 4'd7:begin send_data <= rx_data[6]; end
24 4'd8:begin send_data <= rx_data[7]; end
25 4'd9:begin send_data <= 1'b1; end
26 default: send_data <= 1'b1;
27 endcase
28 else
29 send_data <= send_data;
30 end // always
31
32 endmodule



1 module top(
2 input wire sclk,
3 input wire rst_n,
4 input wire rx_232,
5 output wire tx_232
6 );
7
8 wire [3:0] tx_num,rx_num;
9 wire tx_en,rx_en;
10 wire tr_tx,tr_rx;
11 wire [7:0] rx_data;
12
13 bsp_gen bsp_gen_tx(
14 .sclk (sclk),
15 .rst_n (rst_n),
16 .en (tx_en),
17 .tr_data (tr_tx), //中点标志
18 .num (tx_num) //发送接受的计数位数
19 );
20
21 uart_tx uart_tx_inst(
22 .sclk (sclk),
23 .rst_n (rst_n),
24 .tr_data (tr_tx),
25 .num (tx_num),
26 .rx_data (rx_data),
27 .send_data (tx_232) //发送的数据
28 );
29
30 bsp_gen bsp_gen_rx(
31 .sclk (sclk),
32 .rst_n (rst_n),
33 .en (rx_en),
34 .tr_data (tr_rx), //中点标志
35 .num (rx_num) //发送接受的计数位数
36 );
37
38 uart_rx uart_rx_inst(
39 .sclk (sclk),
40 .rst_n (rst_n),
41 .tr_data (tr_rx),
42 .num (rx_num),
43 .rx_232 (rx_232),//RS232传入串口的数据
44 .rx_en (rx_en),//使能启动接收波特率计数
45 .tx_en (tx_en),//使能接收数据之后,开始启动发送数据模块
46 .rx_data (rx_data)
47 );
48
49
50 endmodule



1 `timescale 1ns/1ns
2 module tb_uart();
3
4 reg sclk;
5 reg rst_n;
6 reg rx_232;
7 wire tx_232;
8
9 initial begin
10 sclk = 0;
11 rst_n = 0;
12 #100;
13 rst_n = 1;
14 end // initial
15
16 initial begin
17 rx_232 = 1;
18 get_data();
19 #1500000 $stop;
20 end // initial
21
22 always #10 sclk = ~sclk;
23
24 top top_inst(
25 .sclk (sclk),
26 .rst_n (rst_n),
27 .rx_232 (rx_232),
28 .tx_232 (tx_232)
29 );
30
31 task get_data();
32 begin
33 #200 rx_232 = 0;//开始位
34 #110000 rx_232 = 0;//MSB‐‐LSB(8'b0110_0100)
35 #110000 rx_232 = 1;
36 #110000 rx_232 = 1;
37 #110000 rx_232 = 0;
38 #110000 rx_232 = 0;
39 #110000 rx_232 = 1;
40 #110000 rx_232 = 0;
41 #110000 rx_232 = 0;
42 #110000 rx_232 = 1;//停止位
43 end //
44 endtask
45
46 endmodule


1 .main clear
2
3 vlib work
4
5 vlog ./tb_uart.v
6
7 vlog ./../design/*.v
8
9 vsim ‐voptargs=+acc work.tb_uart
10
11 add wave ‐divider {bsp_gen_tx}
12
13 add wave tb_uart/top_inst/bsp_gen_tx/*
14
15 add wave ‐divider {uart_rx_inst}
16
17 add wave tb_uart/top_inst/uart_rx_inst/*
18
19 add wave ‐divider {bsp_gen_rx}
20
21 add wave tb_uart/top_inst/bsp_gen_rx/*
22
23 add wave ‐divider {uart_tx_inst}
24
25 add wave tb_uart/top_inst/uart_tx_inst/*
26
27 run 10ms

 

你可能感兴趣的:(fpga)