No modules are the essentially the base or a "toolbox" if you will. You need to inject one module into another so that the it can have access to its "tools" (filters/directives/services etc). The reason is that the module is responsible for dependency loading and order of operations. This is so that when you request a "tool" from a module into a controller you can be sure it is there (or an error will be thrown).
Modules can list other modules as their dependencies. Depending on a module implies that the required module needs to be loaded before the requiring module is loaded. In other words the configuration blocks of the required modules execute before the configuration blocks of the requiring module. The same is true for the run blocks. Each module can only be loaded once, even if multiple other modules require it.
When you inject one module into another you are saying "Module A requires things from Module B". Now when you when you require a specific tool that is when you inject it into the controller so that you have access to that specific tool.
So consider:
var app = angular.module('myApp', ['ngFileUpload']);
app.controller('MyCtrl', ['$scope', 'Upload', function ($scope, Upload) {
.....
Upload.upload(uploadData).then(function (resp) {
//success
}, null, function (evt) {
//upload progress
});
.....
}]);
So because you inject ngFileUpload your controller in the myApp module can now inject the Upload service from the ngFileUpload module and the controller does not need to worry if the service is present (if it is not you will get an injection error from angular).