Internal Loop-Back : 이전에 설계했던 SimpleUartTx 의 ASCII code 'X' 를 Rx 가 제대로 수신하는지만 확인한다. (Simulation Only)
Clk : DE1 - SoC Board 의 default freqency 는 50Mhz 로 20ns 의 Clock Period 를 가진다. Bit Rate 115200bps 를 만족하기 위해선 1 Bit 를 전송할 때, 8680ns 가 필요하고 20ns 의 주기가 434 cycles 유지되어야 한다.
f_det : Uart 는 기본적으로 IDLE 과 STOP 에서 1, START 에서 0 의 값을 가진다. Clock Signal 이 존재하는 않는 Asychronous system 에서 Data 의 송수신이 이뤄지기 위해 START 와 STOP 이 필요하고 START 를 알리는 F_det 을 설계했다.
Cap : Tx 에서 전송된 DATA 를 안정적으로 받기 위해 DATA 의 중간 값을 Capture 한다. 이를 위해 START 에서 20ns 의 주기를 217 cycles 동안 유지하고 (4340ns) MID 상태를 추가했다. (clk_count == 216) 에서 Tx_cst 의 mid 값을 capture 하고 Rx_cst 는 다음 state 로 이동한다.
Data bit : 217 cycles 이 지나면 start bit capture (#4340), 이후에는 동일하게 434 count 를 진행하면서 d0, d1 ~ d7 를 capture 한다.
module simple_uart_rx(
input clk,
input reset_n,
input rx,
output reg [7:0] rx_data
);
localparam idle = 0,
start = 1,
mid = 2,
d0 = 3,
d1 = 4,
d2 = 5,
d3 = 6,
d4 = 7,
d5 = 8,
d6 = 9,
d7 = 10,
stop = 11,
stop_1 = 12;
reg rx_delay1, rx_delay2;
reg [3:0] cst = 0;
reg [3:0] nst;
reg [8:0] clk_count = 9'd0;
wire bit_clr = (clk_count == 433);
wire bit_cap = ((clk_count == 216) && (cst == start));
// capture mid value in start state
// falling edge detected
always @(posedge clk, negedge reset_n) begin
if(!reset_n) begin
rx_delay1 <= 0;
rx_delay2 <= 0;
end
else begin
rx_delay1 <= rx;
rx_delay2 <= rx_delay1;
end
end
assign f_det = ~rx_delay1 & rx_delay2;
// 217, 434 clk counter
always @(posedge clk, negedge reset_n) begin
if(!reset_n) begin
clk_count <= 9'd0;
end
else if((f_det && (cst == idle)) || bit_clr || bit_cap) begin
clk_count <= 9'd0;
end
else begin
clk_count <= clk_count + 9'd1;
end
end
// state variation
always @(posedge clk, negedge reset_n) begin
if(!reset_n) begin
cst <= idle;
end
else if(f_det && (cst == idle)) begin
// line 60 : if f_det is '1' in idle state, move to start state
cst <= start;
end
else if(!f_det && (cst == idle)) begin
// line 63: keep its idle state if f_det is not '1'
cst <= idle;
end
else if(bit_clr || bit_cap) begin // bit_cap : idle -> start
cst <= nst; // bit_clr
end
end
// next state
always @(*) begin
case (cst)
idle : nst = idle; // line 63
start : nst = mid; // line 60
mid : nst = d0;
d0 : nst = d1;
d1 : nst = d2;
d2 : nst = d3;
d3 : nst = d4;
d4 : nst = d5;
d5 : nst = d6;
d6 : nst = d7;
d7 : nst = stop;
stop : nst = stop_1;
default: nst = idle;
endcase
end
// output
always @(posedge clk, negedge reset_n) begin
if (!reset_n)
rx_data = 9'd0;
else if (clk_count == 9'd0) begin
// moore machine, prevent value changes in rx cst
case (cst)
d0 : rx_data[0] = rx;
d1 : rx_data[1] = rx;
d2 : rx_data[2] = rx;
d3 : rx_data[3] = rx;
d4 : rx_data[4] = rx;
d5 : rx_data[5] = rx;
d6 : rx_data[6] = rx;
d7 : rx_data[7] = rx;
endcase
end
end
endmodule
`include "../simple_uart_rx/simple_uart_rx.v"
`include "../simple_uart_tx/simple_uart_tx.v"
module simple_uart(
input clk,
input reset_n,
output [7:0] rx_data
);
wire w_uart;
simple_uart_tx uSimple_uart_tx_0(
.clk(clk),
.reset_n(reset_n),
.tx(w_uart)
);
simple_uart_rx uSimple_uart_rx_0(
.clk(clk),
.reset_n(reset_n),
.rx(w_uart),
.rx_data(rx_data)
);
endmodule
`timescale 1 ns / 1 ns
module simple_uart_tb();
reg clk;
reg reset_n;
wire [7:0] rx_data;
simple_uart uSimple_uart(
.clk(clk),
.reset_n(reset_n),
.rx_data(rx_data)
);
initial begin
clk = 1'b1;
forever #10 clk = ~clk;
end
initial begin
reset_n = 1'b1;
end
endmodule
Data 8bit 를 받은 후에, ASCII 'X' 를 출력하고 Value 를 유지한다.
hex : 0x58
// tcl file
vlib work
vlog simple_uart.v simple_uart_tb.v
vsim simple_uart_tb
view wave
add wave -radix bin /clk
add wave -radix unsigned /uSimple_uart/uSimple_uart_rx_0/clk_count
add wave -radix bin /reset_n
add wave -radix bin /uSimple_uart/uSimple_uart_tx_0/tx
add wave -radix unsigned /uSimple_uart/uSimple_uart_tx_0/cst
add wave -radix bin /uSimple_uart/uSimple_uart_rx_0/rx
add wave -radix bin /uSimple_uart/uSimple_uart_rx_0/f_det
add wave -radix unsigned /uSimple_uart/uSimple_uart_rx_0/cst
add wave -radix bin /rx_data
run 130 us
'[Harman] 반도체 설계 > Quartus' 카테고리의 다른 글
Quartus II project - Uart Rx Segment [2]. (0) | 2023.08.19 |
---|---|
Quartus II project - Uart Rx Segment [1]. (0) | 2023.08.17 |
Quartus II Project - Falling Edge Detection. (0) | 2023.08.15 |
Quartus II Project - notes [2] (0) | 2023.08.13 |
Quartus II project - notes [1] (0) | 2023.08.12 |