skyxjh 发表于 2013-7-3 19:23:07

开源原创verilog四通道接收一通道转发UART模块

开源原创verilog四通道接收一通道转发UART模块。
该模块实现4通道接收,1通道转发,4字节为1帧。
设置发送通道波特率为接收通道的4倍就可以保证不丢失数据。
如果接收通道的数据不是连续的,间隔时间内能保证转发完4帧数据,这样发送通道波特率可以与接收通道相同。
每通道包括8字节FIFO,转发某一通道数据帧时不影响数据的接收。

skyxjh 发表于 2013-7-3 19:24:27


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

skyxjh 发表于 2013-7-3 19:24:55


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

skyxjh 发表于 2013-7-3 19:25:23


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

skyxjh 发表于 2013-7-3 19:25:40


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

skyxjh 发表于 2013-7-3 19:26:02


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

skyxjh 发表于 2013-7-3 19:26:17


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

skyxjh 发表于 2013-7-3 19:32:31

为方便大家下载引用,打包工程代码如下,请勿用于商业用途,用于教程或出版请联系本人。

skyxjh 发表于 2013-7-3 21:05:54

发送通道的FIFO可以省了,直接对接对应接收通道的FIFO就可以,可以节省不少资源。

skyxjh 发表于 2013-7-3 21:08:05

只要资源足够,可以扩展到N通道,代码扩展很方便。

skyxjh 发表于 2013-7-3 21:12:05

4RX、1TX加调度代码只占用700多个LE。

coding2011 发表于 2013-7-3 22:26:40

非常不错的思路,值得学习一下

lyl520719 发表于 2013-7-4 07:58:22

感谢skyxjh 。

sky_prince 发表于 2013-7-4 09:51:12

顶起,向skyxjh学习。

wdooy 发表于 2013-7-5 16:53:25

学习!!!!!!!!!!

afei8856 发表于 2013-7-18 10:52:16

参考学习一下设计思路

zpwkxg 发表于 2015-3-1 15:06:56

4收1发用在什么地方?

xiaomao1490 发表于 2015-3-1 15:24:52

这个可以用在哪些方面

wowangru 发表于 2018-11-9 20:52:37

采样倍数是多少?

wowangru 发表于 2018-11-16 13:48:37

丢包吗????????

TKZXJ 发表于 2018-12-16 15:42:58

感谢分享
页: [1]
查看完整版本: 开源原创verilog四通道接收一通道转发UART模块