| |
verilog;toolbar:false">一次Trig写入一个byte 发出去一个byte,如果再增加一个fifo就好了 module UART_TX #( parameter BAUDRATE = 115200, parameter FREQ_CLK = 50000000 )( TX_DOUT, TX_DONE, TX_ACTIVE, CLK, RSTB, TX_DIN, TX_TRIG ); output reg TX_DOUT; output reg TX_DONE; output reg TX_ACTIVE; input wire CLK; input wire RSTB; input wire TX_TRIG; input wire [7:0] TX_DIN; reg [15:0] DIV_CNT; reg [3:0] BIT_INDEX; reg [7:0] TX_DATA_REG; reg [2:0] TX_PST; reg [2:0] TX_NST; reg DIV_CNT_INC; reg DIV_CNT_CLR; reg BIT_INDEX_INC; reg BIT_INDEX_CLR; reg DATA_ONE; reg DATA_ZERO; reg TX_TRIG_1P; reg TX_TRIG_2P; reg TX_TRIG_3P; reg TX_EN; wire TX_TRIG_RISE; wire TX_1bit; parameter NCPB = FREQ_CLK/BAUDRATE; //NUMBER_CLK_PER_BIT parameter TX_IDLE = 3'b000; parameter TX_START = 3'b001; parameter TX_DATA = 3'b010; parameter TX_STOP = 3'b011; parameter TX_FINISH = 3'b100; always@(posedge CLK or negedge RSTB)begin if(!RSTB)begin TX_PST <= TX_IDLE; TX_DONE <= 1'b0; TX_ACTIVE <= 1'b0; end else if(TX_TRIG_RISE)begin TX_PST <= TX_IDLE; TX_DONE <= 1'b0; TX_ACTIVE <= 1'b0; end else begin TX_PST <= TX_NST; TX_DONE <= (TX_NST == TX_FINISH); TX_ACTIVE <= (|TX_PST[1:0]); end end always@(posedge CLK or negedge RSTB)begin if(!RSTB)begin TX_DATA_REG <= 8'h00; end else begin TX_DATA_REG <= TX_DIN; end end always@(posedge CLK or negedge RSTB)begin if(!RSTB)begin TX_DOUT <= 1'b0; end else if(DATA_ONE) begin TX_DOUT <= 1'b1; end else if(DATA_ZERO) begin TX_DOUT <= 1'b0; end end always@(posedge CLK or negedge RSTB)begin if(!RSTB)begin DIV_CNT <= 16'h00; end else if(DIV_CNT_INC) begin DIV_CNT <= DIV_CNT + 1'b1; end else if(DIV_CNT_CLR) begin DIV_CNT <= 16'h00; end end always@(posedge CLK or negedge RSTB)begin if(!RSTB)begin BIT_INDEX <= 4'h0; end else if(BIT_INDEX_INC) begin BIT_INDEX <= BIT_INDEX + 1'b1; end else if(BIT_INDEX_CLR) begin BIT_INDEX <= 16'h00; end end always@(posedge CLK or negedge RSTB)begin if(!RSTB)begin {TX_TRIG_1P,TX_TRIG_2P,TX_TRIG_3P} <= 3'b0; end else begin {TX_TRIG_1P,TX_TRIG_2P,TX_TRIG_3P} <= {TX_TRIG,TX_TRIG_1P,TX_TRIG_2P}; end end assign TX_TRIG_RISE = TX_TRIG_2P & !TX_TRIG_3P; always@(posedge CLK or negedge RSTB)begin if(!RSTB)begin TX_EN <= 1'b0; end else if(TX_DONE) begin TX_EN <= 1'b0; end else if(TX_TRIG_RISE)begin TX_EN <= 1'b1; end end assign TX_1bit = DIV_CNT >= NCPB; always@(*) begin TX_NST = TX_PST; DIV_CNT_INC = 1'b0; DIV_CNT_CLR = 1'b0; BIT_INDEX_INC = 1'b0; BIT_INDEX_CLR = 1'b0; DATA_ONE = 1'b0; DATA_ZERO = 1'b0; case(TX_PST) TX_IDLE : begin DATA_ONE = 1'b1; if(TX_EN) TX_NST = TX_START; else TX_NST = TX_IDLE; end TX_START : begin DATA_ZERO = 1'b1; if(DIV_CNT <= NCPB )begin DIV_CNT_INC = 1'b1; end else begin DIV_CNT_CLR = 1'b1; TX_NST = TX_DATA; end end TX_DATA : begin if(TX_DATA_REG[BIT_INDEX]) DATA_ONE = 1'b1; else DATA_ZERO = 1'b1; if(DIV_CNT <= NCPB )begin DIV_CNT_INC = 1'b1; end else begin DIV_CNT_CLR = 1'b1; if(BIT_INDEX != 3'h7)begin BIT_INDEX_INC = 1'b1; end else begin BIT_INDEX_CLR = 1'b1; TX_NST = TX_STOP; end end end TX_STOP : begin DATA_ONE = 1'b1; if(DIV_CNT <= NCPB )begin DIV_CNT_INC = 1'b1; end else begin DIV_CNT_CLR = 1'b1; TX_NST = TX_FINISH; end end TX_FINISH : begin DATA_ONE = 1'b1; DIV_CNT_CLR = 1'b1; BIT_INDEX_CLR = 1'b1; TX_NST = TX_IDLE; end default : TX_NST = TX_IDLE; endcase end endmodule
module UART_RX
#(
parameter BAUDRATE = 115200,
parameter FREQ_CLK = 50000000
)(
RX_DOUT,
RX_VALID,
RX_ACTIVE,
CLK,
RSTB,
RX_DIN,
RX_TRIG
);
output reg [7:0] RX_DOUT;
output reg RX_VALID;
output reg RX_ACTIVE;
input wire CLK;
input wire RSTB;
input wire RX_TRIG;
input wire RX_DIN;
reg [15:0] DIV_CNT;
reg [7:0] RX_DATA_REG;
reg [3:0] BIT_INDEX;
reg [2:0] RX_PST;
reg [2:0] RX_NST;
reg DIV_CNT_INC;
reg DIV_CNT_CLR;
reg BIT_INDEX_INC;
reg BIT_INDEX_CLR;
reg BIT_WRITE;
reg BIT_CLR;
reg RX_TRIG_1P;
reg RX_TRIG_2P;
reg RX_TRIG_3P;
reg RX_EN;
wire RX_TRIG_RISE;
reg RX_DIN_1P;
reg RX_DIN_2P;
parameter NCPB = FREQ_CLK/BAUDRATE; //NUMBER_CLK_PER_BIT
parameter RX_IDLE = 3'b000;
parameter RX_START = 3'b001;
parameter RX_DATA = 3'b010;
parameter RX_STOP = 3'b011;
parameter RX_DONE = 3'b100;
always@(posedge CLK or negedge RSTB)begin
if(!RSTB)begin
RX_PST <= RX_IDLE;
RX_VALID <= 1'b0;
RX_ACTIVE <= 1'b0;
end else begin
RX_PST <= RX_NST;
RX_VALID <= (RX_PST == RX_DONE);
RX_ACTIVE <= (|RX_PST[1:0]);
end
end
always@(posedge CLK or negedge RSTB)begin
if(!RSTB)begin
{RX_DIN_1P,RX_DIN_2P} <= 2'b0;
end else begin
{RX_DIN_1P,RX_DIN_2P} <= {RX_DIN,RX_DIN_1P};
end
end
always@(posedge CLK or negedge RSTB)begin
if(!RSTB)begin
RX_DATA_REG <= 8'h00;
end else if(BIT_WRITE) begin
RX_DATA_REG[BIT_INDEX] <= RX_DIN_2P;
end else if(BIT_CLR) begin
RX_DATA_REG <= 8'h00;
end
end
always@(posedge CLK or negedge RSTB)begin
if(!RSTB)begin
RX_DOUT <= 8'h00;
end else if(RX_VALID)begin
RX_DOUT <= RX_DATA_REG;
end
end
always@(posedge CLK or negedge RSTB)begin
if(!RSTB)begin
DIV_CNT <= 16'h00;
end else if(DIV_CNT_INC) begin
DIV_CNT <= DIV_CNT + 1'b1;
end else if(DIV_CNT_CLR) begin
DIV_CNT <= 16'h00;
end
end
always@(posedge CLK or negedge RSTB)begin
if(!RSTB)begin
BIT_INDEX <= 4'h0;
end else if(BIT_INDEX_INC) begin
BIT_INDEX <= BIT_INDEX + 1'b1;
end else if(BIT_INDEX_CLR) begin
BIT_INDEX <= 16'h00;
end
end
always@(posedge CLK or negedge RSTB)begin
if(!RSTB)begin
{RX_TRIG_1P,RX_TRIG_2P,RX_TRIG_3P} <= 3'b0;
end else begin
{RX_TRIG_1P,RX_TRIG_2P,RX_TRIG_3P} <= {RX_TRIG,RX_TRIG_1P,RX_TRIG_2P};
end
end
assign RX_TRIG_RISE = RX_TRIG_2P & !RX_TRIG_3P;
always@(posedge CLK or negedge RSTB)begin
if(!RSTB)begin
RX_EN <= 1'b0;
end else if(RX_VALID) begin
RX_EN <= 1'b0;
end else if(RX_TRIG_RISE)begin
RX_EN <= 1'b1;
end
end
always@(*) begin
RX_NST = RX_PST;
DIV_CNT_INC = 1'b0;
DIV_CNT_CLR = 1'b0;
BIT_INDEX_INC = 1'b0;
BIT_INDEX_CLR = 1'b0;
BIT_WRITE = 1'b0;
BIT_CLR = 1'b0;
case(RX_PST)
RX_IDLE : begin
if(RX_EN && !RX_DIN_2P)
RX_NST = RX_START;
else
RX_NST = RX_IDLE;
end
RX_START : begin
if(DIV_CNT < (NCPB/2 + 1'b1) )begin
DIV_CNT_INC = 1'b1;
end else begin
DIV_CNT_CLR = 1'b1;
if(!RX_DIN_2P)
RX_NST = RX_DATA;
else
RX_NST = RX_IDLE;
end
end
RX_DATA : begin
if(DIV_CNT < NCPB )begin
DIV_CNT_INC = 1'b1;
end else begin
DIV_CNT_CLR = 1'b1;
BIT_WRITE = 1'b1;
if(BIT_INDEX < 3'h7)begin
BIT_INDEX_INC = 1'b1;
end else begin
BIT_INDEX_CLR = 1'b1;
BIT_CLR = 1'b1;
RX_NST = RX_STOP;
end
end
end
RX_STOP : begin
if(DIV_CNT < NCPB )begin
DIV_CNT_INC = 1'b1;
end else begin
if(RX_DIN_2P)
RX_NST = RX_DONE;
else
RX_NST = RX_IDLE;
end
end
RX_DONE : begin
DIV_CNT_CLR = 1'b1;
BIT_INDEX_CLR = 1'b1;
RX_NST = RX_IDLE;
end
default : RX_NST = RX_IDLE;
endcase
end
endmodulemodule UART_TOP( TX_DOUT, TX_ACTIVE, TX_DONE, RX_VALID, RX_ACTIVE, CLK, RSTB, RX_DIN, TX_TRIG, RX_TRIG ); output TX_DOUT; output TX_ACTIVE; output TX_DONE; output RX_VALID; output RX_ACTIVE; input CLK; input RSTB; input RX_DIN; input TX_TRIG; input RX_TRIG; wire [7:0] RX_DOUT; UART_RX U_UART_RX( .RX_DOUT(RX_DOUT), .RX_VALID(RX_VALID), .RX_ACTIVE(RX_ACTIVE), .CLK(CLK), .RSTB(RSTB), .RX_DIN(RX_DIN), .RX_TRIG(RX_TRIG) ); UART_TX U_UART_TX( .TX_DOUT(TX_DOUT), .TX_DONE(TX_DONE), .TX_ACTIVE(TX_ACTIVE), .CLK(CLK), .RSTB(RSTB), .TX_DIN(RX_DOUT), .TX_TRIG(TX_TRIG) ); endmodule