[VerilogHDL] UART Tx(2)VerilogHDL/Study2024. 5. 22. 00:26
Table of Contents
1. UART(Tx v.2)
- 8개 state를 만들지 않고 baudrate tick에 한번씩 data 1bit씩 전송
구현
더보기
`timescale 1ns / 1ps
module uart (
input clk,
input reset,
input tx_start,
input [7:0] tx_data,
output tx,
output tx_done
);
wire w_br_tick;
baudrate_generator #(
.HERZ(9600)
) U_BR_Gen (
.clk (clk),
.reset(reset),
.br_tick(w_br_tick)
);
transmitter U_TxD (
.clk(clk),
.reset(reset),
.tx_start(tx_start),
.br_tick(w_br_tick),
.tx_data(tx_data),
.tx(tx),
.tx_done(tx_done)
);
endmodule
module baudrate_generator #(
parameter HERZ = 9600
) (
input clk,
input reset,
output br_tick
);
// reg [$clog2(100_000_000/9600)-1:0] counter_reg, counter_next;
reg [$clog2(100_000_000/HERZ)-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 - 1) begin // baudrate 9600Hz
if (counter_reg == 100_000_000 / HERZ - 1) begin
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 tx_start,
input br_tick,
input [7:0] tx_data,
output tx,
output tx_done
);
localparam IDLE = 0, START = 1, DATA = 2, STOP = 3;
reg [7:0] tx_data_reg, tx_data_next;
reg [1:0] state, state_next;
reg [2:0] bit_cnt_reg, bit_cnt_next;
reg tx_reg, tx_next, tx_done_reg, tx_done_next;
// state rigister
always @(posedge clk, posedge reset) begin
if (reset) begin
state <= IDLE;
tx_data_reg <= 7'b0;
bit_cnt_reg <= 3'd0;
tx_reg <= 1'b1;
tx_done_reg <= 1'b0;
end else begin
state <= state_next;
tx_data_reg <= tx_data_next;
bit_cnt_reg <= bit_cnt_next;
tx_reg <= tx_next;
tx_done_reg <= tx_done_next;
end
end
// next state logic
always @(*) begin
state_next = state;
tx_done_next = tx_done_reg;
tx_data_next = tx_data_reg;
tx_next = tx_reg;
bit_cnt_next = bit_cnt_reg;
case (state)
IDLE: begin
tx_next = 1'b1;
tx_done_next = 1'b0;
if (tx_start) begin
tx_data_next = tx_data;
bit_cnt_next = 0;
state_next = START;
end
end
START: begin
tx_next = 1'b0;
if (br_tick) state_next = DATA;
end
DATA: begin
tx_next = tx_data_reg[0];
if (br_tick) begin
if (bit_cnt_reg == 7) begin
state_next = STOP;
end else begin
bit_cnt_next = bit_cnt_reg + 1;
tx_data_next = {1'b0, tx_data_reg[7:1]};
// right shift register(bit right shift)
end
end
end
STOP: begin
tx_next = 1'b1;
if (br_tick) begin
state_next = IDLE;
tx_done_next = 1'b1;
end
end
endcase
end
// output logic
assign tx = tx_reg;
assign tx_done = tx_done_reg;
endmodule
위 그림과 같이 입력 값의 LSB를 출력 값에 넣고 → right shift → LSB를 출력 값 대입(입력 값의 두번째 비트) → 반복
Simulation
더보기
`timescale 1ns / 1ps
module tb_uart();
reg clk;
reg reset;
reg tx_start;
reg [7:0] tx_data;
wire tx;
wire tx_done;
uart dut (
.clk(clk),
.reset(reset),
.tx_start(tx_start),
.tx_data(tx_data),
.tx(tx),
.tx_done(tx_done)
);
always #5 clk = ~clk;
initial begin
clk = 1'b0;
reset = 1'b1;
tx_start = 1'b0;
tx_data = 0;
end
initial begin
#100 reset = 1'b0;
#100 tx_data = 8'b11001010; tx_start = 1'b1;
#10 tx_start = 1'b0;
end
endmodule
1-1. UART PC로 수신받기
구현
더보기
`timescale 1ns / 1ps
module top (
input clk,
input reset,
input btn_tx_start,
output txd
);
wire w_btn_tx_start;
button U_BTN_TX (
.clk(clk),
.in (btn_tx_start),
.out(w_btn_tx_start)
);
uart U_UART_Tx (
.clk(clk),
.reset(reset),
.tx_start(w_btn_tx_start),
.tx_data(8'h41), // 'A'
.tx(txd),
.tx_done()
);
endmodule
더보기
`timescale 1ns / 1ps
module button (
input clk,
input in,
output out
);
localparam N = 64;
reg [N-1:0] Q_reg, Q_next;
wire w_debounce_out;
reg [1:0] diff_reg, diff_next;
// debounce circuit
always @(*) begin
Q_next = {Q_reg[N-2:0], in}; // left shift
end
always @(posedge clk) begin
Q_reg <= Q_next; // 매 클럭마다 shift돼서 출력
diff_reg <= diff_next;
end
assign w_debounce_out = &Q_reg;
// dff edge-detector
always @(*) begin
diff_next[0] = w_debounce_out;
diff_next[1] = diff_reg[0];
end
// output logic
assign out = ~diff_reg[0] & diff_reg[1];
endmodule
버튼 로직
Q_next
: N클럭 동안의in
의 상태정보가 저장되어 있음- Debouncer : N클럭 동안 버튼이 계속 눌렸는지 안눌렸는지 알 수 있음
- Edge Detector : Rising edge, Falling edge Trigger
결과
→ 송신이 되긴 하지만 오류가 섞임
Made By Minseok KIM
'VerilogHDL > Study' 카테고리의 다른 글
[VerilogHDL] System Verilog 기초 (0) | 2024.05.22 |
---|---|
[VerilogHDL] UART Rx, Tx 최종(Oversampling) (0) | 2024.05.22 |
[VerilogHDL] UpCounter, 디버깅, UART Tx (0) | 2024.05.20 |
[VerilogHDL] FSM 코딩(Moore, Mealy) - 버튼, UpCounter (0) | 2024.05.19 |
[VerilogHDL] 조합 논리 회로 & 순차 논리 회로, Latch & FlipFlop (0) | 2024.05.19 |
@민바Minba :: Minba's blog
Let's Be Happy!
도움이 되었으면 좋겠어요 :)