/* Output port */
// Author Andrew Laffely
// Last modified: 12 Feb 03
// !!!!!!!!!!!!!!! DO NOT CHANGE THIS FILE !!!!!!!!!!!!!!!!!!!!!!!!!
module out_port (gclock, reset, i_addr, c_data, c_addr, c_write, valid_next, data_out, ready);

input gclock, reset;
input [1:0] i_addr;     // buffer address requested by ccm
input [1:0] c_addr;     // buffer address requested by core
input [31:0] c_data;    // the data sent from the core
input valid_next;       // flow control bit sent from upstream block
input c_write;	        // write singal from core

output [32:0] data_out; // the data to be sent to interface
output [2:0] ready;     // flow control, port "ready" signal, sent to core
reg [32:0] data_out;
reg [2:0] ready;        // Port ready signal

reg [6:0] valid;        // contains the valid bits of the data in the port
reg [31:0] data [6:0];  // the data in the cdm
reg [2:0] i_addr_hold;  // hold the buf addr while evaluating  
reg [2:0] c_addr_hold;  // hold the buf addr while evaluating
reg [2:0] i_buf_state, c_buf_state; // first or second buf in each port

reg faketiming;         // Makes level sensitive transitions work properly
initial
begin
	faketiming = 1'b0;
	forever #1 faketiming = ~faketiming;
end

// *********************** INTERCONNECT *********************** //
always @ (posedge gclock)  //interconnect side
  begin
    if(!reset)
      begin
	//update valid from last transfer
	if(!(i_addr_hold[2:1] == 2'b11))  
	  begin
	    if(!(valid_next)&&data_out[32])
	      begin
		i_buf_state[i_addr_hold[2:1]]=~i_buf_state[i_addr_hold[2:1]];
		valid[i_addr_hold]=0;
	      end
	  end

	#1 i_addr_hold = {i_addr,i_buf_state[i_addr]};

	//send data
	if(!(i_addr == 2'b11))  //default no data
		#1 data_out={valid[i_addr_hold], data[i_addr_hold]};
	else
		#1 data_out[32]=0;
	end
end
// ******************** END INTERCONNECT *********************** //

// *************************** CORE **************************** //
always @ (posedge c_write)
  begin
	c_addr_hold = {c_addr, c_buf_state[c_addr]};
  end

always @ (negedge c_write) //Core
  begin
	if(!reset)
	  begin
		c_buf_state[c_addr_hold[2:1]]=~c_buf_state[c_addr_hold[2:1]];
		valid[c_addr_hold]=1;  //glitch reset
	  end
  end
// ************************** END CORE ************************* //

always @ (faketiming)
  begin
    if (reset)
      begin
	valid = 4'b0000;
	i_addr_hold = 3'b111;
	i_buf_state=3'b000;
	c_buf_state=3'b000;
      end
   else
      begin
	ready[0]=~valid[c_buf_state[0]];
	ready[1]=~valid[c_buf_state[1]];
	ready[2]=~valid[c_buf_state[2]];

	// *************************** CORE ************************ //
	if (c_write)
	  begin
		data[c_addr_hold]=c_data[31:0];
	  end
	// ************************ END CORE ********************** //
  end
end
endmodule



[ [ [ 'module',
      'out_port',
      '(',
      [ ['gclock'],
        ['reset'],
        ['i_addr'],
        ['c_data'],
        ['c_addr'],
        ['c_write'],
        ['valid_next'],
        ['data_out'],
        ['ready']],
      ')',
      ';'],
    [ ['input', 'gclock', 'reset', ';'],
      ['input', '[', '1', ':', '0', ']', 'i_addr', ';'],
      ['input', '[', '1', ':', '0', ']', 'c_addr', ';'],
      ['input', '[', '31', ':', '0', ']', 'c_data', ';'],
      ['input', 'valid_next', ';'],
      ['input', 'c_write', ';'],
      ['output', '[', '32', ':', '0', ']', 'data_out', ';'],
      ['output', '[', '2', ':', '0', ']', 'ready', ';'],
      ['reg', '[', '32', ':', '0', ']', ['data_out'], ';'],
      ['reg', '[', '2', ':', '0', ']', ['ready'], ';'],
      ['reg', '[', '6', ':', '0', ']', ['valid'], ';'],
      ['reg', '[', '31', ':', '0', ']', ['data', '[', '6', ':', '0', ']'], ';'],
      ['reg', '[', '2', ':', '0', ']', ['i_addr_hold'], ';'],
      ['reg', '[', '2', ':', '0', ']', ['c_addr_hold'], ';'],
      ['reg', '[', '2', ':', '0', ']', ['i_buf_state'], ['c_buf_state'], ';'],
      ['reg', ['faketiming'], ';'],
      [ 'initial',
        [ 'begin',
          [ [[['faketiming'], '=', "1 'b 0"], ';'],
            [ 'forever',
              [['#', '1'], [[['faketiming'], '=', '~', ['faketiming']], ';']]]],
          'end']],
      [ 'always',
        ['@', '(', ['posedge', ['gclock']], ')'],
        [ 'begin',
          [ [ 'if',
              ['(', '!', ['reset'], ')'],
              [ 'begin',
                [ [ 'if',
                    [ '(',
                      '!',
                      '(',
                      [['i_addr_hold', ['[', '2', '1', ']']], '==', "2 'b 11"],
                      ')',
                      ')'],
                    [ 'begin',
                      [ [ 'if',
                          [ '(',
                            '!',
                            '(',
                            [['valid_next']],
                            ')',
                            '&&',
                            ['data_out', ['[', '32', ']']],
                            ')'],
                          [ 'begin',
                            [ [ [ [ 'i_buf_state',
                                    [ '[',
                                      ['i_addr_hold', ['[', '2', '1', ']']],
                                      ']']],
                                  '=',
                                  '~',
                                  [ 'i_buf_state',
                                    [ '[',
                                      ['i_addr_hold', ['[', '2', '1', ']']],
                                      ']']]],
                                ';'],
                              [ [ ['valid', ['[', ['i_addr_hold'], ']']],
                                  '=',
                                  '0'],
                                ';']],
                            'end']]],
                      'end']],
                  [ ['#', '1'],
                    [ [ ['i_addr_hold'],
                        '=',
                        [ '{',
                          ['i_addr'],
                          ['i_buf_state', ['[', ['i_addr'], ']']],
                          '}']],
                      ';']],
                  [ 'if',
                    ['(', '!', '(', [['i_addr'], '==', "2 'b 11"], ')', ')'],
                    [ ['#', '1'],
                      [ [ ['data_out'],
                          '=',
                          [ '{',
                            ['valid', ['[', ['i_addr_hold'], ']']],
                            ['data', ['[', ['i_addr_hold'], ']']],
                            '}']],
                        ';']],
                    'else',
                    [ ['#', '1'],
                      [[['data_out', ['[', '32', ']']], '=', '0'], ';']]]],
                'end']]],
          'end']],
      [ 'always',
        ['@', '(', ['posedge', ['c_write']], ')'],
        [ 'begin',
          [ [ [ ['c_addr_hold'],
                '=',
                [ '{',
                  ['c_addr'],
                  ['c_buf_state', ['[', ['c_addr'], ']']],
                  '}']],
              ';']],
          'end']],
      [ 'always',
        ['@', '(', ['negedge', ['c_write']], ')'],
        [ 'begin',
          [ [ 'if',
              ['(', '!', ['reset'], ')'],
              [ 'begin',
                [ [ [ [ 'c_buf_state',
                        ['[', ['c_addr_hold', ['[', '2', '1', ']']], ']']],
                      '=',
                      '~',
                      [ 'c_buf_state',
                        ['[', ['c_addr_hold', ['[', '2', '1', ']']], ']']]],
                    ';'],
                  [[['valid', ['[', ['c_addr_hold'], ']']], '=', '1'], ';']],
                'end']]],
          'end']],
      [ 'always',
        ['@', '(', [['faketiming']], ')'],
        [ 'begin',
          [ [ 'if',
              ['(', ['reset'], ')'],
              [ 'begin',
                [ [[['valid'], '=', "4 'b 0000"], ';'],
                  [[['i_addr_hold'], '=', "3 'b 111"], ';'],
                  [[['i_buf_state'], '=', "3 'b 000"], ';'],
                  [[['c_buf_state'], '=', "3 'b 000"], ';']],
                'end'],
              'else',
              [ 'begin',
                [ [ [ ['ready', ['[', '0', ']']],
                      '=',
                      '~',
                      ['valid', ['[', ['c_buf_state', ['[', '0', ']']], ']']]],
                    ';'],
                  [ [ ['ready', ['[', '1', ']']],
                      '=',
                      '~',
                      ['valid', ['[', ['c_buf_state', ['[', '1', ']']], ']']]],
                    ';'],
                  [ [ ['ready', ['[', '2', ']']],
                      '=',
                      '~',
                      ['valid', ['[', ['c_buf_state', ['[', '2', ']']], ']']]],
                    ';'],
                  [ 'if',
                    ['(', ['c_write'], ')'],
                    [ 'begin',
                      [ [ [ ['data', ['[', ['c_addr_hold'], ']']],
                            '=',
                            ['c_data', ['[', '31', '0', ']']]],
                          ';']],
                      'end']]],
                'end']]],
          'end']]],
    'endmodule']]
