- PC에서 FPGA 보드로 '1'을 보내면 Led 1개 ON
- PC에서 FPGA 보드로 '2'을 보내면 Led 2개 ON
- PC에서 FPGA 보드로 '3'을 보내면 Led 3개 ON
led_FSM
`timescale 1ns / 1ps
module led_FSM (
input clk,
input reset,
input [7:0] data,
output reg [2:0] led
);
localparam LED0 = 0, LED1 = 1, LED2 = 2, LED3 = 3;
reg [1:0] state, state_next;
always @(posedge clk, posedge reset) begin
if (reset) begin
state <= LED0;
end else begin
state <= state_next;
end
end
always @(*) begin
state_next = state;
case (state)
LED0: begin
if (data == 8'h30) state_next = state;
else if (data == 8'h31) state_next = LED1;
else if (data == 8'h32) state_next = LED2;
else if (data == 8'h33) state_next = LED3;
end
LED1: begin
if (data == 8'h30) state_next = LED0;
else if (data == 8'h31) state_next = state;
else if (data == 8'h32) state_next = LED2;
else if (data == 8'h33) state_next = LED3;
end
LED2: begin
if (data == 8'h30) state_next = LED0;
else if (data == 8'h31) state_next = LED1;
else if (data == 8'h32) state_next = state;
else if (data == 8'h33) state_next = LED3;
end
LED3: begin
if (data == 8'h30) state_next = LED0;
else if (data == 8'h31) state_next = LED1;
else if (data == 8'h32) state_next = LED2;
else if (data == 8'h33) state_next = LED3;
end
endcase
end
always @(*) begin
led = 3'b000;
case (state)
LED0: begin
led = 3'b000;
end
LED1: begin
led = 3'b001;
end
LED2: begin
led = 3'b011;
end
LED3: begin
led = 3'b111;
end
endcase
end
endmodule
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;
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_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_tx_rx_loop
`timescale 1ns / 1ps
module top_txrx_loop(
input clk,
input reset,
// Transmitter
output tx,
// Receiver
input rx,
// led
output [2:0] led
);
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)
);
led_FSM U_LED(
.clk(clk),
.reset(reset),
.data(w_rx_data),
.led(led)
);
endmodule
schematic
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]
## LEDs
set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { led[0] }]; #IO_L23N_T3_A02_D18_14 ,Sch=LED0
set_property -dict { PACKAGE_PIN E19 IOSTANDARD LVCMOS33 } [get_ports { led[1] }]; #IO_L3N_T0_DQS_EMCCLK_14 ,Sch=LED1
set_property -dict { PACKAGE_PIN U19 IOSTANDARD LVCMOS33 } [get_ports { led[2] }]; #IO_L15P_T2_DQS_RDWR_B_14 ,Sch=LED2
set_property -dict { PACKAGE_PIN V19 IOSTANDARD LVCMOS33 } [get_ports { led[3] }]; #IO_L15N_T2_DQS_DOUT_CSO_B_14 ,Sch=LED3
##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 num.sv (0) | 2024.07.09 |
---|---|
0521 system verilog, adder.sv (0) | 2024.07.09 |
0520 oversampling, uart (0) | 2024.06.22 |
0517 uart_tx_rx (0) | 2024.06.22 |
0517 uart_tx (0) | 2024.06.22 |