Computer/Computer Structure

DMAC - FIFO for DMAC

고양이는생선을좋아해 2013. 5. 26. 12:14

#FIFO for DMAC

- 기존 FIFO에서 data in port와 data out port를 3개 늘려서 구현

- 내부에 3개의 Register File을 Instance

 

 

module fifo_for_DMAC(
  clk,
  reset_n,
  wr_en,
  rd_en,
  din0,
  din1,
  din2,
  dout0,
  dout1,
  dout2,
  data_count,
  full,
  empty,
  wr_ack,
  wr_err,
  rd_ack,
  rd_err
 );
input clk, reset_n, wr_en, rd_en;
input [7:0] din0, din1, din2;
output reg [7:0] dout0, dout1, dout2;
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_dout0, next_dout1, next_dout2;
wire [7:0] r_data0, r_data1, r_data2;

regfile U0_regfile(.clk(clk), .wAddr(tail), .wData(din0), .we(we), .rAddr(head), .rData(r_data0)); //call regfile
regfile U1_regfile(.clk(clk), .wAddr(tail), .wData(din1), .we(we), .rAddr(head), .rData(r_data1)); //call regfile
regfile U2_regfile(.clk(clk), .wAddr(tail), .wData(din2), .we(we), .rAddr(head), .rData(r_data2)); //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_data0)
if(re)next_dout0 <= r_data0;  //if re is 1, r_data is stored at next_dout0
else next_dout0 <=8'h00;   //else 8'h00 is stored at next_dout0

always@(re, r_data1)
if(re)next_dout1 <= r_data1;  //if re is 1, r_data is stored at next_dout1
else next_dout1 <=8'h00;    //else 8'h00 is stored at next_dout1

always@(re, r_data2)
if(re)next_dout2 <= r_data2;  //if re is 1, r_data is stored at next_dout1
else next_dout2 <=8'h00;    //else 8'h00 is stored at next_dout1

//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     
 state <= IDLE_STATE;    
 data_count <= 0;    
 head <= 0;       
 tail <= 0;       
 dout0 <= 0;       
 dout1 <= 0;       
 dout2 <= 0;       
 end       
else if(reset_n)begin     
 state <= next_state;      
 data_count <= next_data_count;
 head <= next_head;
 tail <= next_tail;
 dout0 <= next_dout0;
 dout1 <= next_dout1;
 dout2 <= next_dout2;
 end
else begin         
 state <= 3'bxxx;
 data_count <= 4'bxxxx;
 head <= 3'bxxx;
 tail <= 3'bxxx;
 dout0 <= 8'bxxxxxxxx;
 dout1 <= 8'bxxxxxxxx;
 dout2 <= 8'bxxxxxxxx;
 end
end

always @(state, data_count)
begin
 case(state)
 IDLE_STATE :                          
 if(data_count == 0)   {full, empty, wr_ack, wr_err, rd_ack, rd_err} = 6'b010000; 
 else if(data_count == 8) {full, empty, wr_ack, wr_err, rd_ack, rd_err} = 6'b100000; 
 else        {full, empty, wr_ack, wr_err, rd_ack, rd_err} = 6'b000000; 
 WRITE_STATE :                         
 if(data_count == 8)   {full, empty, wr_ack, wr_err, rd_ack, rd_err} = 6'b101000; 
 else        {full, empty, wr_ack, wr_err, rd_ack, rd_err} = 6'b001000; 
 WR_ERR_STATE :     {full, empty, wr_ack, wr_err, rd_ack, rd_err} = 6'b100100; 
 READ_STATE :                         
 if(data_count == 0)   {full, empty, wr_ack, wr_err, rd_ack, rd_err} = 6'b010010; 
 else        {full, empty, wr_ack, wr_err, rd_ack, rd_err} = 6'b000010; 
 RD_ERR_STATE :     {full, empty, wr_ack, wr_err, rd_ack, rd_err} = 6'b010001; 
 default :      {full, empty, wr_ack, wr_err, rd_ack, rd_err} = 6'bxxxxxx;
 endcase
end

 

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