串口协议,很容易理解,所以就由这个来上手。
串口分为三部分,至少我自己想实现的只有三部分。
起始状态、发数据状态还有停止位状态。
在这里起始位一位,停止位一位,数据位8位,没有奇偶校验。
本来加多了一个状态init,最后看到别人的那种可以一直发的,然后就把它注释掉了。
于是在这基础上,就选择用状态机了,其实用计数器更好一点。但都写一半就懒得改了。
本来想设置data变了就发串口的。最后还是注释掉了。
不会英语所以随便打了。。
贴代码:
module uart(
input wire clk,
input wire rst_n,
input wire [7:0] data,
output reg tx,
input wire fork_flag,
output wire ok,
output reg [3:0] bit
);
localparam init = 'b0011;
localparam start = 'b0001;
localparam stop = 'b0010;
localparam write = 'b0000;
reg [3:0]staus;
// wire data_flag;
// reg [7:0]data_d1;
// reg write_flag;
// always @(posedge clk or negedge rst_n)
// begin
// if(!rst_n)
// begin
// data_d1 <= 8'b0;
// write_flag <= 0;
// end
// else if(!data_flag)
// begin
// if(data_d1 != data)
// begin
// write_flag <= 1;
// end
// else
// begin
// write_flag <= 0;
// end
// end
// else
// begin
// data_d1 <= data;
// end
// end
assign data_flag = staus == write;
assign ok = bit == 8;
assign write_flag = fork_flag;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
staus <= stop;
end
// else if(staus == stop)
// begin
// staus <= init;
// end
else if(staus == start)
begin
staus <= write;
end
else if(bit == 7)
begin
staus <= stop;
end
else if(write_flag & staus == stop)
begin
staus <= start;
end
else if((staus != stop) & (staus != write) & (staus != start))
begin
staus <= stop;
end
else
begin
staus <= staus;
end
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
tx <= 1;
bit <= 0;
end
else
begin
case(staus)
// init:
// begin
// tx <= 1;
// bit <= bit;
// end
start:
begin
tx <= 0;
bit <= 0;
end
write:
begin
tx <= data[bit];
bit <= bit + 1;
end
stop:
begin
tx <= 1;
bit <= 0;
end
default:
begin
tx <= tx;
bit <= bit;
end
endcase
end
end
endmodule
testbench:
`timescale 1ns / 1ns
module tb_uart;
// usat Parameters
parameter PERIOD = 10;
// uart Inputs
reg clk = 0 ;
reg rst_n = 0 ;
reg [7:0] data = 0 ;
wire ok;
reg fork_flag;
// uart Outputs
wire tx ;
wire [3:0] bit ;
initial
begin
clk = 0;
forever #(PERIOD/2) clk=~clk;
end
initial
begin
rst_n = 0;
#(PERIOD*2) rst_n = 1;
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
data <= 8'hFF;
fork_flag <= 1;
end
else if(ok)
begin
data <= data - 1;
fork_flag <= 1;
end
else
begin
fork_flag <= 0;
data <= data;
end
end
uart u_uart (
.clk ( clk ),
.rst_n ( rst_n ),
.data ( data [7:0] ),
.ok ( ok ) ,
.fork_flag (1),
.tx ( tx ),
.bit ( bit [3:0] )
);
// initial
// begin
// $finish;
// end
endmodule
ff的数据从发送到停止位: