83 lines
3.2 KiB
Systemverilog
83 lines
3.2 KiB
Systemverilog
/*
|
|
Copyright 2021 Blue Liang, liangkangnan@163.com
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
module uart_tx (
|
|
input logic clk_i, // 时钟输入
|
|
input logic rst_ni, // 异步复位信号,低电平有效
|
|
input logic enable_i, // TX模块使能信号
|
|
input logic parity_en_i, // 校验使能
|
|
input logic parity_i, // 校验方式:奇校验还是偶检验
|
|
input logic we_i, // 开始发送数据
|
|
input logic [7:0] wdata_i, // 要发送的一个字节数据
|
|
input logic [15:0] div_ratio_i, // 波特率分频系数
|
|
output logic idle_o, // TX模块空闲
|
|
output logic tx_bit_o // 要发送的1 bit数据
|
|
);
|
|
|
|
logic [3:0] bit_cnt_d, bit_cnt_q;
|
|
logic [10:0] shift_reg_d, shift_reg_q;
|
|
logic tx_d, tx_q;
|
|
logic tick;
|
|
|
|
always_comb begin
|
|
if (!enable_i) begin
|
|
bit_cnt_d = 4'h0;
|
|
shift_reg_d = 11'h7ff;
|
|
tx_d = 1'b1;
|
|
end else begin
|
|
bit_cnt_d = bit_cnt_q;
|
|
shift_reg_d = shift_reg_q;
|
|
tx_d = tx_q;
|
|
if (we_i) begin
|
|
// LSB first
|
|
shift_reg_d = {1'b1, (parity_en_i ? parity_i : 1'b1), wdata_i, 1'b0};
|
|
bit_cnt_d = (parity_en_i ? 4'd11 : 4'd10);
|
|
end else if ((bit_cnt_q != 4'h0) && tick) begin
|
|
// 右移1位
|
|
shift_reg_d = {1'b1, shift_reg_q[10:1]};
|
|
tx_d = shift_reg_q[0];
|
|
bit_cnt_d = bit_cnt_q - 4'h1;
|
|
end
|
|
end
|
|
end
|
|
|
|
always_ff @(posedge clk_i or negedge rst_ni) begin
|
|
if (!rst_ni) begin
|
|
bit_cnt_q <= 4'h0;
|
|
shift_reg_q <= 11'h7ff;
|
|
tx_q <= 1'b1;
|
|
end else begin
|
|
bit_cnt_q <= bit_cnt_d;
|
|
shift_reg_q <= shift_reg_d;
|
|
tx_q <= tx_d;
|
|
end
|
|
end
|
|
|
|
assign idle_o = (bit_cnt_q == 4'h0);
|
|
assign tx_bit_o = tx_q;
|
|
|
|
clk_div #(
|
|
.RATIO_WIDTH(16)
|
|
) u_clk_div (
|
|
.clk_i(clk_i),
|
|
.rst_ni(rst_ni || (~we_i)),
|
|
.en_i(we_i || (bit_cnt_q != 4'h0)),
|
|
.ratio_i(div_ratio_i),
|
|
.clk_o(tick)
|
|
);
|
|
|
|
endmodule
|