|  | @@ -10,9 +10,17 @@ use File::Spec;
 | 
	
		
			
				|  |  |  # Variables from configuration file
 | 
	
		
			
				|  |  |  our $iodev_addr_bits;
 | 
	
		
			
				|  |  |  our $iodev_addr_shift;
 | 
	
		
			
				|  |  | +our $xdev_addr_bits;
 | 
	
		
			
				|  |  | +our $xdev_addr_shift;
 | 
	
		
			
				|  |  |  our @sysirqs;
 | 
	
		
			
				|  |  |  our @iodevs;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +sub base($$$) {
 | 
	
		
			
				|  |  | +    my($num,$bits,$shift) = @_;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    my $v = ($num | (~0 << $bits)) << $shift;
 | 
	
		
			
				|  |  | +    return $v & 0xffffffff;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  sub generate_h($) {
 | 
	
		
			
				|  |  |      my($out) = @_;
 | 
	
	
		
			
				|  | @@ -23,8 +31,9 @@ sub generate_h($) {
 | 
	
		
			
				|  |  |      printf $out "#define IODEV_ADDR_BITS %d\n", $iodev_addr_bits;
 | 
	
		
			
				|  |  |      printf $out "#define IODEV_ADDR_SHIFT %d\n", $iodev_addr_shift;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    my $ndev = 0;
 | 
	
		
			
				|  |  | -    my $nirq = 0;
 | 
	
		
			
				|  |  | +    my $ndev  = 0;
 | 
	
		
			
				|  |  | +    my $nxdev = 0;
 | 
	
		
			
				|  |  | +    my $nirq  = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      print $out "\n";
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -41,15 +50,25 @@ sub generate_h($) {
 | 
	
		
			
				|  |  |  	next unless ($dcount);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	my $name = uc($dev->{-name});
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	printf $out "\n#define %s_DEV %d\n", $name, $ndev;
 | 
	
		
			
				|  |  | +	my $xdev = $dev->{-xdev};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if ($xdev) {
 | 
	
		
			
				|  |  | +	    printf $out "\n#define %s_XDEV %d\n", $name, $nxdev;
 | 
	
		
			
				|  |  | +	    printf $out "#define %s_BASE 0x%08x\n", $name,
 | 
	
		
			
				|  |  | +		base($nxdev, $xdev_addr_bits, $xdev_addr_shift);
 | 
	
		
			
				|  |  | +	} else {
 | 
	
		
			
				|  |  | +	    printf $out "\n#define %s_DEV  %d\n", $name, $ndev;
 | 
	
		
			
				|  |  | +	    printf $out "#define %s_BASE 0x%08x\n", $name,
 | 
	
		
			
				|  |  | +		base($ndev, $iodev_addr_bits, $iodev_addr_shift);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  |  	printf $out "#define %s_DEV_COUNT %d\n", $name, $dcount;
 | 
	
		
			
				|  |  |  	if ($icount) {
 | 
	
		
			
				|  |  |  	    printf $out "#define %s_IRQ %d\n", $name, $nirq;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	$ndev += $dcount;
 | 
	
		
			
				|  |  | -	$nirq += $dcount * $icount;
 | 
	
		
			
				|  |  | +	$ndev  += $xdev ? 0 : $dcount;
 | 
	
		
			
				|  |  | +	$nxdev += $xdev ? $dcount : 0;
 | 
	
		
			
				|  |  | +	$nirq  += $dcount * $icount;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      printf $out "\n#define IRQ_VECTORS %d\n", $nirq;
 | 
	
	
		
			
				|  | @@ -111,17 +130,23 @@ sub generate_verilog($)
 | 
	
		
			
				|  |  |      my($out) = @_;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      my $ndev = 0;
 | 
	
		
			
				|  |  | +    my $nxdev = 0;
 | 
	
		
			
				|  |  |      my $nirq = scalar(@sysirqs);
 | 
	
		
			
				|  |  |      my $irq_edge = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      my @imux = ();
 | 
	
		
			
				|  |  | +    my @xmux = ();
 | 
	
		
			
				|  |  |      my @wait = ();
 | 
	
		
			
				|  |  |      my @valid = ();
 | 
	
		
			
				|  |  |      my @irqs = ();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    print $out "\twire [31:0] iodev_rdata;\n";
 | 
	
		
			
				|  |  | -    printf $out "\twire [%d:0] iodev_valid = iodev_mem_valid << cpu_mem_addr[%d:%d];\n",
 | 
	
		
			
				|  |  | -	(1 << $iodev_addr_bits)-1,
 | 
	
		
			
				|  |  | +    print $out "\treg [31:0]  nxdev_rdata;\n";
 | 
	
		
			
				|  |  | +    print $out "\treg [31:0]  iodev_rdata;\n";
 | 
	
		
			
				|  |  | +    printf $out "\twire [%d:0]  xdev_valid  = iodev_mem_valid << cpu_mem_addr[%d:%d];\n",
 | 
	
		
			
				|  |  | +	(1 << $xdev_addr_bits)-1,
 | 
	
		
			
				|  |  | +	$xdev_addr_shift+$xdev_addr_bits-1, $xdev_addr_shift;
 | 
	
		
			
				|  |  | +    printf $out "\twire [%d:0]  iodev_valid = xdev_valid[%d] << cpu_mem_addr[%d:%d];\n",
 | 
	
		
			
				|  |  | +	(1 << $iodev_addr_bits)-1, (1 << $xdev_addr_bits)-1,
 | 
	
		
			
				|  |  |  	$iodev_addr_shift+$iodev_addr_bits-1, $iodev_addr_shift;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      print $out "\n";
 | 
	
	
		
			
				|  | @@ -129,6 +154,7 @@ sub generate_verilog($)
 | 
	
		
			
				|  |  |      foreach my $dev (@iodevs) {
 | 
	
		
			
				|  |  |  	my $dcount = $dev->{-count};
 | 
	
		
			
				|  |  |  	my $irq    = $dev->{-irq};
 | 
	
		
			
				|  |  | +	my $xdev   = $dev->{-xdev};
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	$dcount = 1 unless (defined($dcount));
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -144,8 +170,13 @@ sub generate_verilog($)
 | 
	
		
			
				|  |  |  		length($irq)-1, $name, $didx;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	printf $out "\twire [%2d:0] iodev_valid_%s = iodev_valid[%d:%d];\n",
 | 
	
		
			
				|  |  | -	    $dcount-1, $name, $ndev+$dcount-1, $ndev;
 | 
	
		
			
				|  |  | +	if ($xdev) {
 | 
	
		
			
				|  |  | +	    printf $out "\twire [%2d:0] iodev_valid_%s = xdev_valid[%d:%d];\n",
 | 
	
		
			
				|  |  | +		$dcount-1, $name, $nxdev+$dcount-1, $nxdev;
 | 
	
		
			
				|  |  | +	} else {
 | 
	
		
			
				|  |  | +	    printf $out "\twire [%2d:0] iodev_valid_%s = iodev_valid[%d:%d];\n",
 | 
	
		
			
				|  |  | +		$dcount-1, $name, $ndev+$dcount-1, $ndev;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	printf $out "\ttri1 [%2d:0] iodev_wait_n_%s;\n", $dcount-1, $name;
 | 
	
		
			
				|  |  |  	push(@wait, "(&iodev_wait_n_$name)");
 | 
	
	
		
			
				|  | @@ -155,7 +186,11 @@ sub generate_verilog($)
 | 
	
		
			
				|  |  |  	for (my $d = 0; $d < $dcount; $d++) {
 | 
	
		
			
				|  |  |  	    my $dsuf = ($dcount > 1) ? "[$d]" : '';
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	    push(@imux, "iodev_rdata_$name$dsuf");
 | 
	
		
			
				|  |  | +	    if ($xdev) {
 | 
	
		
			
				|  |  | +		push(@xmux, "iodev_rdata_$name$dsuf");
 | 
	
		
			
				|  |  | +	    } else {
 | 
	
		
			
				|  |  | +		push(@imux, "iodev_rdata_$name$dsuf");
 | 
	
		
			
				|  |  | +	    }
 | 
	
		
			
				|  |  |  	    for (my $i = 0; $i < length($irq); $i++) {
 | 
	
		
			
				|  |  |  		my $isuf = "[$i]";
 | 
	
		
			
				|  |  |  		my $type = substr($irq,$i,1);
 | 
	
	
		
			
				|  | @@ -168,19 +203,34 @@ sub generate_verilog($)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		$nirq++;
 | 
	
		
			
				|  |  |  	    }
 | 
	
		
			
				|  |  | -	    $ndev++;
 | 
	
		
			
				|  |  | +	    if ($xdev) {
 | 
	
		
			
				|  |  | +		$nxdev++;
 | 
	
		
			
				|  |  | +	    } else {
 | 
	
		
			
				|  |  | +		$ndev++;
 | 
	
		
			
				|  |  | +	    }
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      print  $out "\t// I/O input MUX\n";
 | 
	
		
			
				|  |  | -    print  $out "\talways \@(\*)\n";
 | 
	
		
			
				|  |  | +    print  $out "\talways_comb\n";
 | 
	
		
			
				|  |  |      printf $out "\t\tcase (cpu_mem_addr[%d:%d])\n",
 | 
	
		
			
				|  |  | +	$xdev_addr_shift+$xdev_addr_bits-1, $xdev_addr_shift;
 | 
	
		
			
				|  |  | +    my $nxdev = 0;
 | 
	
		
			
				|  |  | +    foreach my $dev (@xmux) {
 | 
	
		
			
				|  |  | +	printf $out "\t\t\t%d'd%d:\t iodev_rdata = %s;\n",
 | 
	
		
			
				|  |  | +	    $xdev_addr_bits, $nxdev++, $dev;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    printf $out "\t\t\t%d'd%d:\n",
 | 
	
		
			
				|  |  | +	    $xdev_addr_bits, (1 << $xdev_addr_bits)-1;
 | 
	
		
			
				|  |  | +    printf $out "\t\t\tcase (cpu_mem_addr[%d:%d])\n",
 | 
	
		
			
				|  |  |  	$iodev_addr_shift+$iodev_addr_bits-1, $iodev_addr_shift;
 | 
	
		
			
				|  |  |      my $ndev = 0;
 | 
	
		
			
				|  |  |      foreach my $dev (@imux) {
 | 
	
		
			
				|  |  | -	printf $out "\t\t\t%d'd%d:\t iodev_rdata = %s;\n",
 | 
	
		
			
				|  |  | +	printf $out "\t\t\t\t%d'd%d:\t iodev_rdata = %s;\n",
 | 
	
		
			
				|  |  |  	    $iodev_addr_bits, $ndev++, $dev;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    print $out "\t\t\t\tdefault: iodev_rdata = 32'hffffffff;\n";
 | 
	
		
			
				|  |  | +    print $out "\t\t\tendcase\n";
 | 
	
		
			
				|  |  |      print $out "\t\t\tdefault: iodev_rdata = 32'hffffffff;\n";
 | 
	
		
			
				|  |  |      print $out "\t\tendcase\n";
 | 
	
		
			
				|  |  |  
 |