![[VerilogHDL] FIFO, UART&FIFO](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FppB3S%2FbtsHHS6e5x6%2FpfzRIReYChdEtBzkmoYIaK%2Fimg.png)
[VerilogHDL] FIFO, UART&FIFOVerilogHDL/Study2024. 5. 30. 09:11
Table of Contents
#1. FIFO(Fist In First Out)
== Circular Queue, 선입선출
- push & pop할 떄 버퍼의 어디를 가리킬지 포인터가 필요하다.
- read하는 속도와 write하는 속도가 다를때 FIFO 사용
Push algorithm
- push 할 때 memory full이면 안된다.
Pop algorithm
- pop 할 때 memory empty면 안된다.
FIFO module
- push 할 때 memory full이면 안된다.
- pop 할 때 memory empty면 안된다.
rw_en = 1
일때 write 가능
구현
[FIFO module]
더보기
`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 empty,
output [DATA_WIDTH-1:0] rdata
);
wire w_full;
wire [ADDR_WIDTH-1:0] w_waddr, w_raddr;
register_file #(
.ADDR_WIDTH(ADDR_WIDTH),
.DATA_WIDTH (DATA_WIDTH) // 3bit address==2^3개 메모리 공간, 8bit data
) U_RegFile (
.clk (clk),
.reset(reset),
.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),
// wrte
.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 // 3bit address==2^3개 메모리 공간, 8bit data
) (
input clk,
input reset,
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];
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,
// wrte
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'b0;
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; // read이면 full = 0
rd_ptr_next = rd_ptr_reg + 1;
if (rd_ptr_next == wr_ptr_reg) begin
empty_next = 1'b1; // 모두 읽었으면 empty
end
end
end
2'b10: begin // write
if (!full_reg) begin
empty_next = 1'b0; // write이면 empty = 0
wr_ptr_next = wr_ptr_reg + 1;
if (wr_ptr_next == rd_ptr_reg) begin
full_next = 1'b1; // 모두 썼으면 full
end
end
end
2'b11: begin // write, read
if (empty_reg) begin // 비어있으면 더이상 진행 X
wr_ptr_next = wr_ptr_reg;
rd_ptr_next = rd_ptr_reg;
end else begin // 비어 있지 않으면 각 포인터 +1
wr_ptr_next = wr_ptr_reg + 1;
rd_ptr_next = rd_ptr_reg + 1;
end
end
endcase
end
endmodule
- Register Module
- 데이터를 저장하는 스토리지
- 데이터의 크기(Data Width)만큼의 저장공간이 2^(주소 크기)개 만큼 있다.
- write enable 신호를 받으면
write address
주소에 데이터를 저장 read address
주소에 저장된 데이터 반환
- FIFO Control module
- 어떤 주소에 저장되어 있는 데이터를 읽고 쓸 것인지 제어하는 유닛
read
: 레지스터가 비어있지 않으면 read address 포인터 1씩 증가 (read address == write address가 되면 Empty, 더이상 읽을 수 없음)write
: 레지스터가 가득 차 있지 않으면 write address 포인터 1씩 증가 (write address == read address가 되면 Full, 더 이상 쓸 수 없음)
⇒ Control unit에서 주소에 대한 포인터를 반환하면 Register module에서 해당 주소의 데이터를 read/write
#1-2. Verification
구현
GitHub - k1minseok/SystemVerilog_FIFO_0523: Implement FIFO module & Verification using System Verilog
Implement FIFO module & Verification using System Verilog - k1minseok/SystemVerilog_FIFO_0523
github.com
- SW의 FIFO와 HW(dut ← 설계한 FIFO모듈)을 비교하여 dut의 무결성을 검증한다.
시뮬레이션
=> 정상 동작!!
#2. UART + FIFO
위 그림과 같이 rx fifo와 tx fifo를 loop하여 PC로부터 받은 데이터를 다시 PC로 전송
- FIFO가 full이면 데이터 받지 않음
구현
GitHub - k1minseok/Verilog_UART_FIFO_0524: Implement UART module with FIFO
Implement UART module with FIFO. Contribute to k1minseok/Verilog_UART_FIFO_0524 development by creating an account on GitHub.
github.com
결과
위 결과와 같이 입력한 값이 정상적으로 출력된다.
Made By Minseok KIM
'VerilogHDL > Study' 카테고리의 다른 글
[VerilogHDL] RISC-V 기본, RV32I R-Type, IL-Type (0) | 2024.06.18 |
---|---|
[VerilogHDL] CPU 기본 구조, 메모리, Counter 설계(Control Unit, Data Path) (1) | 2024.06.03 |
[VerilogHDL] Verification(32bit register, BRAM) (0) | 2024.05.23 |
[VerilogHDL] System Verilog 기초 (0) | 2024.05.22 |
[VerilogHDL] UART Rx, Tx 최종(Oversampling) (0) | 2024.05.22 |
@민바Minba :: Minba's blog
Let's Be Happy!
도움이 되었으면 좋겠어요 :)