uart
`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;
wire [7:0] w_rx_data;
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_reg = 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_reg = 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
fifo.v
`timescale 1ns / 1ps
module fifo #(
parameter ADDR_WIDTH = 3,
DATA_WIDTH = 8
) (
input clk,
input reset,
input wr_en,
output full,
input [DATA_WIDTH - 1:0] wdata,
input rd_en,
output [DATA_WIDTH - 1:0] rdata,
output empty
);
wire [ADDR_WIDTH-1:0] w_waddr, w_raddr;
register_file #(
.ADDR_WIDTH(ADDR_WIDTH),
.DATA_WIDTH(DATA_WIDTH)
) U_RegFile (
.clk (clk),
.wr_en(wr_en & ~full),
.waddr(w_waddr),
.wdata(wdata),
.raddr(w_raddr),
.rdata(rdata)
);
fifo_control_unit #(
.ADDR_WIDTH(ADDR_WIDTH)
) U_FIFO_CU (
.clk (clk),
.reset(reset),
// write
.wr_en(wr_en),
.full (full),
.waddr(w_waddr),
// read
.rd_en(rd_en),
.empty(empty),
.raddr(w_raddr)
);
endmodule
module register_file #(
parameter ADDR_WIDTH = 3,
DATA_WIDTH = 8
) (
input clk,
input wr_en,
input [ADDR_WIDTH - 1:0] waddr,
input [DATA_WIDTH - 1:0] wdata,
input [ADDR_WIDTH - 1:0] raddr,
output [DATA_WIDTH - 1:0] rdata
);
reg [DATA_WIDTH-1:0] mem[0:2**ADDR_WIDTH-1];
always @(posedge clk) begin
if (wr_en) mem[waddr] <= wdata;
end
assign rdata = mem[raddr];
endmodule
module fifo_control_unit #(
parameter ADDR_WIDTH = 3
) (
input clk,
input reset,
// write
input wr_en,
output full,
output [ADDR_WIDTH-1:0] waddr,
// read
input rd_en,
output empty,
output [ADDR_WIDTH-1:0] raddr
);
reg [ADDR_WIDTH-1:0] wr_ptr_reg, wr_ptr_next;
reg [ADDR_WIDTH-1:0] rd_ptr_reg, rd_ptr_next;
reg full_reg, full_next, empty_reg, empty_next;
assign waddr = wr_ptr_reg;
assign raddr = rd_ptr_reg;
assign full = full_reg;
assign empty = empty_reg;
always @(posedge clk, posedge reset) begin
if (reset) begin
wr_ptr_reg <= 0;
rd_ptr_reg <= 0;
full_reg <= 1'b0;
empty_reg <= 1'b1;
end else begin
wr_ptr_reg <= wr_ptr_next;
rd_ptr_reg <= rd_ptr_next;
full_reg <= full_next;
empty_reg <= empty_next;
end
end
always @(*) begin
wr_ptr_next = wr_ptr_reg;
rd_ptr_next = rd_ptr_reg;
full_next = full_reg;
empty_next = empty_reg;
case ({
wr_en, rd_en
})
2'b01: begin // read
if (!empty_reg) begin
full_next = 1'b0;
rd_ptr_next = rd_ptr_reg + 1;
if (rd_ptr_next == wr_ptr_reg) begin
empty_next = 1'b1;
end
end
end
2'b10: begin // write
if (!full_reg) begin
empty_next = 1'b0;
wr_ptr_next = wr_ptr_reg + 1;
if (wr_ptr_next == rd_ptr_reg) begin
full_next = 1'b1;
end
end
end
2'b11: begin // write, read
if (empty_reg) begin
wr_ptr_next = wr_ptr_reg;
rd_ptr_next = rd_ptr_reg;
end else begin
wr_ptr_next = wr_ptr_reg + 1;
rd_ptr_next = rd_ptr_reg + 1;
end
end
endcase
end
endmodule
tb_uart_fifo.sv
`timescale 1ns / 1ps
module tb_uart_fifo ();
reg clk;
reg reset;
wire tx;
reg tx_en;
reg [7:0] tx_data;
wire tx_full;
reg rx;
reg [7:0] rx_data;
reg rx_en;
reg rx_empty;
wire w_tx_rx_loop;
uart_fifo dut (
.clk(clk),
.reset(reset),
.tx(w_tx_rx_loop),
.tx_en(tx_en),
.tx_data(tx_data),
.tx_full(tX_full),
.rx(w_tx_rx_loop),
.rx_en(rx_en),
.rx_data(rx_data),
.rx_empty(rx_empty)
);
always #5 clk = ~clk;
initial begin
clk = 0;
reset = 1'b1;
tx_en = 1'b0;
rx_en = 1'b0;
end
initial begin
#80 reset = 1'b0;
#50;
@(posedge clk);
tx_data = "0";
tx_en = 1'b1;
@(posedge clk);
tx_en = 1'b0;
@(posedge clk);
tx_data = "1";
tx_en = 1'b1;
@(posedge clk);
tx_en = 1'b0;
@(posedge clk);
tx_data = "2";
tx_en = 1'b1;
@(posedge clk);
tx_en = 1'b0;
@(~rx_empty)
while (!rx_empty) begin
rx_en = 1'b1;
@(posedge clk);
end
end
endmodule
schematic
simulation
baudrate_generator : if(counter_reg == 3)으로 실행하기
constraint
##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' 카테고리의 다른 글
0528 Computer Architecture, Dedicated Processor 0~9 counter (0) | 2024.07.09 |
---|---|
0525 uart tx rx systemverilog (0) | 2024.07.09 |
0523 FIFO Systemverilog verification (0) | 2024.07.09 |
0522 RAM SystemVerilog verification (0) | 2024.07.09 |
0522 32bit register.sv (0) | 2024.07.09 |