OpenCores
URL https://opencores.org/ocsvn/spacewire/spacewire/trunk

Subversion Repositories spacewire

[/] [spacewire/] [trunk/] [rtl/] [LSer.v] - Rev 27

Compare with Previous | Blame | View Log

// File name=Module= LSer     2005-04-23      btltz@mail.china.com       btltz from CASIC  
// Description:      Distributed line schedulers with 16 identic "routing table"(a "16 port memory" :-> ).
//                   1 table every Line Scheduler 
// Spec :            Note Port0 is in the routing table. But it is disposed by module "cfg_ctrl"     	    
//                   Because minimum latency is a key issue, the fifo empty flag is monitored and Router
//                   will transfer data whenever the buffer has data.
// Abbreviations: 	  Tab(TAB)   ---   table
// Origin:  SpaceWire Std - Draft-1(Clause 8)of ECSS(European Cooperation for Space Standardization),ESTEC,ESA.
//          SpaceWire Router Requirements Specification Issue 1 Rev 5. Astrium & University of Dundee 
// TODO:	     make rtl faster
////////////////////////////////////////////////////////////////////////////////////
//
/*synthesis translate_off*/
`include "timescale.v"
/*synthesis translate_on */
`define reset  1	               // WISHBONE standard reset
`define XIL_BRAM	    			   // Use Xilinx block RAM
`define XIL_DISRAM	 			   // Use Xilinx distributed RAM	
 
module LSer	#(parameter IF_PORTNUM =16, IO_DW =10,	              // interface port number=16. 
                        TRY_DW = IF_PORTNUM >16  ?  5   :
								         (IF_PORTNUM >8   ?  4   :  3 ),
                        ORG_AW = TRY_DW,
								TAB_DW = IF_PORTNUM+1                    // 16 IF_PORTNUM + 1 config port 
				  )
            (
// interface with SpW input ports
                  output reg  rd_IBUF_o,    // Note write to SpW IO port FIFO is performed by "switch core"
                  input [IO_DW-2:0]	SpW_di,		           // ignor the parity bit		
					   input  empty_IBUF_i,     // empty flag of SpW input interface buffer(fifo)
// config/control interface
                  output tab_d0_o,                      // d0 of the routing table value     
						input try_msb,	                       // if true, try "more(not most :-> ) significant bit"
 
						input [TAB_DW-1:0] tab_di,
						input we_tab_i,
						input [7:0] tab_WrAddr_i,
// origin line No.
                  input [ORG_AW-1:0] org_line_i,    
// Switch Matrix interface
                  output reg[IF_PORTNUM-1:0] we_cell_o,
					   //output sop_req_o,                    // pulse. start of package require 
						output [TRY_DW-1:0] cfg_SMX_o,         // try cnt data out to "config" switch matrix
						//output eop_o,	                     // pulse. end of package command
						//input  sop_ack_i,						   // level. responsion from switch matrix for sop
                  input [IF_PORTNUM-1:0] full_cell_i,
// global signal input						
						input reset,
						input gclk  
				);
 
				  parameter EOP         = 9'b1_0000_0000;                 // {p,1'b1,8'b0000_0000}
				  parameter EEP         = 9'b1_0000_0001;   		          // {p,1'b1,8'b0000_0001}
				  parameter HEADS_Cargo = 9'b0_xxxx_xxxx;                 // {p,1'b0,1-byte data } 
 
				  parameter STATE_NUM   = 8; 
              parameter IDLE           = 8'b0000_0001;
				  parameter JUDGE_HEAD	   = 8'b0000_0010;
				  parameter DEL_HEAD       = 8'b0000_0100;
				  parameter TRY_ORG_COL    = 8'b0000_1000;
				  parameter INCR_TRY_COL   = 8'b0001_0000;
				  parameter DECR_TRY_COL   = 8'b0010_0000;
				  parameter DISTRIBUTING   = 8'b0100_0000;				   
              parameter GRAB_CELL_WAIT	= 8'b1000_0000;			 // N-Chars from one packet shall not be interleaved with N-Chars from another packet(but FCTs,NULLs,TimeCodes).		 
 
				  parameter HCW = TAB_DW <8  ?  3  :	       // Hot counter width
                					(TAB_DW <16  ?  4  :
					 					 (TAB_DW <32  ?   5   :
					   				  (TAB_DW <64  ?    6   :  2 )));
              parameter True  = 1;
				  parameter False = 0;
 
// dispose SpW data input from fifo 
reg [7:0] Head;
wire [8:0] SpW_data = SpW_di[8:0];										 // exclude parity bit
assign emgEXP = (SpW_data == EOP) || (SpW_data == EEP); // emerge	a Nchar(control data)
// assign emgEOP = (SpW_data == EOP);
// assign emgEEP = (SpW_data == EEP);
// assign emgEXX = (SpW_data[8]==1) && (   (|SpW_data[7:1]) != 1'b0  );
 
assign IBUF_HasData = !empty_IBUF_i;
assign head_ptr2cfg = ( |SpW_data==1'b0 );	              // the head points to config area
 
reg [STATE_NUM-1:0] state, next_state;	  
reg C_ld_Head;
 
// table declaration.implemented by Single Port RAM.  
`ifdef XIL_BRAM 
reg  [TAB_DW-1:0] ram [255:0] /* synthesis syn_ramstyle = "block_ram" */;    // Addr range 0-255(255 reserved) 
`else 
reg  [TAB_DW-1:0] ram [255:0] /* synthesis syn_ramstyle = "select_ram" */;  
`endif 	
wire [7:0] tab_addr = we_tab_i  ?  tab_WrAddr_i  :  Head;
wire [TAB_DW-1:0] tab_do;	 
 
assign            tab_d0_o = tab_do[0] && !we_tab_i;  
wire [TAB_DW-2:0] tab_sw_do;
assign  tab_sw_do =	tab_do[TAB_DW-1 : 1];	 // tab data out for swith 
 
// try_cnt
reg [TRY_DW-1:0] try_cnt;
reg C_incr_cnt, C_decr_cnt, C_ld_org;                     // command to increase try counter or decrease try counter 
 
 
//An EEP received by a routing switch shall be transferred through the routing switch in the same way as an EOP
 
///////////////////
// HEAD delete
// 
always @(posedge gclk)
if(reset)
  Head <= 1;	          // to avoid initial address 0 of table(configuration port) 
else if(C_ld_Head)
  Head <= SpW_di[7:0];
 
///////////////////////
// try_cnt incr or decr
//
 
wire reset_ld_org = reset || C_ld_org; 
 
always @(posedge gclk)
if(reset_ld_org)
  try_cnt <= org_line_i;
else if(C_incr_cnt)
  begin
  if(try_cnt==IF_PORTNUM)	      // to support arbitrary	ports number
    try_cnt <= 0;
  else
    try_cnt <= try_cnt + 1;
  end
else if(C_decr_cnt)
  begin
  if(try_cnt==0)				   // to support arbitrary ports number
    try_cnt <= IF_PORTNUM;	    
  else
    try_cnt <= try_cnt - 1;
  end 
 
 
//////////////////////
// Routing Table
//
// implemented by Single Port RAM. Should complete configuration before read 
`ifdef XIL_BRAM
 reg [7:0] Addr_reg;                     
 always @(posedge gclk)
 begin
    if(we_tab_i)
	   ram[tab_addr] <= tab_di;
	Addr_reg <= tab_addr;					        // register the addr input 
 end	  
 assign tab_do = ram[Addr_reg];  
 
 `else                                         // Use distributed RAM 
 always @(posedge gclk)
 if(we_tab_i)
   ram[tab_addr] <= tab_di;	 
 assign tab_do = ram[tab_addr];
`endif	
 
 
///////////////////////////////
// Control FSM	 
//
// The first data character following either EOP or EEP shall be taken as the first character of the next packet
 
 
// reg [HCW-1:0] seekN1;                // Seek for annother "1", the order is "seekN1"
// reg [IF_PORTNUM-1:0] C_Load_BitX; 
 
always @(posedge gclk)
if(reset==`reset)  
    state <= IDLE;   //Initialized state			   
else 
    state <= next_state;
 
//------ next_state assignment
always @(*)
begin:NEXT_ASSIGN
  //Default Values for FSM outputs:		     
	 C_ld_Head   = 1'b0;
	 rd_IBUF_o   = 1'b0;               // single wire 		
	 C_incr_cnt  = 1'b0;
	 C_decr_cnt  = 1'b0;
	 C_ld_org    = 1'b0;
	 we_cell_o   = 0;						  // array
 
 
 
  //Use "Default next_state" style ->
    next_state = state;
      case(state) /* synthesis parallel_case */
  IDLE        :   begin  //When EOP marker seen, router terminates connection and frees output port
 
							if(IBUF_HasData || emgEXP)
						   begin 						 
						   rd_IBUF_o = 1'b1;	         // read buf to refresh the data output 						
						   next_state = JUDGE_HEAD;
					      end
					   end
  JUDGE_HEAD   :  begin
    /*temp*/        rd_IBUF_o = 1'b1;	         // 2nd read, later will emerge a "data" or a "EXP" 
                    if(head_ptr2cfg || emgEXP ) // if(result of 1st read) 
						    next_state = IDLE;	      // IDLE is also a state to waite configuration command to pass by
						  else 							   
							 next_state = DEL_HEAD;							
						end
  DEL_HEAD    :   begin
	/*temp*/ 		  C_ld_Head = 1'b1;						
						  if(emgEXP)  						 // if (result of 2nd read)
                	    begin
						    rd_IBUF_o = 1'b1;	
						    next_state = JUDGE_HEAD; // taken as the first character of the next packet
                      end								// An EOP or EEP received immediately after an EOP or EEP represents an empty packet                          
                    else
						    begin
							 C_ld_org = 1;
                      next_state = TRY_ORG_COL;
							 end
						end
  TRY_ORG_COL :   begin	                     
	/*temp*/ 		  if( tab_sw_do[org_line_i] == 1 &&     // here "org_line_i"=="try_cnt"
	                     full_cell_i[org_line_i] == False  )
 
						    	 next_state = DISTRIBUTING; 							
                    else if( try_msb )
						       next_state = INCR_TRY_COL;
                    else 
						       next_state = DECR_TRY_COL;
						end
  INCR_TRY_COL:   begin
                    C_incr_cnt = 1'b1;
						  if(  tab_sw_do[try_cnt] == 1 &&  
						       full_cell_i[try_cnt] == False )
						     next_state = DISTRIBUTING;                
					   end
  DECR_TRY_COL :  begin
                    C_decr_cnt = 1'b1;
						  if(  tab_sw_do[try_cnt] == 1 &&  
						       full_cell_i[try_cnt] == False )
						     next_state = DISTRIBUTING;     
                  end
  DISTRIBUTING :  begin
                    rd_IBUF_o = 1'b1;
						  we_cell_o[try_cnt] = 1'b1;		// only one "we_cell_o" is active at the same time. 
						  if( emgEXP )
						    next_state = DEL_HEAD;
						  else if(empty_IBUF_i ==True)   // if not emerge a "EXP"
						    next_state = GRAB_CELL_WAIT;
                  end
  GRAB_CELL_WAIT: begin	 
                	  if(IBUF_HasData)
						  next_state = DISTRIBUTING;
					   end					 
		default:  next_state = 'bx;    // for simulation
    endcase
end  
 
 
////////////////////
// Output assignment
//
assign cfg_SMX_o = try_cnt;	 
 
 
 
 
 
/*
wire [TAB_DW-1:0] HotDec [0:TAB_DW-1];	       // decode output of table to one-hot  
// assignment of HotDec array
always @(*)
begin 
 integer k;
  for (k =0; k<IF_PORTNUM; k =k+1)
   HotDec[i] = Hot_Neq1(tab_do, seekN1); 
end
 
always @(posedge gclk)
if(reset ==`reset)
 cfg_data_o <= 0;			// cfg_data_o has 17 value: 0, 1000..., 0100..., 00100..., 000100...
else if( |Load_BitX )
   begin
   case(1'b1)  // synthesis parallel_case /
	C_Load_BitX[0]    :   cfg_data_o <= HotDec[0];
	C_Load_BitX[1]    :   cfg_data_o <= HotDec[1];
	C_Load_BitX[2]	   :   cfg_data_o <= HotDec[2];
	C_Load_BitX[3]    :   cfg_data_o <= HotDec[3];
	C_Load_BitX[4]    :   cfg_data_o <= HotDec[4];
	C_Load_BitX[5]	   :   cfg_data_o <= HotDec[5];
	C_Load_BitX[6]    :   cfg_data_o <= HotDec[6];
	C_Load_BitX[7]    :   cfg_data_o <= HotDec[7];
	C_Load_BitX[8]	   :   cfg_data_o <= HotDec[8];
	C_Load_BitX[9]    :   cfg_data_o <= HotDec[9];
	C_Load_BitX[10]   :   cfg_data_o <= HotDec[10];
	C_Load_BitX[11]	:   cfg_data_o <= HotDec[11];
	C_Load_BitX[12]	:   cfg_data_o <= HotDec[12];
	C_Load_BitX[13]   :   cfg_data_o <= HotDec[13];
	C_Load_BitX[14]   :   cfg_data_o <= HotDec[14];
	C_Load_BitX[15]	:   cfg_data_o <= HotDec[15];
	default           :   begin
	                    cfg_data_o <= 16'b0;
							  $display("Error at time=%dns  PORT WIDTH exceeded, maybe you need to modify this HDL file manually :-# ",	$time);
							  end
   end
*/
 
/*
///////////////////
//	 Function array
//
function [IF_PORTNUM-1:0] Hot_Neq1;
input [TAB_DW-1:0] di;
input [HCW-1:0] NEXT;
integer k;
integer n1 = 0;    //number of 1s
  for(k =0; k <TAB_DW; k =k+1)
  begin
    if(di[k] =1'b1)
	   n1 = n1 + 1;
	 if( n1 ==NEXT )
	   begin
	   hot_1st[TAB_NUM-1:k+1] =0; 
		hot_1st[k] = 1'b1;
		hot_1st[k-1:0] = 0;
		end
  end
endfunction
*/
 
 
endmodule
 
`undef reset 
`undef XIL_BRAM
`undef XIL_DISRAM
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.