UART_TXer.v:
// 2022-1-23 verilog学习
// 串口发送模块
`timescale 1ns/10ps
module UART_TXer(
clk,
res,
data_in,
en_data_in,
TX,
rdy
);
input clk;
input res;
input[7:0] data_in; // 准备发送的数据
input en_data_in; // 发送使能
output TX; // 不是output[9:0]的原因,发送数据是一位一位发的,一位寄存器即可
output rdy; // 空闲标志,0表示空闲
reg[3:0] state; // 主状态机寄存器
reg[9:0] send_buf; // 发送寄存器
assign TX = send_buf[0]; // 连接TX
reg[9:0] send_flag; // 用于判断右移结束
reg[12:0] con; // 用于计算波特周期
reg rdy; // ready=0 空闲
always@(posedge clk or negedge res)
if(~res)begin
state<=0; send_buf<=1; con<=0; rdy<=0; send_flag<=10'b10_0000_0000; // TX在空闲时是1,send_buf
end
else begin
case(state)
0:// 等待使能信号
begin
if(en_data_in)begin
send_buf <= {1'b1, data_in, 1'b0};
send_flag <= 10'b10_0000_0000;
rdy <= 1; // 准备发数据,不空闲
state<=1;
end
end
1:// 串口发送,send_buf寄存器右移
begin
if(con==5000-1)begin // 一个bit占宽0-4999
con<=0;
end
else begin
con<=con+1;
end
if(con==0)begin // 新的bit到来
send_buf[8:0] <= send_buf[9:1]; // 右移,该时刻send_buf[8:0]等于上一时刻send_buf[9:1]
send_flag[8:0] <= send_flag[9:1];
end
if(send_flag[0])begin
rdy <= 0; // 发完数据,空闲
state <= 0;
end
end
endcase
end
endmodule
// testbench
module UART_TXer_tb;
reg clk,res;
reg[7:0] data_in;
reg en_data_in;
wire TX;
wire rdy;
UART_TXer UART_TXer(
clk,
res,
data_in,
en_data_in,
TX,
rdy
); // 同名例化
initial begin
clk<=0; res<=0; data_in<=8'h0a; en_data_in<=0;
#17 res<=1;
#30 en_data_in<=1; // 发送
#10 en_data_in<=0;
#2000000 $stop;
end
always #5 clk = ~clk;
endmodule
modelsim:
data_in = 8’h0a = 0000_1010,从 data_in[0] 发到 data_in[7],
TX依次为 0,1,0,1,0,0,0,0