既上一篇我們設計了 Uart_TX 的狀態機,我們今天要來引用狀態機模塊來實現這個 Uart_TX 的模塊。
先來看看這個模塊該有哪些輸入輸出腳:
輸入:
輸出:
module usage_Uart_TX(
clk_50M,
reset_n,
write,
write_value,
uart_txd,
busy
);
/*--------ports declarations--------*/
input clk_50M;
input write;
input reset_n;
input [7:0] write_value;
output uart_txd;
output busy;
wire uart_txd;
wire busy;
宣告變數:
需要用到的變數有:
/*---------variables---------*/
reg [7:0] regdata;
reg [2:0] counter;
reg [12:0] cnt_9600;
reg tick_uart;
wire TX_D;
wire LDEN;
wire SHEN;
wire rstcount;
wire countEN;
引用狀態機模組
/*---------Uart_TX instantiation---------*/
Uart_TX U0(
.clk_50M(clk_50M),
.rst_n(reset_n),
.count(counter),
.rstcount(rstcount),
.countEN(countEN),
.tick_uart(tick_uart),
.TX_D(TX_D),
.LDEN(LDEN),
.SHEN(SHEN),
.en(write),
.busy(busy)
);
cnt_9600 & tick_uart:
因為我是以鮑率 9600 為主,所以需除出 9600 HZ,首先,輸入頻率為 50MHZ,50M/9600 = 5208.333,取 5208,因此我們要每計數到 5207(因為0 ~ 5207 就會數 5208 次)就產生一個 clk 的 tick
/*---------9600HZ counter---------*/
always@(posedge clk_50M or negedge reset_n)begin
if(!reset_n)cnt_9600 <= 13'd0;
else begin
if(cnt_9600<13'd5207)begin
cnt_9600 <= cnt_9600 + 13'd1;
tick_uart <= 1'b0;
end
else begin
cnt_9600 <= 13'd0;
tick_uart <= 1'b1;
end
end
end
靠 rstcount&countEN 來控制 counter
/*---------counter---------*/
always@(posedge clk_50M or negedge reset_n)begin
if(!reset_n)counter <= 3'd0;
else begin
if(tick_uart==1'b1)begin
if(rstcount) counter <= 3'd0;
else if(countEN)counter <= counter + 3'd1;
else counter <= counter;
end
else counter <= counter;
end
end
if(tick_uart==1'b1) 是因為一個 count 要待滿一個鮑率的時間週期。
靠 LDEN&SHEN 來控制我們的 regdata
/*---------write_value---------*/
always@(posedge clk_50M or negedge reset_n)begin
if(!reset_n)regdata <= 8'd0;
else begin
if(tick_uart==1'b1)begin
if(LDEN) regdata <= write_value;
else if(SHEN)regdata <= regdata>>1;
else regdata <= regdata;
end
else regdata <= regdata;
end
end
endmodule
regdata>>1 這邊右移是因 uart 是 LSB 先傳。
最後的最後
要在非 SHIFT 狀態時 tick_uart 切到狀態機的 TX_D,而在 SHIFT 狀態時切回 regdata 的 LSB。
/*---------assign wire---------*/
assign uart_txd = (SHEN)?(regdata[0]):(TX_D);
來看看 quartus 的 State Machine Viewer 有沒有符合自己的預期
大家可以試著自己寫看看 testbench 來測試結果正不正確~~
那麼到這邊我們就完成了 Uart_TX 的實作了唷~