# 軟硬體協同設計HW6
### ● 作業標題:7-Seg Display controlled by UART
### ● 班級姓名座號:國立高雄大學電機系大四 B1095117 黃致衡
### ● 授課老師:林宏益教授
---
## 一、作業內容:
###
撰寫具有 UART 通訊協定中能進行 RX 功能的模組。
## 二、實作步驟:
### 1. 撰寫除頻器的 RTL code (clk_div.v)
```
module clk_div
(
input clk,
input rst_n,
output reg clkout
);
parameter BAUDRATE = 9600;
parameter DIV_NUMBER = 125000000 / BAUDRATE;
reg [13:0] num = 0;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
num <= 0;
clkout <= 0;
end
else
if(num == DIV_NUMBER-1)
begin
num <= 0;
clkout <= 1;
end
else
begin
num <= num+1;
clkout <= 0;
end
end
endmodule
```
### 2. 再撰寫除頻器的 Testbench (clk_div_tb.v)
```
`timescale 1ns / 1ps
module clk_div_tb;
reg tb_clk, tb_rst_n;
wire clkout;
parameter clk_duration = 8;
initial
begin
$dumpfile("test.vcd");
$dumpvars;
end
initial
begin
tb_clk = 1'b1;
tb_rst_n = 1'b0;
#20 tb_rst_n = 1'b1;
#20 tb_rst_n = 1'b0;
#5_000_000 $finish;
end
always #(clk_duration/2) tb_clk = ~tb_clk;
clk_div u_clk_div(.clk(tb_clk), .rst_n(tb_rst_n), .clkout(clkout));
endmodule
```
※模擬結果圖

> 由此可知 DIVISION_NUMBER 大約需設定為 13020,其公式為:
> Clock signal / BAUDRATE。
### 3. 撰寫 UART 中 RX 模組的 RTL code (clk_div.v)
```
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 22:27:09 12/04/2019
// Design Name:
// Module Name: uart_rx
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module uart_rx
(
input clk,
input rst_n,
input rx,
output reg [9:0] data_out
);
// State Machine Defination
parameter IDLE = 2'b01;
parameter SAMP = 2'b10;
// UART Configure Defination
parameter START_BIT = 1;
parameter DATA_BIT = 8;
parameter STOP_BIT = 1;
parameter PARI_BIT = 0;
parameter RECV_BIT = START_BIT + DATA_BIT + STOP_BIT + PARI_BIT;
// Negedge Detection Filter
reg [3:0] data_in;
always @ (posedge clk or negedge rst_n)
if (!rst_n)
begin
data_in[0] <= 1'b0;
data_in[1] <= 1'b0;
data_in[2] <= 1'b0;
data_in[3] <= 1'b0;
end
else
begin
data_in[0] <= rx;
data_in[1] <= data_in[0];
data_in[2] <= data_in[1];
data_in[3] <= data_in[2];
end
wire rx_neg = data_in[3] & data_in[2] & (~data_in[1]) & (~data_in[0]);
reg [1:0] current_state, next_state;
// Current State To Next State
always @ (posedge clk or negedge rst_n)
if(!rst_n)
current_state <= IDLE;
else
current_state <= next_state;
// State
reg sample_finish;
always @(current_state or sample_finish or rx_neg)
begin
next_state = 2'bx;
case(current_state)
IDLE :
begin
if (rx_neg) next_state = SAMP;
else next_state = IDLE;
end
SAMP :
begin
if (sample_finish) next_state = IDLE;
else next_state = SAMP;
end
default : next_state = IDLE;
endcase
end
reg [3:0] recv_cnt;
reg sample_en;
reg [RECV_BIT - 1 : 0] data_temp;
always @ (posedge clk or negedge rst_n)
if (!rst_n)
begin
data_out <= 10'bx;
data_temp <= 10'bx;
sample_finish <= 1'b0;
sample_en <= 1'b0;
recv_cnt <= 4'b0;
end
else
begin
case (next_state)
IDLE:
begin
//data_out <= 10'bx;
data_temp <= 10'bx;
sample_finish <= 1'b0;
sample_en <= 1'b0;
recv_cnt <= 4'b0;
end
SAMP:
begin
if (recv_cnt == RECV_BIT)
begin
data_out <= data_temp;
data_temp <= 10'bx;
sample_finish <= 1'b1;
sample_en <= 1'b0;
recv_cnt <= 4'b0;
end
else
begin
sample_en <= 1'b1;
if (clk)
begin
data_out <= data_out;
data_temp[recv_cnt] <= rx;
sample_finish <= 1'b0;
recv_cnt <= recv_cnt + 1'b1;
end
else
begin
data_out <= data_out;
data_temp <= data_temp;
sample_finish <= sample_finish;
recv_cnt <= recv_cnt;
end
end
end
default:
begin
data_out <= 10'bx;
sample_finish <= 1'b0;
sample_en <= 1'b0;
end
endcase
end
// Sample Counter Signal Generator
parameter BAUD_MAX = 50;
reg [5:0] baud_cnt;
always @ (posedge clk or negedge rst_n)
if (!rst_n)
begin
baud_cnt <= 6'd0;
end
else
begin
if (sample_en)
begin
if (baud_cnt == BAUD_MAX - 1) baud_cnt <= 6'd0;
else baud_cnt <= baud_cnt + 1'b1;
end
else baud_cnt <= 6'd0;
end
// Sample Clock Signal Generator
parameter BAUD_CNT_H = (BAUD_MAX / 2);
wire baud_clk = (baud_cnt == BAUD_CNT_H) ? (1'b1) : (1'b0);
endmodule
```
### 4. 再撰寫 UART 中 RX 模組的 Testbench (uart_tb.v)
```
`timescale 1ns / 1ps
// Company:
// Engineer:
//
// Create Date: 14:03:06 12/05/2019
// Design Name: uart_rx
// Module Name: D:/Xlinx_ISE_Projects/testbench/uart_rx_tb.v
// Project Name: test
// Target Device:
// Tool versions:
// Description:
//
// Verilog Test Fixture created by ISE for module: uart_rx
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
module uart_tb;
// Inputs
reg CLK;
reg RST_N;
reg RX;
// Outputs
wire [9:0] DATA_OUT;
integer i;
initial
begin
$dumpfile("tt.vcd");
$dumpvars(0,uart_tb);
$dumpvars;
//$fsdbDumpfile("test.fsdb");
//$fsdbDumpvars;
end
initial
begin
for(i=0 ; i<=700000 ; i=i+1)
begin
i = i+1;
$display("At time %t, RST_N=%b | RX=%b | data_i=%b", $realtime/1000, RST_N, RX, DATA_OUT);
#200;
end
end
always #1 CLK = ~CLK;
initial
begin
// Initialize Inputs
CLK = 0;
RST_N = 0;
RX = 1;
// Wait 100 ns for global reset to finish
#100;
// Add stimulus here
RST_N = 1;
#100;
// Generate Start bit
#200 RX = 1'b0;
// 8 data bits
#200 RX = 1'b1;
#200 RX = 1'b0;
#200 RX = 1'b1;
#200 RX = 1'b0;
#200 RX = 1'b0;
#200 RX = 1'b0;
#200 RX = 1'b0;
#200 RX = 1'b0;
// Generate Stop bit
#200 RX = 1'b1;
#600;
// Generate Start bit
#200 RX = 1'b0;
// 8 data bits
#200 RX = 1'b1;
#200 RX = 1'b1;
#200 RX = 1'b1;
#200 RX = 1'b0;
#200 RX = 1'b0;
#200 RX = 1'b1;
#200 RX = 1'b1;
#200 RX = 1'b1;
// Generate Stop bit
#200 RX = 1'b1;
#20000 $finish;
end
// Instantiate the Unit Under Test (UUT)
uart_rx U_uart_rx
(
.clk(CLK),
.rst_n(RST_N),
.rx(RX),
.data_out(DATA_OUT)
);
endmodule
```
※模擬結果圖


> 由此可見在 testbench 中產生了兩組 data_out 的值,LSB 的 0 代表通知 RX 為 start bit,而 MSB 的 1 代表通知 RX 為 end bit。
>中間夾住的 8bits 則為需要傳送的訊號內容,由右至左判讀。