- module uart_rx
- #(
- parameter UART_BPS = 'd9600 ,
- CLK_FREQ = 'd50_000_000
- )(
- input wire sys_clk ,
- input wire sys_rst_n ,
- input wire rx ,
-
- output reg [7:0] po_data ,
- output reg po_flag
- );
-
- parameter BAUD_CNT_MAX = CLK_FREQ / UART_BPS ;
- // reg define signal
- reg rx_reg1 ;
- reg rx_reg2 ;
- reg rx_reg3 ;
- reg start ;
- reg work_en ;
- reg [12:00] baud_cnt ;
- reg bit_flag ;
- reg [ 3: 0] bit_cnt ;
- reg [ 7: 0] rx_data ;
- reg rx_flag ;
-
- // rx_reg1 ;rx_reg2 ;rx_reg3 ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n) begin
- rx_reg1 <= 1'b1 ;
- rx_reg2 <= 1'b1 ;
- rx_reg3 <= 1'b1 ;
- end else begin
- rx_reg1 <= rx ;
- rx_reg2 <= rx_reg1 ;
- rx_reg3 <= rx_reg2 ;
- end
- end
- // start ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n) begin
- start <= 1'b0 ;
- end else begin
- if(rx_reg3 == 1'b1 && rx_reg2 == 1'b0 && bit_cnt == 4'd0) begin // 或者bit_cnt换成 work_en == 0
- start <= 1'b1 ;
- end else begin
- start <= 1'b0 ;
- end
- end
- end
- // work_en ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n) begin
- work_en <= 1'b0 ;
- end else begin
- if(start == 1'b1) begin
- work_en <= 1'b1 ;
- end else begin
- if((bit_cnt == 4'd8) && (bit_flag == 1'b1)) begin
- work_en <= 1'b0 ;
- end else begin
- work_en <= work_en ;
- end
- end
- end
- end
- // [12:00] baud_cnt ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n) begin
- baud_cnt <= 13'd0 ;
- end else begin
- if(work_en == 1'b1 && baud_cnt == BAUD_CNT_MAX - 1'b1) begin
- baud_cnt <= 13'd0 ;
- end else begin
- if(work_en == 1'b1) begin
- baud_cnt <= baud_cnt + 1'b1 ;
- end else begin
- baud_cnt <= 13'd0 ;
- end
- end
- end
- end
- // always @(posedge sys_clk or negedge sys_rst_n) begin
- // if(~sys_rst_n) begin
- // baud_cnt <= 13'd0 ;
- // end else begin
- // if(work_en == 1'b1 && baud_cnt == BAUD_CNT_MAX - 1'b1 || work_en == 1'b0) begin
- // baud_cnt <= 13'd0 ;
- // end else begin
- // baud_cnt <= baud_cnt + 1'b1 ;
- // end
- // end
- // end
- // bit_flag ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n) begin
- bit_flag <= 1'b0 ;
- end else begin
- if(baud_cnt == BAUD_CNT_MAX - 1'b1) begin // 也可以写成baud_cnt == BAUD_CNT_MAX / 2 - 1'b1
- bit_flag <= 1'b1 ; // 这样后面赋值时,就可以直接用bit_flag .
- end else begin
- bit_flag <= 1'b0 ;
- end
- end
- end
- // [ 2: 0] bit_cnt ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n) begin
- bit_cnt <= 4'd0 ;
- end else begin
- if(bit_flag == 1'b1 && work_en == 1'b1 && bit_cnt == 4'd8) begin
- bit_cnt <= 4'd0 ;
- end else begin
- if(bit_flag == 1'b1 && work_en == 1'b1) begin
- bit_cnt <= bit_cnt + 1'b1 ;
- end else begin
- if(work_en == 1'b1) begin
- bit_cnt <= bit_cnt ;
- end else begin
- bit_cnt <= 3'd0 ;
- end
- end
- end
- end
- end
- // [7:0] rx_data ,
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n) begin
- rx_data <= 8'd0 ;
- end else begin
- if(bit_cnt >= 4'd1 && bit_cnt <= 4'd8 && baud_cnt == 13'd3000) begin
- rx_data <= {rx_reg3, rx_data[7:1]} ;
- end else begin
- rx_data <= rx_data ;
- end
- end
- end
- // rx_flag
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n) begin
- rx_flag <= 1'b0 ;
- end else begin
- if(bit_cnt == 4'd8 && bit_flag == 1'b1) begin
- rx_flag <= 1'b1 ;
- end else begin
- rx_flag <= 1'b0 ;
- end
- end
- end
- // output signal
- // po_flag
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n) begin
- po_flag <= 1'b0 ;
- end else begin
- if(rx_flag == 1'b1) begin
- po_flag <= 1'b1 ;
- end else begin
- po_flag <= 1'b0 ;
- end
- end
- end
- // po_data
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n) begin
- po_data <= 8'd0 ;
- end else begin
- if(rx_flag == 1'b1) begin
- po_data <= rx_data ;
- end else begin
- po_data <= 8'd0 ;
- end
- end
- end
- endmodule
- module uart_tx (
- input wire sys_clk ,
- input wire sys_rst_n ,
- input wire [7:0] pi_data ,
- input wire pi_flag ,
-
- output reg tx
- );
-
- // reg signal define
- reg pi_flag_r ;
- reg [7:0] pi_data_r ;
- reg work_en ;
- reg [12:00] baud_cnt ;
- reg bit_flag ;
- reg [ 3: 0] bit_cnt ;
- // pi_flag_r ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n) begin
- pi_flag_r <= 1'b0 ;
- end else begin
- if(pi_flag == 1'b1) begin
- pi_flag_r <= 1'b1 ;
- end else begin
- pi_flag_r <= 1'b0 ;
- end
- end
- end
- // [7:0] pi_data_r ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n) begin
- pi_data_r <= 1'b0 ;
- end else begin
- if(pi_flag == 1'b1) begin
- pi_data_r <= pi_data ;
- end else begin
- pi_data_r <= pi_data_r ;
- end
- end
- end
- // work_en ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n) begin
- work_en <= 1'b0 ;
- end else begin
- if(baud_cnt == 13'd5027 && bit_cnt == 4'd9) begin
- work_en <= 1'b0 ;
- end else begin
- if(pi_flag_r == 1'b1) begin
- work_en <= 1'b1 ;
- end else begin
- work_en <= work_en ;
- end
- end
- end
- end
- // [12:00] baud_cnt ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n) begin
- baud_cnt <= 13'd0 ;
- end else begin
- if(work_en == 1'b1 && baud_cnt == 13'd5027 || work_en == 1'b0) begin
- baud_cnt <= 13'd0 ;
- end else begin
- if(work_en == 1'b1) begin
- baud_cnt <= baud_cnt + 1'b1 ;
- end else begin
- baud_cnt <= 13'd0 ;
- end
- end
- end
- end
- // bit_flag ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n) begin
- bit_flag <= 1'b0 ;
- end else begin
- if(baud_cnt == 13'd5026) begin // 野火上是等于 1 .
- bit_flag <= 1'b1 ;
- end else begin
- bit_flag <= 1'b0 ;
- end
- end
- end
- // [ 3: 0] bit_cnt ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n) begin
- bit_cnt <= 4'd0 ;
- end else begin
- if(bit_flag == 1'b1 && bit_cnt == 4'd9 || work_en == 1'b0) begin
- bit_cnt <= 4'd0 ;
- end else begin
- if(bit_flag == 1'b1) begin
- bit_cnt <= bit_cnt + 1'b1 ;
- end else begin
- bit_cnt <= bit_cnt ;
- end
- end
- end
- end
- // output signal
- // tx
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n) begin
- tx <= 1'b1 ;
- end else begin
- if(work_en == 1'b1 && bit_cnt == 4'd0) begin
- tx <= 1'b0 ;
- end else begin
- if(work_en == 1'b1 && bit_cnt == 4'd9 || work_en == 1'b0) begin
- tx <= 1'b1 ;
- end else begin
- tx <= pi_data_r[bit_cnt - 1'b1] ;
- end
- end
- end
- end
- endmodule
- module top_uart(
- input wire sys_clk ,
- input wire sys_rst_n ,
- input wire rx ,
-
- output wire tx
- );
-
- // 模块间连线
- wire [7:0] po_data ;
- wire po_flag ;
-
- uart_rx uart_rx_insert_top(
- .sys_clk ( sys_clk ) ,
- .sys_rst_n ( sys_rst_n ) ,
- .rx ( rx ) ,
-
- .po_data ( po_data ) ,
- .po_flag ( po_flag )
- );
-
- uart_tx uart_tx_insert_top(
- .sys_clk ( sys_clk ) ,
- .sys_rst_n ( sys_rst_n ) ,
- .pi_data ( po_data ) ,
- .pi_flag ( po_flag ) ,
-
- .tx ( tx )
- );
-
- endmodule
- `timescale 1ns/1ns
- module test_top();
- reg sys_clk ;
- reg sys_rst_n ;
- reg rx ;
-
- wire tx ;
-
-
- // Instantiation
- top_uart top_uart_insert(
- .sys_clk ( sys_clk ) ,
- .sys_rst_n ( sys_rst_n ) ,
- .rx ( rx ) ,
-
- .tx ( tx )
- );
- parameter CYCLE = 20 ;
-
- task rx_bit ;
-
- input [7:0] data ;
-
- integer i ;
- for (i = 0;i <= 9 ;i = i + 1 ) begin
- case (i)
- 0: rx <= 1'b0 ;
- 1: rx <= data[i - 1];
- 2: rx <= data[i - 1];
- 3: rx <= data[i - 1];
- 4: rx <= data[i - 1];
- 5: rx <= data[i - 1];
- 6: rx <= data[i - 1];
- 7: rx <= data[i - 1];
- 8: rx <= data[i - 1];
- 9: rx <= 1'b1 ;
- default: rx <= 1'b1 ;
- endcase
- #(CYCLE * 5207) ;
- end
- endtask
- initial begin
- sys_clk = 1'b1 ;
- sys_rst_n <= 1'b0 ;
- rx <= 1'b1 ;
- #( CYCLE * 10 ) ;
- sys_rst_n <= 1'b1 ;
- #( 210 ) ;
- sys_rst_n <= 1'b0 ;
- #( 10 ) ;
- #( CYCLE * 10 ) ;
- sys_rst_n <= 1'b1 ;
- #( CYCLE * 100 ) ;
- rx_bit(8'd1) ;
- rx_bit(8'd2) ;
- rx_bit(8'd3) ;
- rx_bit(8'd4) ;
- rx_bit(8'd5) ;
- rx_bit(8'd6) ;
- rx_bit(8'd7) ;
- rx_bit(8'd8) ;
- rx_bit(8'd9) ;
- rx_bit(8'd9) ;
- $stop ;
- end
- always #( CYCLE / 2 ) sys_clk = ~sys_clk ;
- // initial begin
- // $timeformat(-9,0,"ns",6) ;
- // /* (第一个位置)
- // -9 是10 的负9次方 表示纳秒
- // -3 表示毫秒
- // */
- // /* (第二个位置)
- // 0 表示,小数点后显示的位数
- // */
- // /* (第三个位置)
- // “打印字符” 与单位相对应
- // */
- // /* (第四个位置)
- // 6 表示 打印的最小数字字符 是6个
- // */
- // $monitor("@time %t:sel=%b,seg=%b,cnt_16=%b,sum_tb=%b",$time,sel,seg,cnt_16) ; // 监测函数
- // end
- endmodule
- `timescale 1ns/1ns
- module test_uart();
- reg sys_clk ;
- reg sys_rst_n ;
- reg rx ;
-
- wire [7:0] po_data ;
- wire po_flag ;
-
- wire tx ;
-
-
- // Instantiation
- uart_rx uart_rx_insert(
- .sys_clk ( sys_clk ) ,
- .sys_rst_n ( sys_rst_n ) ,
- .rx ( rx ) ,
-
- .po_data ( po_data ) ,
- .po_flag ( po_flag )
- );
- parameter CYCLE = 20 ;
-
- initial begin
- sys_clk = 1'b1 ;
- sys_rst_n <= 1'b0 ;
- rx <= 1'b1 ;
- #( CYCLE * 10 ) ;
- sys_rst_n <= 1'b1 ;
- #( 210 ) ;
- sys_rst_n <= 1'b0 ;
- #( 10 ) ;
- #( CYCLE * 10 ) ;
- sys_rst_n <= 1'b1 ;
- #( CYCLE * 100 ) ;
-
- rx <= 1'b0; // 起始位
- #( CYCLE * 5207 ) ;
- rx <= 1'b1; // 1
- #( CYCLE * 5207 ) ;
- rx <= 1'b0; // 2
- #( CYCLE * 5207 ) ;
- rx <= 1'b1; // 3
- #( CYCLE * 5207 ) ;
- rx <= 1'b0; // 4
- #( CYCLE * 5207 ) ;
- rx <= 1'b1; // 5
- #( CYCLE * 5207 ) ;
- rx <= 1'b0; // 6
- #( CYCLE * 5207 ) ;
- rx <= 1'b1; // 7
- #( CYCLE * 5207 ) ;
- rx <= 1'b0; // 8
- #( CYCLE * 5207 ) ;
- rx <= 1'b1; // 终止位
- #( CYCLE * 5207 ) ;
- $stop ;
- end
-
- always #( CYCLE / 2 ) sys_clk = ~sys_clk ;
-
- uart_tx uart_tx_insert(
- .sys_clk ( sys_clk ) ,
- .sys_rst_n ( sys_rst_n ) ,
- .pi_data ( po_data ) ,
- .pi_flag ( po_flag ) ,
-
- .tx ( tx )
- );
-
- // initial begin
- // $timeformat(-9,0,"ns",6) ;
- // /* (第一个位置)
- // -9 是10 的负9次方 表示纳秒
- // -3 表示毫秒
- // */
- // /* (第二个位置)
- // 0 表示,小数点后显示的位数
- // */
- // /* (第三个位置)
- // “打印字符” 与单位相对应
- // */
- // /* (第四个位置)
- // 6 表示 打印的最小数字字符 是6个
- // */
- // $monitor("@time %t:sel=%b,seg=%b,cnt_16=%b,sum_tb=%b",$time,sel,seg,cnt_16) ; // 监测函数
- // end
-
- endmodule