#FIFO
- First-In-First-Out memory queue
- 내부에 read와 write에 대한 pointer를 관리하는 control logic이 있어서 status flags를 생성하고,
user logic과 interface하기 위한 handshake signal을 제공
#Features
- Data widths가 8bits인 8개의 data를 저장할 수 있는 memory depth을 가진다.
- status flag로 full과 empty flag를 제공
- Invalid한 read 또는 write 요청에 대하여 FIFO 상태를 변화시키지 않고 거절한다.
- Count vector는 FIFO 안에 있는 현재 data의 수를 제공한다.
#State Diagram
module fifo(clk, reset_n, wr_en, rd_en, din, dout, data_count, full, empty, wr_ack, wr_err, rd_ack, rd_err);
input clk, reset_n, wr_en, rd_en;
input [7:0] din;
output reg [7:0] dout;
output [3:0] data_count;
output reg full, empty, wr_ack, wr_err, rd_ack, rd_err;
reg we,re;
reg [2:0] state, next_state;
reg [3:0] data_count, next_data_count;
reg [2:0] head, next_head;
reg [2:0] tail, next_tail;
reg [7:0] next_dout;
wire [7:0] r_data;
regfile U0_regfile(.clk(clk), .wAddr(tail), .wData(din), .we(we), .rAddr(head), .rData(r_data)); //call regfile
/////////State Encoding/////////
parameter IDLE_STATE = 3'b000;
parameter WRITE_STATE = 3'b001;
parameter READ_STATE = 3'b010;
parameter WR_ERR_STATE = 3'b011;
parameter RD_ERR_STATE = 3'b100;
//re value set by next_state
always@(next_state)
case(next_state)
READ_STATE:re = 1'b1; //if state is Read, re signal is 1
default:re = 1'b0; //default re siganl is 0
endcase
//2 to 1 multiplexer's roll
always@(re, r_data)
if(re)next_dout <= r_data; //if re is 1, r_data is stored at next_dout
else next_dout <=8'h00; //else 8'h00 is stored at next_dout
//next state logic
always @(wr_en, rd_en, state, next_state, data_count) //sensitive list
begin
case(state)
IDLE_STATE : //at IDLE_STATE
if(wr_en == 0 && rd_en == 0) next_state = IDLE_STATE; //if wr_en and rd_en are 0, IDLE_STATE
else if(wr_en == 1 && data_count < 8) next_state = WRITE_STATE; //if wr_en is 1 and data_count < 8, WRITE_STATE
else if(rd_en == 1 && data_count > 0) next_state = READ_STATE; //if rd_en is 1 and data_count > 0, READ_STATE
else if(wr_en == 1 && data_count == 8) next_state = WR_ERR_STATE;//if wr_en is 1 and data_count = 8, WR_ERR_STATE
else if(rd_en == 1 && data_count == 0) next_state = RD_ERR_STATE;//if rd_en is 1 and data_count = 0, RD_ERR_STATE
else next_state = 3'bxxx;
WRITE_STATE : //at WRITE_STATE
if(wr_en == 1 && data_count < 8) next_state = WRITE_STATE; //if wr_en is 1 and data_count < 8, WRITE_STATE
else if(wr_en == 1 && data_count == 8) next_state = WR_ERR_STATE;//if wr_en is 1 and data_count = 8, WR_ERR_STATE
else if(wr_en == 0 && rd_en == 0) next_state = IDLE_STATE; //if wr_en and rd_en are 0, IDLE_STATE
else if(rd_en == 1) next_state = READ_STATE; //if rd_en is 1, READ_STATE(적어도 data_count is bigger than 1 at WRITE_STATE)
else next_state = 3'bxxx;
READ_STATE : //at READ_STATE
if(rd_en == 1 && data_count > 0) next_state = READ_STATE; //if rd_en is 1 and data_count > 0, READ_STATE
else if(rd_en == 1 && data_count == 0) next_state = RD_ERR_STATE;//if rd_en is 1 and data_count = 0, RD_ERR_STATE
else if(wr_en == 1) next_state = WRITE_STATE; //if wr_en is 1 WRITE_STATE(적어도 data_count is smaller than 7 at READ_STATE)
else if(rd_en == 0 && wr_en == 0) next_state = IDLE_STATE; //if wr_en and rd_en are 0, IDLE_STATE
else next_state = 3'bxxx;
WR_ERR_STATE : //at WR_ERR_STATE
if(wr_en == 1) next_state = WR_ERR_STATE; //if wr_en is 1, WR_ERR_STATE
else if(rd_en == 1) next_state = READ_STATE; //if rd_en is 1, READ_STATE(data_count is 8 at WR_ERR_STATE)
else if(wr_en == 0 && rd_en == 0) next_state = IDLE_STATE; //if wr_en and rd_en are 0, IDLE_STATE
else next_state = 3'bxxx;
RD_ERR_STATE : //at RD_ERR_STATE
if(rd_en == 1) next_state = RD_ERR_STATE; //if rd_en is 1, RD_ERR_STATE
else if(wr_en == 1) next_state = WRITE_STATE; //if wr_en is 1, WRITE_STATE(data_count is 0 at RD_ERR_STATE)
else if(rd_en == 0 &&wr_en == 0) next_state = IDLE_STATE; //if wr_en and rd_en are 0, IDLE_STATE
else next_state = 3'bxxx;
default: next_state = 3'bxxx;
endcase
end
//sequential logic part(memory part)
always @(posedge clk or negedge reset_n)
begin
if(!reset_n) begin //reset_n = 0
state <= IDLE_STATE; //IDLE_STATE
data_count <= 0; //0
head <= 0; //0
tail <= 0; //0
dout <= 0; //0
end //initialize
else if(reset_n)begin //if reset_n is 1
state <= next_state; //next_value are stored at current value
data_count <= next_data_count;
head <= next_head;
tail <= next_tail;
dout <= next_dout;
end
else begin //else unknow value are stored
state <= 3'bxxx;
data_count <= 4'bxxxx;
head <= 3'bxxx;
tail <= 3'bxxx;
dout <= 8'bxxxxxxxx;
end
end
//output logic (full, empty, wr_ack, rd_ack, rd_err)flag
always @(state, data_count)
begin
case(state)
IDLE_STATE : //at IDLE_STATE
if(data_count == 0) {full, empty, wr_ack, wr_err, rd_ack, rd_err} = 6'b010000; //if data_count is 0, empty flag 1
else if(data_count == 8) {full, empty, wr_ack, wr_err, rd_ack, rd_err} = 6'b100000; //if data_count is 8, full flag 1
else {full, empty, wr_ack, wr_err, rd_ack, rd_err} = 6'b000000; //else all flag 0
WRITE_STATE : //at WRITE_STATE
if(data_count == 8) {full, empty, wr_ack, wr_err, rd_ack, rd_err} = 6'b101000; //if data_count is 8, full, wr_ack flag 1
else {full, empty, wr_ack, wr_err, rd_ack, rd_err} = 6'b001000; //else wr_ack flag 1
WR_ERR_STATE : {full, empty, wr_ack, wr_err, rd_ack, rd_err} = 6'b100100; //at WR_ERR_STATE full, wr_err flag 1
READ_STATE : //at READ_STATE
if(data_count == 0) {full, empty, wr_ack, wr_err, rd_ack, rd_err} = 6'b010010; //if data_count is 0, empty, rd_ack flag 1
else {full, empty, wr_ack, wr_err, rd_ack, rd_err} = 6'b000010; //else rd_ack flag 1
RD_ERR_STATE : {full, empty, wr_ack, wr_err, rd_ack, rd_err} = 6'b010001; //at RD_ERR_STATE empty, rd_err flag 1
default : {full, empty, wr_ack, wr_err, rd_ack, rd_err} = 6'bxxxxxx;
endcase
end
//next value logic
always @(next_state, head, tail, data_count)
begin
case(next_state)
IDLE_STATE : begin //at IDLE_STATE current head, tail, data_count value are stored
next_head = head; // at next_head, next_tail, next_data_count value
next_tail = tail; // we is 0
next_data_count = data_count;
we = 1'b0;
end
WRITE_STATE : begin
next_head = head; //at WRITE_STATE current head, tail + 1, data_count value + 1 are stored
next_tail = tail + 3'b1; // at next_head, next_tail, next_data_count value
next_data_count = data_count + 4'b1; // we is 1
we = 1'b1; // because of WRITE_STATE state, tail is increased by 1
end
WR_ERR_STATE : begin
next_head = head; //at WE_ERR current head, tail, data_count value are stored
next_tail = tail; // at next_head, next_tail, next_data_count value
next_data_count = data_count; // we is 0
we = 1'b0;
end
READ_STATE : begin
next_head = head + 3'b1; //at READ_STATE current head + 1, tail, data_count value - 1 are stored
next_tail = tail; // at next_head, next_tail, next_data_count value
next_data_count = data_count - 4'b1; // we is 0
we = 1'b0; // because of READ_STATE state, head is increased by 1
end
RD_ERR_STATE : begin
next_head = head; //at RD_ERR_STATE current head, tail, data_count value are stored
next_tail = tail; // at next_head, next_tail, next_data_count value
next_data_count = data_count; // we is 0
we = 1'b0;
end
default : begin
next_head = 3'bxxx;
next_tail = 3'bxxx;
next_data_count = 4'bxxxx;
we = 1'bx;
end
endcase
end
endmodule
'Computer > Computer Structure' 카테고리의 다른 글
DMAC - MASTER (0) | 2013.05.26 |
---|---|
DMAC - SLAVE (0) | 2013.05.26 |
DMAC - Register File (0) | 2013.05.26 |
DMAC - Bus (0) | 2013.05.26 |
DMAC - Memory (0) | 2013.05.26 |