## 7-Seg Display Controlled by UART實驗報告 ### B1095165 黃瑄凱 指導教授:林宏益 ## 一、實驗目的 >使用者輸入0~9, A~F, 七段顯示器顯示該數字/文字。 > >使用者輸入其他數字/文字,七段顯示器顯示E。 ## 二、實驗原理 ### 原理: (參考文獻1中有更詳細的說明) #### UART重點 起始位(Start Bit):在每個數據帧開始時,UART發送一個邏輯“0”的信號,表示傳輸字符開始。 數據位(Data Bits):緊隨在起始位後面,數據位的個數可以是4、5、6、7、8等,構成一個字符。 奇偶校驗位(Parity Bit):用於校驗數據傳輸的正確性,使得數據位中“1”的位數為偶數或奇數,以校驗數據的準確性。 停止位(Stop Bit):標識一個字符數據的結束,可以是1位、1.5位或2位的高電平。同時也提供計算機校正時鐘同步的機會。 #### 工作原理 發送數據過程:在空閒狀態下(線路處於高電平),發送端拉低線路一個數據位的時間,按照約定的波特率從低位到高位依次發送數據,發送完畢後,發送校驗位和停止位,一幀數據發送完成。 接收數據過程:在檢測到線路下降沿(高電平變為低電平)時,開始接收數據。從低位到高位接收數據,並進行校驗,確認正確性後通知接收設備或存入緩衝。 工作圖 ![20212201752227667](https://hackmd.io/_uploads/BJlzT4QIa.bmp) [圖片來源](https://www.ebyte.com/new-view-info.aspx?id=1390) ## 三、實驗材料: * Verilog HDL程式碼 * Testbench * 電路示意圖 * VCS編譯器 ## 四、實驗步驟: 1.編寫Verilog HDL程式碼,包括數字轉換和重置功能。 2.創建相應的Testbench來驗證設計的正確性。 3.使用VCS編譯器進行合成。 ## 五、實驗結果: * Verilog HDL程式碼-Top.module ``` `timescale 1ns / 1ps module UART_Data_Processor( input clk, input rst, input rx_pin_in, output [7:0] seg7 ); wire rx_pin_H2L; Edge_Detector rx_in_detect( .clk( clk ), .rst( rst ), .pin_in( rx_pin_in ), .sig_H2L( rx_pin_H2L ) ); wire rx_band_sig; wire clk_bps; Baud_Rate_Generator rx_baud_gen( .clk( clk ), .rst( rst ), .band_sig( rx_band_sig ), .clk_bps( clk_bps ) ); wire [7:0] rx_data; UART_Control_Unit rx_control( .clk( clk ), .rst( rst ), .rx_pin_in( rx_pin_in ), .rx_pin_H2L( rx_pin_H2L ), .rx_band_sig( rx_band_sig ), .rx_clk_bps( clk_bps ), .rx_data( rx_data ), .rx_done_sig( rx_done_sig ) ); ASCII_to_7seg u_ASCII2seg7( .rst( rx_done_sig ), .ASCII( rx_data ), .seg7_out(seg7) ); endmodule ``` * Verilog HDL程式碼-H2L Signal detect ``` `timescale 1ns / 1ps module Edge_Detector( input clk, input rst, input pin_in, output sig_H2L ); reg pin_pre; assign sig_H2L = !pin_in & pin_pre; always @( posedge clk or posedge rst ) if( rst ) pin_pre <= 1'b0; else pin_pre <= pin_in; endmodule ``` * Verilog HDL程式碼-generator ``` `timescale 1ns / 1ps module Baud_Rate_Generator( input clk, input rst, input band_sig, output reg clk_bps ); parameter SYS_RATE = 125000000; parameter BAND_RATE = 9600; //此處使用9600 parameter CNT_BAND = SYS_RATE / BAND_RATE; parameter HALF_CNT_BAND = CNT_BAND / 2; reg [13:0] cnt_bps; always @( posedge clk or posedge rst ) if( rst ) begin cnt_bps <= HALF_CNT_BAND; clk_bps <= 1'b0; end else if( !band_sig ) begin cnt_bps <= HALF_CNT_BAND; clk_bps <= 1'b0; end else if( cnt_bps == CNT_BAND ) begin cnt_bps <= 14'd0; clk_bps <= 1'b1; end else begin cnt_bps <= cnt_bps + 1'b1; clk_bps <= 1'b0; end endmodule ``` * Verilog HDL程式碼-Control ``` `timescale 1ns / 1ps module UART_Control_Unit ( input clk, input rst, input rx_pin_in, input rx_pin_H2L, output reg rx_band_sig, input rx_clk_bps, output reg [7:0] rx_data, output reg rx_done_sig ); localparam [3:0] IDLE = 4'd0, BEGIN = 4'd1, DATA0 = 4'd2, DATA1 = 4'd3, DATA2 = 4'd4, DATA3 = 4'd5, DATA4 = 4'd6, DATA5 = 4'd7, DATA6 = 4'd8, DATA7 = 4'd9, END = 4'd10, BFREE = 4'd11; reg [3:0] pos; always @(posedge clk or posedge rst) if (rst) begin rx_band_sig <= 1'b0; rx_data <= 8'd0; pos <= IDLE; rx_done_sig <= 1'b0; end else begin case (pos) IDLE: if (rx_pin_H2L) begin rx_band_sig <= 1'b1; pos <= pos + 1'b1; rx_data <= 8'd0; end BEGIN: if (rx_clk_bps) begin if (rx_pin_in == 1'b0) begin pos <= pos + 1'b1; end else begin rx_band_sig <= 1'b0; pos <= IDLE; end end DATA0, DATA1, DATA2, DATA3, DATA4, DATA5, DATA6, DATA7: if (rx_clk_bps) begin rx_data[pos - DATA0] <= rx_pin_in; pos <= pos + 1'b1; end END: if (rx_clk_bps) begin rx_done_sig <= 1'b1; pos <= pos + 1'b1; rx_band_sig <= 1'b0; end BFREE: begin rx_done_sig <= 1'b0; pos <= IDLE; end endcase end endmodule ``` * Verilog HDL程式碼-ASCII 7-seg signal ``` module ASCII_to_7seg ( input rst, input [7:0] ASCII, output reg [7:0] seg7_out ); always @* begin case (ASCII) 8'b0011_0000: seg7_out <= 8'b00000011; 8'b0011_0001: seg7_out <= 8'b10011111; 8'b0011_0010: seg7_out <= 8'b00100101; 8'b0011_0011: seg7_out <= 8'b00001101; 8'b0011_0100: seg7_out <= 8'b10011001; 8'b0011_0101: seg7_out <= 8'b01001001; 8'b0011_0110: seg7_out <= 8'b01000001; 8'b0011_0111: seg7_out <= 8'b00011111; 8'b0011_1000: seg7_out <= 8'b00000001; 8'b0011_1001: seg7_out <= 8'b00001001; 8'b0100_0001: seg7_out <= 8'b00010001; 8'b0100_0010: seg7_out <= 8'b11000001; 8'b0100_0011: seg7_out <= 8'b11100101; 8'b0100_0100: seg7_out <= 8'b10000101; 8'b0100_0101: seg7_out <= 8'b01100001; 8'b0100_0110: seg7_out <= 8'b01110001; default: seg7_out <= 8'b01100001; endcase end endmodule ``` * Verilog HDL程式碼-Testbench ``` `timescale 1ns / 1ps module rx_top_tb(); reg clk; reg rst; reg uart_rx; wire [7:0] seg7; integer i; reg [7:0] data_test = 8'h41; UART_Data_Processor u_rx_top( .clk(clk), .rst(rst), .rx_pin_in(uart_rx), .seg7(seg7) ); initial begin $dumpfile("rx_top.vcd"); $dumpvars; end initial begin clk = 0; for (i = 0; i < 256; i = i + 1) begin rst = 1; #15 rst = 0; uart_rx = 1; // 起始位 #104167 uart_rx = 0; // 數據 #104167 uart_rx = data_test[0]; #104167 uart_rx = data_test[1]; #104167 uart_rx = data_test[2]; #104167 uart_rx = data_test[3]; #104167 uart_rx = data_test[4]; #104167 uart_rx = data_test[5]; #104167 uart_rx = data_test[6]; #104167 uart_rx = data_test[7]; // 停止 #104167 uart_rx = 1; #104167 uart_rx = 1; #104167 uart_rx = 1; #104167 uart_rx = 1; #104167 uart_rx = 1; #104167 uart_rx = 1; #104167 uart_rx = 1; data_test = data_test + 1; end #50 $finish; end always #4 clk = ~clk; //此處一定要用4,不能用10 endmodule ``` * Testbench模擬結果 ![實驗結果](https://hackmd.io/_uploads/B1XAA4mL6.jpg) * 電路圖 ![實驗結果2](https://hackmd.io/_uploads/ryzXyB78a.jpg) * Coverage * Lint ![Coverage](https://hackmd.io/_uploads/SkHmMSd86.jpg) * 實驗影片 [7-seg Display controlled bu UART](https://youtu.be/rr6zHzBjJdw) ## 六、實驗討論: 這次實驗中遇到最大的問題莫過於是wave圖沒有輸入訊號,後來和同學討論才知道Testbench中有著許多問題,uart. Baud rate我設定的值為9600,起初#的數值快到30000後來改成104167還是有許多問題。最後發現我設定125000000如果delay用10ns切一次會產生問題,後來改成4ns就把問題解決掉了。 ## 七、實驗心得: 這次實驗相比前幾次十分的困難,我們需要撰寫的.v檔已經不是一個就能解決,要透過一個top包許多檔案才能完成我們的code,而這次我也遇到了許多bug,一開始simulation看到20幾個error,到最後能產生結果的成就感是相當巨大的。也非常慶幸網路上有許多資料能夠參考,才讓我得以順利完成這份作業。 ## 八、參考文獻: 1.[徐晓康. (2022, December 1). Verilog功能模块——Uart收发. CSDN博客.](https://blog.csdn.net/weixin_42837669/article/details/127772676) 2.[YodaLee. (2021, September 5). Open FPGA 系列 - UART.](https://yodalee.me/2021/09/openfpga_uart/) 3.課堂講義 ## 九、實驗成果: [7-seg Display controlled bu UART](https://youtu.be/rr6zHzBjJdw)