开源原创verilog四通道接收一通道转发UART模块
开源原创verilog四通道接收一通道转发UART模块。该模块实现4通道接收,1通道转发,4字节为1帧。
设置发送通道波特率为接收通道的4倍就可以保证不丢失数据。
如果接收通道的数据不是连续的,间隔时间内能保证转发完4帧数据,这样发送通道波特率可以与接收通道相同。
每通道包括8字节FIFO,转发某一通道数据帧时不影响数据的接收。
module uart8n1(
input rst,
input clk,
input rxd,
output txd
);
parameter true = 1'b0, false = 1'b1;
wire txen, txfull, txempty, txhfull;
wire dat;
wire rdrxd;
wire rxfull;
wire rxempty;
wire rxhfull;
uart8n1_ctrl ctrl(
.rst(rst),
.clk(clk),
.rxhfull(rxhfull),
.txhfull(txhfull),
.txen(txen),
.rdrxd(rdrxd)
);
uart8n1_rx rx1(
.rst(rst),
.clk(clk),
.rxd(rxd),
.rxen(true),
.divp(50_000_000/115_200), //fclk/baud
.rdrxd(rdrxd),
.dat(dat),
.rxfull(rxfull),
.rxempty(rxempty),
.rxhfull(rxhfull)
);
uart8n1_rx rx2(
.rst(rst),
.clk(clk),
.rxd(rxd),
.rxen(true),
.divp(50_000_000/115_200), //fclk/baud
.rdrxd(rdrxd),
.dat(dat),
.rxfull(rxfull),
.rxempty(rxempty),
.rxhfull(rxhfull)
);
uart8n1_rx rx3(
.rst(rst),
.clk(clk),
.rxd(rxd),
.rxen(true),
.divp(50_000_000/115_200), //fclk/baud
.rdrxd(rdrxd),
.dat(dat),
.rxfull(rxfull),
.rxempty(rxempty),
.rxhfull(rxhfull)
);
uart8n1_rx rx4(
.rst(rst),
.clk(clk),
.rxd(rxd),
.rxen(true),
.divp(50_000_000/115_200), //fclk/baud
.rdrxd(rdrxd),
.dat(dat),
.rxfull(rxfull),
.rxempty(rxempty),
.rxhfull(rxhfull)
);
uart8n1_tx tx(
.rst(rst),
.clk(clk),
.dat(dat),
.txen(txen),
.divp(50_000_000/115_200),//fclk/baud
.txd(txd),
.txfull(txfull),
.txempty(txempty),
.txhfull(txhfull)
);
endmodule
module uart8n1_ctrl(
input rst,
input clk,
input rxhfull,
input txhfull,
output txen,
output rdrxd
);
parameter true = 1'b0, false = 1'b1;
reg txe = false;
assign txen = txe;
reg rdd = 4'hf;
assign rdrxd = rdd;
reg ctrstate = IDLE;
parameter IDLE = 3'h0, RD0 = 3'h1, RD1 = 3'h2, RD2 = 3'h3, RD3 = 3'h4;
reg statetrans1 = 2'b0;
parameter RDRXFIFO = 2'd0, WRTXFIFO = 2'd1, BYTECNT = 2'd2;
reg bytecnt = 2'b0;
task trans4bytes;
input chl;
case(statetrans1)
RDRXFIFO: begin
rdd <= true;
statetrans1 <= 2'd1;
end
WRTXFIFO: begin
txe <= true;
statetrans1 <= 2'd2;
end
BYTECNT: begin
txe <= false;
rdd <= false;
if(bytecnt == 2'd3) begin
ctrstate <= IDLE;
end
else begin
bytecnt <= bytecnt + 1'b1;
statetrans1 <= RDRXFIFO;
end
end
endcase
endtask
always @(posedge clk or negedge rst) begin
if(rst == true) begin
rdd <= {4{false}};
txe <= false;
ctrstate <= IDLE;
end
else begin
case(ctrstate)
IDLE: begin
rdd <= {4{false}};
txe <= false;
bytecnt <= 2'd0;
statetrans1 <= RDRXFIFO;
if(rxhfull == true) begin ctrstate <= RD0; end
else if(rxhfull == true) begin ctrstate <= RD1; end
else if(rxhfull == true) begin ctrstate <= RD2; end
else if(rxhfull == true) begin ctrstate <= RD3; end
else begin ctrstate <= IDLE; end
end
RD0: begin trans4bytes(0); end
RD1: begin trans4bytes(1); end
RD2: begin trans4bytes(2); end
RD3: begin trans4bytes(3); end
endcase
end
end
endmodule
module uart8n1_rx(
input rst,
input clk,
input rxd,
input rxen,
input divp,
input rdrxd,
output dat,
output rxfull,
output rxempty,
output rxhfull
);
parameter true = 1'b0, false = 1'b1;
reg rxdata = 8'b0;
wire rxdat = rxdata;
reg dready = false;
wire ien = dready;
wire rxdlpo;
reg divcnt = 16'b0;
reg bitcnt = 3'b0;
reg rxstate = IDLE;
parameter IDLE = 2'h0, RXSTART = 2'h1, RXDATBITS = 2'h2, RXSTOP = 2'h3;
fifo8x8 rxfifo(
.rst(rst),
.ien(ien),
.oen(rdrxd),
.idat(rxdat),
.odat(dat),
.full(rxfull),
.empty(rxempty),
.hfull(rxhfull)
);
lowpass lp(
.clk(clk),
.lin(rxd),
.lout(rxdlpo)
);
always @ (posedge clk or negedge rst) begin
if(rst == 1'b0) begin
dready <= false;
divcnt <= 16'b0;
rxstate <= IDLE;
end
else begin
case(rxstate)
IDLE: begin
dready <= false;
if(rxen == true && rxdlpo == 1'b0) begin
divcnt <= 16'b0;
rxstate <= RXSTART;
end
end
RXSTART: begin
if(divcnt == divp) begin
divcnt <= 16'b0;
if(rxdlpo == 1'b0) begin
bitcnt <= 3'b0;
rxstate <= RXDATBITS;
end
else begin
rxstate <= IDLE;
end
end
else begin
divcnt <= divcnt + 1'b1;
end
end
RXDATBITS: begin
if(divcnt == divp) begin
// rxdata <= {rxdlpo,rxdata}; //Lsb first
rxdata <= {rxdata,rxdlpo}; //Msb first
divcnt <= 16'b0;
if(bitcnt == 3'h7) begin
bitcnt <= 3'b0;
rxstate <= RXSTOP;
end
else begin
bitcnt <= bitcnt + 1'b1;
end
end
else begin
divcnt <= divcnt + 1'b1;
end
end
RXSTOP: begin
if(divcnt == divp) begin
divcnt <= 16'b0;
rxstate <= IDLE;
if(rxdlpo == 1'b1) begin
dready <= true;
end
end
else begin
divcnt <= divcnt + 1'b1;
end
end
endcase
end
end
endmodule
module uart8n1_tx(
input rst,
input clk,
input dat,
input txen,
input divp,
output reg txd,
output txfull,
output txempty,
output txhfull
);
parameter true = 1'b0, false = 1'b1;
wire txdat;
reg rdfifo = false;
wire oen = rdfifo;
reg divcnt = 16'b0;
reg bitcnt = 3'b0;
reg txstate = IDLE;
parameter IDLE = 2'h0, TXSTART = 2'h1, TXDATBITS = 2'h2, TXSTOP = 2'h3;
fifo8x8 txfifo(
.rst(rst),
.ien(txen),
.oen(oen),
.idat(dat),
.odat(txdat),
.full(txfull),
.empty(txempty),
.hfull(txhfull)
);
always @ (posedge clk or negedge rst) begin
if(rst == 1'b0) begin
txd <= 1'b1;
rdfifo <= false;
txstate <= IDLE;
end
else begin
case(txstate)
IDLE: begin
txd <= 1'b1;
if(txempty == false) begin
divcnt <= 16'b0;
txstate <= TXSTART;
end
end
TXSTART: begin
txd <= 1'b0;
rdfifo <= true;
if(divcnt == divp) begin
divcnt <= 16'b0;
bitcnt <= 3'b0;
txstate <= TXDATBITS;
end
else begin
divcnt <= divcnt + 1'b1;
end
end
TXDATBITS: begin
// txd <= txdat; //Lsb first
txd <= txdat; //Msb first
if(divcnt == divp) begin
divcnt <= 16'b0;
if(bitcnt == 3'd7) begin
bitcnt <= 3'b0;
txstate <= TXSTOP;
end
else begin
bitcnt <= bitcnt + 1'b1;
end
end
else begin
divcnt <= divcnt + 1'b1;
end
end
TXSTOP: begin
txd <= 1'b1;
rdfifo <= false;
if(divcnt == divp) begin
divcnt <= 16'b0;
txstate <= IDLE;
end
else begin
divcnt <= divcnt + 1'b1;
end
end
endcase
end
end
endmodule
module fifo8x8(
input rst,
input ien,
input oen,
input idat,
output odat,
output full,
output empty,
output hfull
);
parameter true = 1'b0, false = 1'b1;
reg mem ;
reg wraddr = {3{1'b0}};
reg rdaddr = {3{1'b1}};
wire datnum = wraddr - rdaddr;
assign full= datnum == 1'b0 ? true : false;
assign empty = datnum == 1'b1 ? true : false;
assign hfull = datnum > 3'h4 ? true : false;
assign odat = oen == true ? mem : 8'bz;
always @ (negedge ien or negedge rst) begin
if(rst == 1'b0) begin //reset
wraddr <= {3{1'b0}};
end
else begin
if(full == false) begin //push
mem <= idat;
wraddr <= wraddr + 1'b1;
end
end
end
always @ (negedge oen or negedge rst) begin
if(rst == 1'b0) begin //reset
rdaddr <= {3{1'b1}};
end
else begin
if(empty == false) begin //pop
rdaddr <= rdaddr + 1'b1;
end
end
end
endmodule
module lowpass(
input clk,
input lin,
output lout
);
reg lpbuf;
always @ (posedge clk) begin lpbuf <= {lpbuf,lin}; end
wire lin1 = & lpbuf;
wire lin0 = | lpbuf;
assign lout = (lin1 == 1'b1) ? 1'b1 : (lin0 == 1'b0) ? 1'b0 : lout;
endmodule
为方便大家下载引用,打包工程代码如下,请勿用于商业用途,用于教程或出版请联系本人。
发送通道的FIFO可以省了,直接对接对应接收通道的FIFO就可以,可以节省不少资源。 只要资源足够,可以扩展到N通道,代码扩展很方便。 4RX、1TX加调度代码只占用700多个LE。 非常不错的思路,值得学习一下
感谢skyxjh 。 顶起,向skyxjh学习。 学习!!!!!!!!!! 参考学习一下设计思路 4收1发用在什么地方?
这个可以用在哪些方面 采样倍数是多少? 丢包吗???????? 感谢分享
页:
[1]