Circuit Design/🔥HDL
[Verilog] 12. UART(3) TX
Nekoder
2024. 6. 10. 16:10
728x90
TX
TX Block 부분은 Parallel로 받은 Data를 다시 Serial로 변경시켜서 출력하는 Block입니다.
저번에 제작한 FIFO Block에서 나온 Output을 받아 TX를 제작하겠습니다.
TX에서도 상태 변화를 FSM(Finite State Machine)을 사용하여 구현하겠습니다.
uart_tx.v code
'timescale 1ns / 1ps
module uart_tx(
input [7:0] DATA, // output from the FIFO
input START, // ~Empty signal from FIFO
input RST,
input CLK,
output reg TXD // Serial output. It's equal to RXDin
);
localparam [1:0] idle = 2'b00, //FSM state component
start = 2'b01,
tx_send = 2'b10,
stop = 2'b11;
reg [3:0] curr_state, next_state; //FSM state Register
reg [3:0] over_sample_cnt, bit_cnt;
wire over_sample_cnt_done, bit_cnt_done;
wire parity;
wire baud_x16_en;
reg [7:0] tx_data_in;
wire [8:0] tx_data = {parity, tx_data_in};
always @ (posedge CLK) begin
if(START)
tx_data_in <= DATA;
end
always @ (posedge CLK) begin // Check the state per 1 clk, change to the next state
if (RST)
curr_state <= idle;
else
curr_state <= next_state;
end
always @ (curr_state, START, over_sample_cnt_done, bit_cnt_done) begin //FSM
case (curr_state)
idle : // when START be a '1' in idle state, Change curr_state to start
if(START)
next_state = start;
else // else maintain the idle
next_state = idle;
start : // when 'over_sample_cnt_done' be a '1' in start state, Change curr_state to tx_send
if(over_sample_cnt_done)
next_state = tx_send;
else // else maintain the start
next_state = start;
tx_send : // when 'over_sample_cnt_done & bit_cnt_done' be a '1' in tx_send state, Change curr_state to stop
if(over_sample_cnt_done && bit_cnt_done)
next_state = stop;
else // else maintain the tx_send
next_state = tx_send;
stop : // when 'over_sample_cnt_done' be a '1' in stop state, Change curr_state to idle
if(over_sample_cnt_done)
next_state = idle;
else // else maintain the stop
next_state = stop;
default : next_state = idle;
endcase
end
// The part of making over_sample_cnt
always @ (posedge CLK) begin
if (curr_state == idle)
over_sample_cnt <= 5'd15;
else if (baud_x16_en)
over_sample_cnt <= over_sample_cnt -1;
end
assign over_sample_cnt_done = (over_sample_cnt == 4'd0) & baud_x16_en;
//The part of making bit_cnt
always @ (posedge CLK) begin
if (curr_state != tx_send)
bit_cnt <= 4'd0;
else if (over_sample_cnt_done)
bit_cnt <= bit_cnt + 1;
end
assign bit_cnt_done = over_sample_cnt_done & (bit_cnt == 4'd8);
//make a parity
assign parity = tx_data[7:0];
//Parallel to Serial (TXD)
always @ (curr_state, bit_cnt) begin
if (curr_state == idle || curr_state == stop)
TXD = 1'b1;
else if (curr_state == start)
TXD = 1'b0;
else
TXD = tx_data[bit_cnt];
end
//instance the uart_baud_gen
uart_baud_gen baud_gen_10 (
.RST (RST),
.CLK (CLK),
.BAUD_X16_EN (baud_x16_en)
);
endmodule
uart_top.v code
'timescale 1ns / 1ps
module uart_top(
input RST,
input CLK,
input RXD,
output [6:0] AN,
output CA,
output PAR_ERR,
output FRM_ERR,
output TXD
);
wire [7:0] rx_data;
wire rx_data_rdy, empty;
wire [7:0] dout;
reg [7:0] dout_reg;
always @ (posedge CLK) begin
if (~empty)
dout_reg <= dout;
end
uart_rx uart_rx_0 (
.RST (RST),
.CLK (CLK),
.RXD (RXD),
.RX_DATA (rx_data),
.RX_DATA_RDY (rx_data_rdy),
.FRM_ERR (FRM_ERR),
.PARITY_ERR (PAR_ERR)
);
my_fifo fifo_0(
.RST (RST),
.CLK (CLK),
.DIN (rx_data),
.WR_EN (rx_data_rdy),
.FULL (FULL),
.DOUT (dout),
.RD_EN (~empty),
.EMPTY (empty)
);
display_inf disp_0 (
.RST (RST),
.CLK (CLK), // 125 Mhz
.NUM_1S (dout_reg [3:0]),
.NUM_10S (dout_reg [7:4]),
.CA (CA),
.AN (AN)
);
uart_tx uart_tx_0 (
.RST (RST),
.CLK (CLK),
.START (~empty),
.DATA (dout),
.TXD (TXD)
);
endmodule
가장 아래에 tx부분을 추가하여 module들을 연결해 주었습니다.
이렇게 FIFO와 Baud_x16_gen 모듈의 값에 따른 FSM을 구현한 TX module을 제작하여, 기존 uart에 연결하는 과정까지 마무리하였습니다
728x90