UART
10021 ワード
タンデム実験
注意:連続送信の精度を確保するために、システムクロックを50 Hz 1)トップレベルの実験モジュールに倍周波数することができる.
2)受入モジュール
送信モジュール
注意:連続送信の精度を確保するために、システムクロックを50 Hz 1)トップレベルの実験モジュールに倍周波数することができる.
module uart_top(
input sys_clk, // 50M
input sys_rst_n, // ,
//uart
input uart_rxd, //UART
output uart_txd //UART
);
//parameter define
parameter CLK_FREQ = 50000000; //
parameter UART_BPS = 115200; //
//wire define
wire uart_en_w; //UART
wire [7:0] uart_data_w; //UART
//*****************************************************
//** main code
//*****************************************************
uart_recv #( //
.CLK_FREQ (CLK_FREQ), //
.UART_BPS (UART_BPS)) //
u_uart_recv(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.uart_rxd (uart_rxd),
.uart_done (uart_en_w),
.uart_data (uart_data_w)
);
uart_send #( //
.CLK_FREQ (CLK_FREQ), //
.UART_BPS (UART_BPS)) //
u_uart_send(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.uart_en (uart_en_w),
.uart_din (uart_data_w),
.uart_txd (uart_txd)
);
endmodule
2)受入モジュール
module uart_recv(
input sys_clk, //
input sys_rst_n, // ,
input uart_rxd, //UART
output reg uart_done, //
output reg [7:0] uart_data //
);
//parameter define
parameter CLK_FREQ = 50000000; //
parameter UART_BPS = 9600; //
localparam BPS_CNT = CLK_FREQ/UART_BPS; // ,
// BPS_CNT
//reg define
reg uart_rxd_d0;
reg uart_rxd_d1;
reg [15:0] clk_cnt; //
reg [ 3:0] rx_cnt; //
reg rx_flag; //
reg [ 7:0] rxdata; //
//wire define
wire start_flag;
//*****************************************************
//** main code
//*****************************************************
// ( ),
assign start_flag = uart_rxd_d1 & (~uart_rxd_d0);
// UART
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
uart_rxd_d0 <= 1'b0;
uart_rxd_d1 <= 1'b0;
end
else begin
uart_rxd_d0 <= uart_rxd;
uart_rxd_d1 <= uart_rxd_d0;
end
end
// start_flag ,
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
rx_flag <= 1'b0;
else begin
if(start_flag) //
rx_flag <= 1'b1; // , rx_flag
else if((rx_cnt == 4'd9)&&(clk_cnt == BPS_CNT/2))
rx_flag <= 1'b0; // ,
else
rx_flag <= rx_flag;
end
end
// ,
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
clk_cnt <= 16'd0;
rx_cnt <= 4'd0;
end
else if ( rx_flag ) begin //
if (clk_cnt < BPS_CNT - 1) begin
clk_cnt <= clk_cnt + 1'b1;
rx_cnt <= rx_cnt;
end
else begin
clk_cnt <= 16'd0; //
rx_cnt <= rx_cnt + 1'b1; // 1
end
end
else begin // ,
clk_cnt <= 16'd0;
rx_cnt <= 4'd0;
end
end
// uart
always @(posedge sys_clk or negedge sys_rst_n) begin
if ( !sys_rst_n)
rxdata <= 8'd0;
else if(rx_flag) //
if (clk_cnt == BPS_CNT/2) begin //
case ( rx_cnt )
4'd1 : rxdata[0] <= uart_rxd_d1; //
4'd2 : rxdata[1] <= uart_rxd_d1;
4'd3 : rxdata[2] <= uart_rxd_d1;
4'd4 : rxdata[3] <= uart_rxd_d1;
4'd5 : rxdata[4] <= uart_rxd_d1;
4'd6 : rxdata[5] <= uart_rxd_d1;
4'd7 : rxdata[6] <= uart_rxd_d1;
4'd8 : rxdata[7] <= uart_rxd_d1; //
default:;
endcase
end
else
rxdata <= rxdata;
else
rxdata <= 8'd0;
end
//
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
uart_data <= 8'd0;
uart_done <= 1'b0;
end
else if(rx_cnt == 4'd9) begin //
uart_data <= rxdata; //
uart_done <= 1'b1; //
end
else begin
uart_data <= 8'd0;
uart_done <= 1'b0;
end
end
endmodule
送信モジュール
module uart_send(
input sys_clk, //
input sys_rst_n, // ,
input uart_en, //
input [7:0] uart_din, //
output reg uart_txd //UART
);
//parameter define
parameter CLK_FREQ = 50000000; //
parameter UART_BPS = 9600; //
localparam BPS_CNT = CLK_FREQ/UART_BPS; // , BPS_CNT
//reg define
reg uart_en_d0;
reg uart_en_d1;
reg [15:0] clk_cnt; //
reg [ 3:0] tx_cnt; //
reg tx_flag; //
reg [ 7:0] tx_data; //
//wire define
wire en_flag;
//*****************************************************
//** main code
//*****************************************************
// uart_en ,
assign en_flag = (~uart_en_d1) & uart_en_d0;
// uart_en
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
uart_en_d0 <= 1'b0;
uart_en_d1 <= 1'b0;
end
else begin
uart_en_d0 <= uart_en;
uart_en_d1 <= uart_en_d0;
end
end
// en_flag , ,
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
tx_flag <= 1'b0;
tx_data <= 8'd0;
end
else if (en_flag) begin //
tx_flag <= 1'b1; // , tx_flag
tx_data <= uart_din; //
end
else
if ((tx_cnt == 4'd9)&&(clk_cnt == BPS_CNT/2))
begin // ,
tx_flag <= 1'b0; // , tx_flag
tx_data <= 8'd0;
end
else begin
tx_flag <= tx_flag;
tx_data <= tx_data;
end
end
// ,
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
clk_cnt <= 16'd0;
tx_cnt <= 4'd0;
end
else if (tx_flag) begin //
if (clk_cnt < BPS_CNT - 1) begin
clk_cnt <= clk_cnt + 1'b1;
tx_cnt <= tx_cnt;
end
else begin
clk_cnt <= 16'd0; //
tx_cnt <= tx_cnt + 1'b1; // 1
end
end
else begin //
clk_cnt <= 16'd0;
tx_cnt <= 4'd0;
end
end
// uart
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
uart_txd <= 1'b1;
else if (tx_flag)
case(tx_cnt)
4'd0: uart_txd <= 1'b0; //
4'd1: uart_txd <= tx_data[0]; //
4'd2: uart_txd <= tx_data[1];
4'd3: uart_txd <= tx_data[2];
4'd4: uart_txd <= tx_data[3];
4'd5: uart_txd <= tx_data[4];
4'd6: uart_txd <= tx_data[5];
4'd7: uart_txd <= tx_data[6];
4'd8: uart_txd <= tx_data[7]; //
4'd9: uart_txd <= 1'b1; //
default: ;
endcase
else
uart_txd <= 1'b1; //
end
endmodule