oversmapling
: 수신기에서 신호를 더 정확하게 복구하기 위해 사용되는 기술이다.
비트당 8, 16 등 샘플을 나눠 가운데 샘플의 값을 얻는 방식이다.
→ 샘플링 속도를 원래 신호의 대역폭에 필요한 최소한 샘플링 속도보다 높이는 기술.
잡음, 타이밍 오류를 줄이고 데이터 정확도를 높이는 기술이다.
transmitter
: oversampling bit = br_cnt
START, STOP: br_cnt == 15가 될 때마다 다음 상태로 넘어간다.
DATA : br_cnt == 15가 될 때마다 data의 LSB를 보낸다.
receiver
: oversampling bit = br_cnt
- START : br_cnt == 7이 되면 다음 상태인 DATA로 넘어간다.
- DATA : br_cnt == 15가 되면 다음 tx_data의 1bit를 받고 저장한다. 8개의 bit를 모두 받으면 STOP 상태로 넘어간다.
- STOP : br_cnt == 15가 되면 IDLE 상태로 넘어간다.
uart .v
`timescale 1ns / 1ps
module uart ( // PC
input clk,
input reset,
// Transmitter
output tx,
input start,
input [7:0] tx_data,
output tx_done,
// Receiver
input rx,
output [7:0] rx_data,
output rx_done
);
wire w_br_tick;
baudrate_generator U_BAUDRATE_GEN (
.clk(clk),
.reset(reset),
.br_tick(w_br_tick)
);
transmitter U_Transmitter (
.clk(clk),
.reset(reset),
.br_tick(w_br_tick),
.start(start),
.tx_data(tx_data),
.tx(tx),
.tx_done(tx_done)
);
receiver U_Receiver (
.clk(clk),
.reset(reset),
.br_tick(w_br_tick),
.rx(rx),
.rx_data(rx_data),
.rx_done(rx_done)
);
endmodule
module baudrate_generator (
input clk,
input reset,
output br_tick
);
// 16 bit sampling -> baudrate 16 times
reg [$clog2(100_000_000 / 9600 / 16)-1 : 0] counter_reg, counter_next;
reg tick_reg, tick_next;
assign br_tick = tick_reg;
always @(posedge clk, posedge reset) begin
if (reset) begin
counter_reg <= 0;
tick_reg <= 1'b0;
end else begin
counter_reg <= counter_next;
tick_reg <= tick_next;
end
end
always @(*) begin
counter_next = counter_reg;
if (counter_reg == 100_000_000 / 9600 / 16 - 1) begin
//if (counter_reg == 3) begin // for simulation
counter_next = 0;
tick_next = 1'b1;
end else begin
counter_next = counter_reg + 1;
tick_next = 1'b0;
end
end
endmodule
module transmitter (
input clk,
input reset,
input br_tick,
input start,
input [7:0] tx_data,
output tx,
output tx_done
);
localparam IDLE = 0, START = 1, DATA = 2, STOP = 3;
reg [1:0] state, state_next;
reg tx_reg, tx_next;
reg tx_done_reg, tx_done_next;
reg [7:0] data_tmp_reg, data_tmp_next;
reg [3:0] br_cnt_reg, br_cnt_next;
reg [2:0] data_bit_cnt_reg, data_bit_cnt_next;
assign tx = tx_reg;
assign tx_done = tx_done_reg;
always @(posedge clk, posedge reset) begin
if (reset) begin
state <= IDLE;
tx_reg <= 1'b0;
br_cnt_reg <= 0;
data_bit_cnt_reg <= 0;
data_tmp_reg <= 0;
tx_done_reg <= 1'b0;
end else begin
state <= state_next;
tx_reg <= tx_next;
br_cnt_reg <= br_cnt_next;
data_bit_cnt_reg <= data_bit_cnt_next;
data_tmp_reg <= data_tmp_next;
tx_done_reg <= tx_done_next;
end
end
always @(*) begin
state_next = state;
data_tmp_next = data_tmp_reg;
tx_next = tx_reg;
br_cnt_next = br_cnt_reg;
data_bit_cnt_next = data_bit_cnt_reg;
tx_done_next = tx_done_reg;
case (state)
IDLE: begin
tx_done_next = 1'b0;
tx_next = 1'b1;
if (start) begin
state_next = START;
data_tmp_next = tx_data;
br_cnt_next = 0; // baud rate 16bit sampling
data_bit_cnt_next = 0;
end
end
START: begin
tx_next = 1'b0;
if (br_tick) begin
if (br_cnt_reg == 15) begin
state_next = DATA;
br_cnt_next = 0;
end else begin
br_cnt_next = br_cnt_reg + 1;
end
end
end
DATA: begin
tx_next = data_tmp_reg[0];
if (br_tick) begin
if (br_cnt_reg == 15) begin
if (data_bit_cnt_reg == 7) begin
state_next = STOP;
br_cnt_next = 0;
end else begin
data_bit_cnt_next = data_bit_cnt_reg + 1;
data_tmp_next = {1'b0, data_tmp_reg[7:1]};
br_cnt_next = 0;
end
end else begin
br_cnt_next = br_cnt_reg + 1;
end
end
end
STOP: begin
tx_next = 1'b1;
if (br_tick) begin
if (br_cnt_reg == 15) begin
tx_done_next = 1'b1;
state_next = IDLE;
end else begin
br_cnt_next = br_cnt_reg + 1;
end
end
end
endcase
end
endmodule
module receiver (
input clk,
input reset,
input br_tick,
input rx,
output [7:0] rx_data,
output rx_done
);
localparam IDLE = 0, START = 1, DATA = 2, STOP = 3;
reg [1:0] state, state_next;
reg [7:0] rx_data_reg, rx_data_next;
reg rx_done_reg, rx_done_next;
reg [3:0] br_cnt_reg, br_cnt_next;
reg [2:0] data_bit_cnt_reg, data_bit_cnt_next;
assign rx_data = rx_data_reg;
assign rx_done = rx_done_reg;
always @(posedge clk, posedge reset) begin
if (reset) begin
state <= IDLE;
rx_data_reg <= 0;
rx_done_reg <= 1'b0;
br_cnt_reg <= 0;
data_bit_cnt_reg <= 0;
end else begin
state <= state_next;
rx_data_reg <= rx_data_next;
rx_done_reg <= rx_done_next;
br_cnt_reg <= br_cnt_next;
data_bit_cnt_reg <= data_bit_cnt_next;
end
end
always @(*) begin
state_next = state;
br_cnt_next = br_cnt_reg;
data_bit_cnt_next = data_bit_cnt_reg;
rx_data_next = rx_data_reg;
rx_done_next = rx_done_reg;
case (state)
IDLE: begin
rx_done_next = 1'b0;
if (rx == 1'b0) begin
br_cnt_next = 0;
data_bit_cnt_next = 0;
rx_data_next = 0;
state_next = START;
end
end
START: begin
if (br_tick) begin
if (br_cnt_reg == 7) begin
br_cnt_next = 0;
state_next = DATA;
end else begin
br_cnt_next = br_cnt_reg + 1;
end
end
end
DATA: begin
if (br_tick) begin
if (br_cnt_reg == 15) begin
br_cnt_next = 0;
rx_data_next = {rx, rx_data_reg[7:1]};
if (data_bit_cnt_reg == 7) begin
state_next = STOP;
br_cnt_next = 0;
end else begin
data_bit_cnt_next = data_bit_cnt_reg + 1;
end
end else begin
br_cnt_next = br_cnt_reg + 1;
end
end
end
STOP: begin
if (br_tick) begin
if (br_cnt_reg == 15) begin
br_cnt_next = 0;
rx_done_next = 1'b1;
state_next = IDLE;
end else begin
br_cnt_next = br_cnt_reg + 1;
end
end
end
endcase
end
endmodule
top_txrx_loop
`timescale 1ns / 1ps
module top_txrx_loop(
input clk,
input reset,
// Transmitter
output tx,
// Receiver
input rx
);
wire [7:0] w_rx_data;
wire w_rx_done;
uart U_UART( // PC
.clk(clk),
.reset(reset),
// Transmitter
.tx(tx),
.start(w_rx_done),
.tx_data(w_rx_data),
.tx_done(),
// Receiver
.rx(rx),
.rx_data(w_rx_data),
.rx_done(w_rx_done)
);
endmodule
tb_uart
`timescale 1ns / 1ps
module tb_uart();
reg clk;
reg reset;
// Transmitter
wire tx;
reg start;
reg [7:0] tx_data;
wire tx_done;
// Receiver
reg rx;
wire [7:0] rx_data;
wire rx_done;
/*
uart dut(
.clk(clk),
.reset(reset),
.tx(tx),
.start(start),
.tx_data(tx_data),
.tx_done(tx_done),
.rx(rx), // loop test
.rx_data(rx_data),
.rx_done(rx_done)
);*/
// loop test
wire w_tx_rx;
uart dut(
.clk(clk),
.reset(reset),
.tx(w_tx_rx),
.start(start),
.tx_data(tx_data),
.tx_done(tx_done),
.rx(w_tx_rx), // loop test
.rx_data(rx_data),
.rx_done(rx_done)
);
always #5 clk = ~clk;
initial begin
clk = 1'b0;
reset = 1'b1;
start = 1'b0;
rx = 1'b1;
end
initial begin
#20 reset = 1'b0;
#100 tx_data = 8'b11000101; start = 1'b1;
#10 start = 1'b0;
end
endmodule
schematic
simulation
constraint
## Clock signal
set_property -dict { PACKAGE_PIN W5 IOSTANDARD LVCMOS33 } [get_ports { clk }]; #IO_L12P_T1_MRCC_34 ,Sch=CLK100MHZ
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk]
##7 segment display
set_property -dict { PACKAGE_PIN W7 IOSTANDARD LVCMOS33 } [get_ports { switch }]; #IO_L13P_T2_MRCC_34 ,Sch=CA
##Buttons
set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { reset }]; #IO_L18N_T2_A11_D27_14 ,Sch=BTNC
##USB-RS232 Interface
set_property -dict { PACKAGE_PIN B18 IOSTANDARD LVCMOS33 } [get_ports { rx }]; #IO_L19P_T3_16 ,Sch=UART_RXD_IN
set_property -dict { PACKAGE_PIN A18 IOSTANDARD LVCMOS33 } [get_ports { tx }]; #IO_L19N_T3_VREF_16 ,Sch=UART_TXD_OUT
video
'[하만]세미콘 아카데미 > verilog' 카테고리의 다른 글
0521 system verilog, adder.sv (0) | 2024.07.09 |
---|---|
0520 uart_led (0) | 2024.07.09 |
0517 uart_tx_rx (0) | 2024.06.22 |
0517 uart_tx (0) | 2024.06.22 |
0516 UART (0) | 2024.06.22 |