Test-Driven Development ('TDD') is a technique that allows you to build hardware quickly, and to have confidence that it works, by writing the test code before writing the RTL code. The procedure concentrates on specific features, or requirements, which are added incrementally. For each new feature, the process of writing a test forces the the developer to concentrate on the specification, and the requirements, for that feature. Once the feature is understood, the developer writes a new unit test for that feature. The RTL code is now written, and is known to be functional when the test passes.
The process of writing and testing the RTL code is, in general, an iterative process. When the new unit test is run for the first time, it will of course fail, because the functionality does not yet exist. The feature should initially be added in any form that will allow the old and new tests to pass: it might, for example, simply be a behavioural model. When the tests pass, the developer can iterate the process of refining, or refactoring, the RTL code, and confirming that the old and new tests still pass, until the code is suitable for production use.
The key to TDD is therefore to break the device down into manageable units, and to follow these steps for every unit, or every new feature which is to be added to the device:
- Write a unit test for the new functionality
- Confirm that the new test fails
- Write the new RTL code so that the old and new tests pass. This is simply a first iteration, and does not have to be production-ready: it should instead be the minimum that is required to make the tests pass
- Refactor and refine the new code as required to improve the structure, and meet any area or timing requirements
- Confirm that the old and new tests still pass, and repeat from step 4 until the requirements have been achieved
TDD has been used in software development for the past 20 years, or longer, and is a cornerstone of Extreme Programming (XP), and agile methods in general. A large number of benefits are generally claimed for TDD development, but the most obvious ones are:
- The unit tests give you immediate feedback on whether any changes to the code base have broken existing functionality
- The unit tests become the functional specification for the device features
- Since the TDD 'use cases' are expressed as tests, others can use the tests as usage examples of how the code is intended to work
In other words: faster development times, fewer bugs, easier isolation of those bugs, and more confidence that the device will function as intended.