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

#Master

- Master interface를 통해 data를 read/write하기 위한 DMAC 내부 component

 

 

#State Diagram

 

module dmac_master(
  clk,
  reset_n,
  //Master interface
  M_req,
  M_address,
  M_wr,
  M_dout,
  M_grant,
  M_din,  
  //Inner interface
  dmac_opstart,
  dmac_opdone,
  dmac_opdone_clear,
  dmac_state,  
  fifo_rden,
  fifo_dout0_srcaddr,
  fifo_dout1_destaddr,
  fifo_dout2_datasize,
  fifo_data_count
 );
 input    clk;
 input    reset_n;
 //Master interface
 output    M_req;
 output [7:0]  M_address;
 output    M_wr;
 output [7:0]  M_dout;
 input    M_grant;
 input [7:0]  M_din;
 //Inner interface
 input    dmac_opstart;
 output   dmac_opdone;
 input    dmac_opdone_clear; 
 output [2:0] dmac_state;
 
 output   fifo_rden;
 input [7:0]  fifo_dout0_srcaddr, fifo_dout1_destaddr, fifo_dout2_datasize;
 input [3:0]  fifo_data_count;
 
 //state encoding
 parameter  IDLE = 3'b000;
 parameter  DONE = 3'b001;
 parameter  FIFO_POP = 3'b010; 
 parameter  BUS_REQUEST = 3'b011;
 parameter  MEMORY_READ = 3'b100;
 parameter  MEMORY_WRITE = 3'b101;

 reg [2:0]  state, next_state;
 reg [7:0]  r_SOURCE_ADDRESS, r_DESTINATION_ADDRESS, r_DATA_SIZE;
 reg [7:0]  next_SOURCE_ADDRESS, next_DESTINATION_ADDRESS, next_DATA_SIZE;
 assign    dmac_state = state;
 
 /////////////////////////////////////////////////////////
 //state register
 /////////////////////////////////////////////////////////
 
always@(posedge clk or negedge reset_n)
 begin
  if(reset_n==0)   state = IDLE;
  else if(reset_n==1) state = next_state;
  else      state = 3'bxxx; 
 end
 
 /////////////////////////////////////////////////////////
 //next state
 /////////////////////////////////////////////////////////
 
always@(state, dmac_opstart, dmac_opdone_clear, M_grant, next_DATA_SIZE, fifo_data_count)
 begin
  case(state)
   IDLE:begin
    if(dmac_opstart==1'b1)       next_state = FIFO_POP;
    else if(dmac_opstart==1'b0)    next_state = IDLE;   
    else            next_state = 3'bxxx;
   end   
   DONE:begin
    if(dmac_opdone_clear==1'b1)    next_state = IDLE;
    else if(dmac_opdone_clear==1'b0)   next_state = DONE;
    else            next_state = 3'bxxx;   
   end
   FIFO_POP:begin
    if(next_DATA_SIZE!=8'h00)     next_state = BUS_REQUEST;   
    else if(next_DATA_SIZE==8'h00)begin
     if(fifo_data_count > 4'h0)    next_state = FIFO_POP;
     else if(fifo_data_count == 4'h0)  next_state = DONE;     
     else           next_state = 3'bxxx;    
    end   
    else            next_state = 3'bxxx;
   end
   BUS_REQUEST:begin
    if(M_grant==1'b1)        next_state = MEMORY_READ;
    else if(M_grant==1'b0)      next_state = BUS_REQUEST;
    else            next_state = 3'bxxx;   
   end
   MEMORY_READ:          next_state = MEMORY_WRITE;  
   MEMORY_WRITE:begin
    if(next_DATA_SIZE!=8'h00)     next_state = MEMORY_READ;
    else if(next_DATA_SIZE==8'h00)begin
     if(fifo_data_count > 4'h0)    next_state = FIFO_POP;
     else if(fifo_data_count == 4'h0)  next_state = DONE;     
     else           next_state = 3'bxxx;    
    end   
    else            next_state = 3'bxxx;
   end
   default:            next_state = 3'bxxx;  
  endcase 
 end
 
 assign dmac_opdone =(state==DONE)?1'b1:1'b0;
 
 //About r_SOURCE_ADDRESS register
 
always@(posedge clk or negedge reset_n)
 begin
  if(reset_n == 1'b0)     r_SOURCE_ADDRESS = 8'h00;
  else if(reset_n == 1'b1)   r_SOURCE_ADDRESS = next_SOURCE_ADDRESS;
  else          r_SOURCE_ADDRESS = 8'hxx;  
 end 
 //About next_SOURCE_ADDRESS
 
always@(state, fifo_dout0_srcaddr, r_SOURCE_ADDRESS)
 begin
  case(state)
   FIFO_POP:        next_SOURCE_ADDRESS = fifo_dout0_srcaddr;
   BUS_REQUEST:       next_SOURCE_ADDRESS = r_SOURCE_ADDRESS;
   MEMORY_READ:       next_SOURCE_ADDRESS = r_SOURCE_ADDRESS;
   MEMORY_WRITE:       next_SOURCE_ADDRESS = r_SOURCE_ADDRESS+8'h1;
   default:         next_SOURCE_ADDRESS = 8'h00;
  endcase
 end
  
 //About r_DESTINATION_ADDRESS register
 
always@(posedge clk or negedge reset_n)
 begin
  if(reset_n == 1'b0)     r_DESTINATION_ADDRESS = 8'h00;
  else if(reset_n == 1'b1)   r_DESTINATION_ADDRESS = next_DESTINATION_ADDRESS;
  else          r_DESTINATION_ADDRESS = 8'hxx;  
 end
 //About next_DESTINATION_ADDRESS
 
always@(state, fifo_dout1_destaddr, r_DESTINATION_ADDRESS)
 begin
  case(state)
   FIFO_POP:       next_DESTINATION_ADDRESS = fifo_dout1_destaddr;
   BUS_REQUEST:      next_DESTINATION_ADDRESS = r_DESTINATION_ADDRESS;
   MEMORY_READ:      next_DESTINATION_ADDRESS = r_DESTINATION_ADDRESS;
   MEMORY_WRITE:      next_DESTINATION_ADDRESS = r_DESTINATION_ADDRESS+8'h1;
   default:        next_DESTINATION_ADDRESS = 8'h00;  
  endcase 
 end
 
 //About r_DATA_SIZE register
 
always@(posedge clk or negedge reset_n)
 begin
  if(reset_n == 1'b0)     r_DATA_SIZE = 8'h00;
  else if(reset_n == 1'b1)   r_DATA_SIZE = next_DATA_SIZE;
  else          r_DATA_SIZE = 8'hxx;  
 end 
 
 //About next_DATA_SIZE
 
always@(state, fifo_dout2_datasize, r_DATA_SIZE)
 begin
  case(state)
   FIFO_POP:       next_DATA_SIZE = fifo_dout2_datasize;
   BUS_REQUEST:      next_DATA_SIZE = r_DATA_SIZE;
   MEMORY_READ:      next_DATA_SIZE = r_DATA_SIZE-8'h1;
   MEMORY_WRITE:      next_DATA_SIZE = r_DATA_SIZE;
   default:        next_DATA_SIZE = 8'h00;  
  endcase 
 end
 
 //About fifo_rden 
 reg   fifo_rden;
 
always@(next_state)
 begin
  case(next_state)
   FIFO_POP:  fifo_rden = 1'b1;
   default:   fifo_rden = 1'b0;
  endcase 
 end 
 
 /////////////////////////////////////////////////////////
 //Output logic
 /////////////////////////////////////////////////////////
 
 //About M_req
 reg    M_req; 
 
always@(state)
 begin
  case(state)
   BUS_REQUEST: M_req = 1'b1;
   MEMORY_READ:  M_req = 1'b1;
   MEMORY_WRITE: M_req = 1'b1;
   default:   M_req = 1'b0; 
  endcase 
 end
 
 //About M_address
 reg [7:0]  M_address;
 
always@(state, r_SOURCE_ADDRESS, r_DESTINATION_ADDRESS)
 begin
  case(state)
   MEMORY_READ: M_address = r_SOURCE_ADDRESS;
   MEMORY_WRITE: M_address = r_DESTINATION_ADDRESS;
   default:   M_address = 8'h00;  
  endcase
 end
  
 //About M_wr
 reg    M_wr;
 
always@(state)
 begin
  case(state)
   MEMORY_READ: M_wr = 1'b0;
   MEMORY_WRITE: M_wr = 1'b1;
   default:   M_wr = 1'b0;  
  endcase 
 end
 
 //About M_dout 
 reg [7:0] M_dout; 
 
always@(state, M_din)
 begin
  case(state)
   MEMORY_WRITE:  M_dout = M_din;
   default:   M_dout = 8'h00;  
  endcase 
 end
 
endmodule