module USRT_send(
rst, //异步复位信号,高有效
clk, //时钟信号,上升沿有效,16倍波特率
is8bit, //为高时发送8Bit数据,
//为低时发送7Bit数据
checkmode, //校验方式
// 2'b00 :无校验,不发送校验位
// 2'b01 :偶校验
// 2'b10 :奇校验
// 2'b11 :未定义,不发送校验位
is1stop, //停止位长度,为高时1个Bit,否则1.5Bit
din, //待发送字符数据
dinwr, //发送数据写脉冲,高有效
dinfree, //发送缓冲区空标志,高表示可以写入字符
txd //串行输出
);
input rst,clk;
input is8bit,is1stop;
input [1:0] checkmode;
input [7:0] din;
input dinwr;
output dinfree;
output txd;
reg txd;
wire Baud1X,Baud2X;
reg BaudClr;
wire dataLoaded;
wire [7:0] SendData;
reg move2Shifter,shiften;
wire datashiftout,datacheckval,shiftlastbit;
//波特率分频器实例
BaudDiv BaudDiv( .clr(BaudClr), .clk(clk), .Baud1X(Baud1X),
.Baud2X(Baud2X));
//发送数据缓冲区实例
SendBuff SendBuff( .rst(rst), .clk(clk), .wr(dinwr),
.rd(move2Shifter), .din(din) , .dout(SendData),
.wren(dinfree), .rden(dataLoaded));
//移位模块实例
ShiftReg ShiftReg( .rst(rst), .clk(clk), .shiften(shiften),
.wr(move2Shifter), .is8Bit(is8bit), .din(SendData),
.shiftout(datashiftout), .chkval(datacheckval),
.islastBit(shiftlastbit));
//
reg [2:0] state,nextstate; //state:状态寄存器;nextstate:次态
//状态编码
parameter ST_IDLE = 3'h0; //
parameter ST_LOAD = 3'h1; //
parameter ST_START = 3'h2; //
parameter ST_CHECK = 3'h3; //
parameter ST_STOP = 3'h4; //
parameter ST_STOP1 = 3'h5; //
//状态机输出
always@(*)
begin
txd = 1'b1;
BaudClr = 1'b0;
move2Shifter = 1'b0;
shiften = Baud1X;
case(state)
ST_IDLE :
begin
BaudClr = 1'b1;
shiften = 1'b0;
end
ST_LOAD :
begin
BaudClr = 1'b1;
move2Shifter = 1'b1;
shiften = 1'b0;
end
ST_START :
begin
txd = datashiftout;
end
ST_CHECK :
begin
case (checkmode)
2'b01 : txd = datacheckval ^ 1'b1;
2'b10 : txd = datacheckval;
default : txd = 1'b1;
endcase
shiften = 1'b0;
end
ST_STOP : begin
shiften = 1'b0;
end
default : ;
endcase
end
//次态计算
always@(*)
begin
nextstate = state;
case(state)
ST_IDLE :
begin
if (dataLoaded) nextstate = ST_LOAD;
end
ST_LOAD : nextstate = ST_START;
ST_START :
if (shiftlastbit & Baud1X)
case(checkmode)
2'b01,2'b10 : nextstate = ST_CHECK;
default : nextstate = ST_STOP;
endcase
ST_CHECK :
if (Baud1X) nextstate = ST_STOP;
ST_STOP :
if (Baud1X)
begin
if (is1stop) nextstate = ST_IDLE;
else nextstate = ST_STOP1;
end
ST_STOP1 :
if (Baud2X) nextstate = ST_IDLE;
default :
nextstate = ST_IDLE;
endcase
end
//更新状态
always@(posedge rst or posedge clk)
if(rst) state <= ST_IDLE;
else state <= nextstate;
endmodule
module BaudDiv(
clr, //清零信号,高有效
clk, //时钟,上升沿有效,16倍波特率时钟
Baud1X, //
Baud2X //
);
input clr,clk;
output Baud1X,Baud2X;
reg [3 : 0] BaudCnt;
always @(posedge clk)
if (clr) BaudCnt <= 4'h0;
else BaudCnt <= BaudCnt + 4'h1;
assign #1 Baud1X = (BaudCnt == 4'hf) ? 1'b1 : 1'b0;
assign #1 Baud2X = ((BaudCnt == 4'h7) ? 1'b1 : 1'b0);
endmodule
module ShiftReg(
rst, //
clk, //
shiften, //
wr, //
is8Bit, //
din, //
shiftout, //
chkval, //
islastBit //
);
input rst,clk,shiften,wr,is8Bit;
input [7:0] din;
output shiftout,chkval,islastBit;
reg chkval;
reg [8:0] shiftreg;
//
always@(posedge rst or posedge clk)
if (rst) shiftreg <= 9'hff;
else if(wr) shiftreg <= {din,1'b0};
else if(shiften) shiftreg <= {1'b1,shiftreg[8:1]};
//
always@(posedge rst or posedge clk)
if(rst) chkval <= 1'b0;
else if (wr) chkval <= 1'b0;
else if(shiften) chkval <= chkval ^ shiftreg[0];
reg [3:0] BitCnt;
//
always@(posedge rst or posedge clk)
if(rst) BitCnt <= 4'h0;
else if (wr) BitCnt <= is8Bit ? 4'h8 : 4'h7;
else if(shiften && (BitCnt != 4'h0)) BitCnt <= BitCnt - 4'h1;
assign #1 islastBit = (BitCnt == 4'h0);
assign #1 shiftout = shiftreg[0];
endmodule
module SendBuff(
rst, //
clk, //
wr, //
rd, //
din, //
dout, //
wren, //
rden //
);
input rst,clk,wr,rd;
input [7:0] din;
output [7:0] dout;
output wren,rden;
reg [7:0] dout;
reg wren,rden;
always@(posedge rst or posedge clk)
if (rst)
begin
dout <= 8'h00;
wren <= 1'b1;
rden <= 1'b0;
end
else if (wr)
begin
dout <= din;
wren <= 1'b0;
rden <= 1'b1;
end
else if (rd)
begin
rden <= 1'b0;
wren <= 1'b1;
end
endmodule
module TBUART;
reg rst,clk16x;
reg [7:0] din;
reg dinwr;
wire dinfree,txd;
initial
begin
dinwr = 1'b0;
#94 DINWR(8'h55);
wait(dinfree) #10 DINWR(8'ha7);
end
USRT_send DUV(
.rst(rst),
.clk(clk16x),
.is8bit(1'b1),
.checkmode(2'b01),
.is1stop(1'b1),
.din(din),
.dinwr(dinwr),
.dinfree(dinfree),
.txd(txd)
);
initial
begin
rst = 1'b1;
#21 rst = 1'b0;
end
initial
begin
clk16x = 1'b0;
forever #5 clk16x = ~clk16x;
end
task DINWR;
input [7:0] indata;
begin
din = indata;
#5 dinwr = 1'b1;
#10 dinwr = 1'b0;
end
endtask
endmodule
¥29.8
¥9.9
¥59.8