日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > > AdriftCoreFPGA芯研社


在實(shí)際工程應(yīng)用中,常常需要通過串口一次性傳輸多字節(jié)的數(shù)據(jù)。例如,以太網(wǎng)模塊可能會發(fā)送經(jīng)過8字節(jié)對齊的一個時鐘周期的64位數(shù)據(jù),然后通過串口傳遞給下游的傳感器設(shè)備。類似地,DDR模塊可能以32字節(jié)對齊的形式發(fā)送一個時鐘周期的256位數(shù)據(jù),通過串口傳輸給上位機(jī)。如果每次都需要通過修改Verilog代碼的方式將數(shù)據(jù)拆分成8位的塊再發(fā)送給串口,將會顯得非常繁瑣。本文通過引入只有三種狀態(tài)的狀態(tài)機(jī),只需更改參數(shù)就可實(shí)現(xiàn)對任意字節(jié)位寬的串口數(shù)據(jù)發(fā)送。這種方法使得在不同情境下輕松適應(yīng)不同的數(shù)據(jù)格式,極大地提高了系統(tǒng)的靈活性和可維護(hù)性。




設(shè)計思路


首先,需要設(shè)計一個字節(jié)計數(shù)器,用于追蹤數(shù)據(jù)發(fā)送到了哪一個字節(jié)。


接著,設(shè)計三個狀態(tài):空閑狀態(tài)、準(zhǔn)備發(fā)送狀態(tài)和發(fā)送數(shù)據(jù)狀態(tài)。


在準(zhǔn)備發(fā)送狀態(tài)下,主要完成兩項(xiàng)任務(wù):一是每到達(dá)一個字節(jié)就啟用串口模塊,二是加載數(shù)據(jù)以準(zhǔn)備發(fā)送。


對于N字節(jié)數(shù)據(jù)的處理方式:每使用完一個字節(jié)后,執(zhí)行右移八位的操作,然后將N位數(shù)據(jù)的低八位發(fā)送給串口模塊(其中N為整數(shù))。這確保了數(shù)據(jù)的有效傳輸,并適應(yīng)了不同字節(jié)長度的情況。

data先從高位字節(jié)發(fā)送:

data <= data_tmp[DATAN_W-1:DATAN_W-8];
data_tmp <= {data_tmp[DATAN_W-9:0],data_tmp[DATAN_W-1:DATAN_W-8]};


data先從低位字節(jié)發(fā)送:

data     <= data_tmp[7:0];
data_tmp <= {data_tmp[7:0],data_tmp[DATAN_W-1:8]};


多字節(jié)發(fā)送模塊


該模塊實(shí)現(xiàn)了多數(shù)據(jù)傳輸?shù)幕A(chǔ)功能,當(dāng)然,可以擴(kuò)展一個busy信號,當(dāng)狀態(tài)機(jī)未工作完成的時候,反壓上游模塊,告訴上游模塊不能再發(fā)。busy信號可以可以通過狀態(tài)機(jī)的IDLE狀態(tài)來生成。

`timescale 1ns / 1ns module uart_tx_multibyte(
 clk      , //時鐘 rst_n    , //復(fù)位 data_n   , //要發(fā)送的多字節(jié)數(shù)據(jù) trans_go , //發(fā)送使能 uart_tx //串口發(fā)送數(shù)據(jù) ); parameter IDLE     = 3'b001; //空閑狀態(tài) parameter S1       = 3'b010; //準(zhǔn)備發(fā)送數(shù)據(jù)狀態(tài),使能,裝載數(shù)據(jù) parameter S2       = 3'b100; //發(fā)送數(shù)據(jù)狀態(tài) //CNTBY_N字節(jié)數(shù),CNTBY_W字節(jié)數(shù)計數(shù)器的位寬(更改這兩個參數(shù),即可實(shí)現(xiàn)串口任意字節(jié)發(fā)送) parameter CNTBY_N  = 5; //發(fā)送數(shù)據(jù)字節(jié)個數(shù) parameter DATAN_W  = 8*CNTBY_N; //發(fā)送數(shù)據(jù)個數(shù) parameter CNTBY_W  = 3; //發(fā)送數(shù)據(jù)字節(jié)計數(shù)器位寬,5=3'b101 parameter DATA_W   = 8; //一次串行發(fā)送的數(shù)據(jù)個數(shù) parameter STATE_W  = 3; //狀態(tài)機(jī)位寬 input clk; input rst_n; input [DATAN_W-1:0]  data_n; input trans_go; output uart_tx; wire uart_tx; reg [CNTBY_W-1:0]  cnt_bytes; wire add_cnt_bytes; wire end_cnt_bytes; reg cnt_bytes_flag; wire tx_done; reg [DATA_W-1:0]   data; reg send_en; reg [STATE_W-1:0]  state_c; reg [STATE_W-1:0]  state_n; wire IDLE2S1_start; wire S12S2_start; wire S22S1_start ; wire S22IDLE_start ; reg [DATAN_W-1:0]  data_tmp;


my_uart_tx my_uart_tx( .clk (clk), //時鐘 .rst_n (rst_n), //復(fù)位 .data (data), //發(fā)送數(shù)據(jù) .send_en (send_en), //發(fā)送使能 .baud_set (4'd4), //波特率設(shè)置,默認(rèn)9600bps .uart_tx (uart_tx), //串口發(fā)送 .tx_done (tx_done) //發(fā)送完成標(biāo)志位 ); always @(posedge clk or negedge rst_n)begin if(!rst_n)
 cnt_bytes <= 0; else if(add_cnt_bytes)begin if(end_cnt_bytes)
 cnt_bytes <= 0; else cnt_bytes <= cnt_bytes + 1'b1; end end assign add_cnt_bytes = cnt_bytes_flag; assign end_cnt_bytes = add_cnt_bytes && cnt_bytes == CNTBY_N - 1; always @(*)begin if(tx_done)
 cnt_bytes_flag = 1; else cnt_bytes_flag = 0; end //狀態(tài)機(jī) //狀態(tài)轉(zhuǎn)移描述 always @(posedge clk or negedge rst_n)begin if(!rst_n)
 state_c <= IDLE; else state_c <= state_n; end //狀態(tài)轉(zhuǎn)移條件判斷描述 always @(*)begin case(state_c)
 IDLE:begin if(IDLE2S1_start)
 state_n = S1; else state_n = state_c; end S1:begin if(S12S2_start)
 state_n = S2; else state_n = state_c; end S2:begin if(S22S1_start)
 state_n = S1; else if(S22IDLE_start)
 state_n = IDLE; else state_n = state_c; end default:
 state_n = IDLE; endcase end //狀態(tài)轉(zhuǎn)移條件描述 assign IDLE2S1_start =  state_c==IDLE  && trans_go; assign S12S2_start   =  state_c==S1    && send_en; assign S22S1_start   =  state_c==S2    && tx_done && !end_cnt_bytes; assign S22IDLE_start =  state_c==S2    && end_cnt_bytes; //狀態(tài)輸出 always @(posedge clk or negedge rst_n)begin if(!rst_n)
 send_en <= 0; else if(state_c == S1)
 send_en <= 1; else send_en <= 0; end always @(posedge clk or negedge rst_n)begin if(!rst_n)begin data <= 0;
 data_tmp <= 0; end else if(state_c == IDLE)begin data <= 0;
 data_tmp <= data_n; end else if(state_c == S1 && !send_en)begin data <= data_tmp[DATAN_W-1:DATAN_W-8];
 data_tmp <= {data_tmp[DATAN_W-9:0],data_tmp[DATAN_W-1:DATAN_W-8]}; end end endmodule 



UART發(fā)送模塊



module my_uart_tx(
 clk      , //時鐘 rst_n    , //復(fù)位 data     , //發(fā)送數(shù)據(jù) send_en  , //發(fā)送使能 baud_set , //波特率設(shè)置 uart_tx  , //串口發(fā)送 tx_done //發(fā)送完成標(biāo)志位 ); parameter DATA_W   = 8; parameter SET_W    = 3; parameter BYTE_D   = 10; parameter BAUT_W   = 17; parameter BYTE_W   = 4; input clk; input rst_n; input [DATA_W-1:0]   data; input send_en; input [SET_W-1:0]    baud_set; output uart_tx; output tx_done; reg uart_tx; reg tx_done; reg [BAUT_W-1:0]   cnt_baud; reg [BAUT_W-1:0]   baud; wire add_cnt_baud; wire end_cnt_baud; reg [BYTE_W-1:0]   cnt_byte; wire add_cnt_byte; wire end_cnt_byte; reg [BYTE_D-1:0]   uart_data; reg cnt_baud_flag; always @(posedge clk or negedge rst_n)begin if(!rst_n)
 cnt_baud <= 0; else if(add_cnt_baud)begin if(end_cnt_baud)
 cnt_baud <= 0; else cnt_baud <= cnt_baud + 1'b1; end end assign add_cnt_baud = cnt_baud_flag; assign end_cnt_baud = add_cnt_baud && cnt_baud == baud - 1; always @(posedge clk or negedge rst_n)begin if(!rst_n)
 cnt_byte <= 0; else if(add_cnt_byte)begin if(end_cnt_byte)
 cnt_byte <= 0; else cnt_byte <= cnt_byte + 1'b1; end end assign add_cnt_byte = end_cnt_baud; assign end_cnt_byte = add_cnt_byte && cnt_byte == BYTE_D - 1; always @(posedge clk or negedge rst_n)begin if(!rst_n)
 uart_tx <= 1; else if(cnt_baud == 0 && add_cnt_baud)
 uart_tx <= uart_data[cnt_byte]; end always @(posedge clk or negedge rst_n)begin if(!rst_n)
 uart_data <= 10'b0; else if(!cnt_baud_flag && send_en)
 uart_data <= {1'b1,data,1'b0}; end always @(posedge clk or negedge rst_n)begin if(!rst_n)
 cnt_baud_flag <= 0; else if(send_en)
 cnt_baud_flag <= 1; else if(end_cnt_byte)
 cnt_baud_flag <= 0; end always @(*)begin case(baud_set) 3'd0:baud = 17'd83333;//600bps 3'd1:baud = 17'd41666;//1200bps  3'd2:baud = 17'd20833;//2400bps  3'd3:baud = 17'd10416;//4800bps 3'd4:baud = 17'd5208 ;//9600bps  3'd5:baud = 17'd2604 ;//19200bps  3'd6:baud = 17'd1302 ;//38400bps  3'd7:baud = 17'd868 ;//57600bps default:
 baud = 0; endcase end always @(posedge clk or negedge rst_n)begin if(!rst_n)
 tx_done <= 0; else if(end_cnt_byte)
 tx_done <= 1; else tx_done <= 0; end endmodule


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
關(guān)閉