//-----------------------------------------------------
// Имя модуля : syn_fifo
// Имя файла : syn_fifo.v
// Функц. назначение : Синхронный (однотактовый) FIFO
// Программист : portal-ed.ru/
//-----------------------------------------------------
module syn_fifo (
clk , // Тактовый вход
rst , // Высокий уровень - сброс
wr_cs , // Запись, выбор блока
rd_cs , // Чтение, выбор блока
data_in , // Входные данные
rd_en , // Разрешение чтения
wr_en , // Разрешение записи
data_out , // Выходные данные
empty , // FIFO пустой
full // FIFO полный
);
// Константы FIFO
parameter DATA_WIDTH = 8;
parameter ADDR_WIDTH = 8;
parameter RAM_DEPTH = (1 << ADDR_WIDTH);
// Объявление портов
input clk ;
input rst ;
input wr_cs ;
input rd_cs ;
input rd_en ;
input wr_en ;
input [DATA_WIDTH-1:0] data_in ;
output full ;
output empty ;
output[DATA_WIDTH-1:0] data_out ;
//-----------Внутренние переменные-------------------
reg [ADDR_WIDTH-1:0] wr_pointer;
reg [ADDR_WIDTH-1:0] rd_pointer;
reg [ADDR_WIDTH :0] status_cnt;
reg [DATA_WIDTH-1:0] data_out ;
wire [DATA_WIDTH-1:0] data_ram ;
//-----------Заданные переменные---------------
assign full = (status_cnt == (RAM_DEPTH-1));
assign empty = (status_cnt == 0);
//-----------Начало кода---------------------------
always @ (posedge clk or posedge rst)
begin : WRITE_POINTER
if (rst) begin
wr_pointer <= 0;
end else if (wr_cs && wr_en ) begin
wr_pointer <= wr_pointer + 1;
end
end
always @ (posedge clk or posedge rst)
begin : READ_POINTER
if (rst) begin
rd_pointer <= 0;
end else if (rd_cs && rd_en ) begin
rd_pointer <= rd_pointer + 1;
end
end
always @ (posedge clk or posedge rst)
begin : READ_DATA
if (rst) begin
data_out <= 0;
end else if (rd_cs && rd_en ) begin
data_out <= data_ram;
end
end
always @ (posedge clk or posedge rst)
begin : STATUS_COUNTER
if (rst) begin
status_cnt <= 0;
// Чтение, но не запись
end else if ((rd_cs && rd_en) && !(wr_cs && wr_en)
&& (status_cnt != 0)) begin
status_cnt <= status_cnt - 1;
// Запись, но не чтение
end else if ((wr_cs && wr_en) && !(rd_cs && rd_en)
&& (status_cnt != RAM_DEPTH)) begin
status_cnt <= status_cnt + 1;
end
end
ram_dp_ar_aw #(DATA_WIDTH,ADDR_WIDTH)DP_RAM (
.address_0 (wr_pointer) , // Вход address_0
.data_0 (data_in) , // Двунаправленный порт data_0
.cs_0 (wr_cs) , // Выбор блока
.we_0 (wr_en) , // Разрешение записи
.oe_0 (1'b0) , // Разрешение выхода
.address_1 (rd_pointer) , // Вход address_q
.data_1 (data_ram) , // Двунаправленный порт data_1
.cs_1 (rd_cs) , // Выбор блока
.we_1 (1'b0) , // Разрешение чтения
.oe_1 (rd_en) // Разрешение выхода
);
endmodule