본문 바로가기

Computer/Computer Structure

DMAC - FIFO

#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