FPGA flow lamp Experiment

Source: Internet
Author: User
Tags case statement constant definition

Source code: http://pan.baidu.com/s/14H8D4

FPGA flow lamp Experiment

It took a few days to summarize the modeling skills of VerilogHDL learned through the experiment of the streaming lamp. Write a summary to develop a set of specifications for you to view and solve problems later.

Goals:

Serial work, pipeline work (Time Parallel), and parallel pipeline work (space parallel) are realized through the experiment of the streaming lamp ). Serial work is the way the CPU works, that is, only one thing can be done at a time. Using VerilogHDL can completely imitate this way of work, that is to say, the algorithms and drivers implemented by the CPU can be completely converted to the corresponding VerilogHDL. In addition, the thought of structured program design (sequence, selection, and loop) can also be implemented through VerilogHDL. In addition to serial work, VerilogHDL also has the advantages of the difficult-to-implement pipeline (Time Parallel) and parallel processing (space parallel) by the CPU. Of course, the current multi-core CPU can also achieve parallel processing through multi-thread programming, but the implementation is relatively complicated. FPGA can implement unlimited parallel processing theoretically as long as there are enough logical resources.

That's why I like FPGA best. You only need to learn a hardware description language. The integrated modules can be written on FPAG, ASIC, or CPLD of different manufacturers. High portability. You do not need to learn a variety of single-chip microcomputer. Different modules can only process one module at a time and stop another module, resulting in poor real-time performance.

The experiment of the flux lamp is based on the flux lamp as the prototype to implement the serial and parallel operation mode. Four LED lights indicate four different steps for completing one task, and one LED flash indicates completing one step at a time.

Sequential work:

Note: Work in sequence to prepare data at T0, process data at T1 to T4, and process data at T16 until data is processed by, data processing shares 16 time points (step count M * Data Count N), and the time complexity is O (M * n ).

The sequence diagram is as follows:

Assembly line:

Note: The pipeline works to prepare data at t0 time, and the first execution time is from T1 to T4. Next, each clock completes one data. Data is processed at seven times. (Step number M + (Data number N-1), time complexity is O (n ).

Parallel pipeline work:

Note: The parallel pipeline works in multiple pipelines at the same time. Data is prepared at t0 time. The first execution time is from T1 to T2, and each clock processes one data. Data is processed at three times. (Steps m + (data N/number of pipelines t-t), time complexity is O (n/T ).

From the time complexity of the above three methods, we can see that the time for pipeline data processing is 1/m in serial mode, while the time for parallel pipeline data processing is 1/T in a single pipeline. This is a way to change the space for time, which can achieve higher efficiency at the cost of consuming more space. For the generation of ultra-large-scale integrated circuits, the cost is reduced and the cost-effectiveness can be improved by changing the space for time. VerilogHDL makes this design method very simple, and parallel stream processing data cannot be replaced by a general processor.

Code conventions:

VerilogHDL is a continuously improved process-oriented language. After reading the relevant grammar books, I found that I did not find a proper and complete syntax structure. Most of the VerilogHDL grammar books only talk about related usage, and the state machine writing is also time-consuming. A variety of Integrated languages and verification languages are mixed together, learning is like a blind person, and cannot find a direction. During code writing, a set of conventions are found based on the code writing principles to standardize modeling. Make full use of the larger possible rows of VerilogHDL.

The history of code writing is the process from the beginning of Code Composition program, to the module composition program, and then to today's object composition program. The quality of object-oriented programming language is controversial. Before I began to formulate the conventions, I had the idea to introduce object-oriented programming methods to encapsulate each module, and then provide interfaces through functional tasks inside the module to achieve high abstraction. To achieve the same modeling as things in actual operation. However, the attempt failed. VerilogHDL does not provide such syntax support, and tasks and functions in VerilogHDL are not the same as those in advanced languages. However, object-oriented thinking is really good and simple. For example, an LED object can be used to enable or disable LEDs. After analyzing the relevant features, modeling will simplify the problem. In addition, the modules in VerilogHDL also have features similar to object-oriented classes.

Write codeThe primary task is management complexity., Research shows that the human intelligence model that can be followed at the same time is 7+2. nested attention usually does not exceed layer 5. When writing a piece of code, it is easy to focus on more than 9 points. Using Intelligent training to focus on the number of intelligent models has little effect. Therefore, in order to be able to write any large-scale code, it is very effective to reduce the number of intelligence models that focus on at the same time. Moreover, software engineering is developed based on relevant programming specifications and restrictions on programming. Although VerilogHDL is a hardware description language, it has been freed from the original circuit diagram input method and has a higher abstraction. Therefore, it should be able to improve development efficiency through similar conclusions in software development. Just like programming with advanced languages with machine code 01. In my opinion, VerilogHDL is more like an assembly language in imitating sequential operations, because it does not implement the order, selection, and loop structure related statements. Structured Design is a milestone in programming and a proven technique. Therefore, introducing structured design to VerilogHDL for modeling can improve modeling efficiency.

Structured design is based on the theory that any program can use sequence, selection, and iteration (often called loops) to implement three structures. In simple terms, the structured design principle is that the process of a program is designed in a top-down manner without any jump in the process. For small-scale programming, arbitrary jump in the program is very flexible and fast. But it does not conform to people's logical thinking methods. Logical thinking is top-down, and it is easy to forget the front when thinking about it. Therefore, according to the structured program design, the hardware modeling conforms to the human logic mode, and can be designed in a straight-line way from top to bottom.

Although there are many similar concepts for advanced language programming and VerilogHDL modeling, they are actually different. VerilogHDL is designed for hardware. To differentiate the concept, compile the code of VerilogHDL as modeling.

Variable name conventions

In modeling, I used a variable convention similar to Java. The variable naming convention for Java is complete and universal together with the Java language.

Reg, wire, and other common variables are named in the lower case of the first letter, followed by each letter starting with an upper case, and other letters in the lower case. Macro definition and constant definition names are all capitalized. Task, function, and module names start with each letter in upper case, and other letters in lower case.

It also involves the names with four special variables, clock (CLK), reset (rst_n), module call start (startsig), and module feedback end signal (donesig ). These four variables are common input and output variables of the module. Therefore, in modeling, the four variable names are no longer named as other variables.

Prefix Reg indicates the register variable that drives an output variable, is indicates the Enable register variable that drives an output variable, and _ n indicates that the low level of the input and output variables is valid.

In modeling, the module can be roughly divided into four categories. Therefore, there are four general conventions: _ interfac interface module. This module does not contain any control and is only used to establish interfaces of external components; _ dirve driver module. This module is a control module that connects to an external module and has an independent driver function. _ control module, it is a module used to coordinate the control functions between modules. Other modules without suffixes are functional modules, and each module can complete independent functions.

Variable naming rules are just a reference and can be used as constraints. In actual situations, variable names are complex. Use conventions to take advantage of management complexity. Be careful when you do not use the appointment for better reasons to avoid errors.

Modeling description:

Several techniques of software programming are used in the modeling process to control the complexity of the system. FollowAbstraction, encapsulation, high cohesion, loose couplingModeling skills, and the useBuild a prototype, AndCode ReadingAudit methods, timely find errors, and minimize the cost of modifying errors.

First, the abstract data type is established from the top layer with LED lights as the object. Only simple ON and OFF operations can be performed on the LED lights. Then, the minimum prototype of the LED lamp is established from the perspective of code at the underlying layer. The minimum prototype I created at the beginning was a module that contains a timer and a LED flip timing logic prototype, enabling timed switch of LED lights. Simulation results show that the timing sequence is correct. Finally, check the Logic Rationality of the Code through code reading.

Related experimental data shows that this programming method is efficient. Because the time when an error is detected is later than the time when the error is generated, the cost of modifying the error is higher. It may even cause irreparable errors and can only be rebuilt. Therefore, even if checking and modifying errors is an effective way to improve efficiency and quality, the development cycle and completion rate are usually very high.

The second step after the prototype is completed is to encapsulate the module accordingPrinciples of one module and one functionAnd separate the timer timing logic from the LED flip timing logic. The complexity is not reduced, but it is transferred to two modules, so that the code concerned at one time is effectively controlled. This method can control any large system complexity. This makes it possible to implement ultra-large systems.

The following uses the code of the lamps as an example to describe various modeling techniques in the ascending order:

Here are the led_control module and led_driver module. Led_driver implements high abstraction and encapsulation of the control led switch. To control each LED, you only need to give it a flashing cycle and start signal, the LED will flash continuously according to a flashing cycle, and each flashing completion gives a complete signal.

This module is created in the form of a module array. Note that it creates led_size led_driver. Each input and output port is (number of BITs * led_size), and the external signal is automatically matched according to the number of bits. If the signal bit is insufficient, it will automatically repeat. For example, the led_size led_driver has led_size clock, but the input clock bit is only one bit. Therefore, the one-bit clock will be automatically extended to the led_size bit. In addition, the led_driver has a 13-bit signal set for the flash period, and the led_size led_driver has led_size * 13, in this way, the [] of the input signal matches the 13-bit flash cycle corresponding to the first led_driver, the [] of the input signal matches the 13-bit flash cycle corresponding to the second led_driver, and so on.

Using the module array is a very effective method, which avoids repeated write of led_driver multiple times and disconnects them. This makes it difficult to find errors because multiple modifications are required when one of them is modified. The module array can also solve this problem and help encapsulate and abstract modules. In the initial code, I wrote the repeated modules in one module to achieve the flickering effect of four flow lights, and the four led flip modules were controlled by the same timer. During the encapsulation process, we found that the four LED driver modules did not achieve high cohesion, that is, four LED modules shared one timer. The module array indicates that each led_driver is independent. The control of four LED lights should be the same as that of one LED lamp. Then I encapsulate one LED module and one timer into one led_driver. It is instantiated four times through the module array. Because each led_driver module is independent, the coupling degree between each LED is reduced and loose coupling is achieved. This makes it easy to extend the control of four LEDs to any number of controls. This is throughEncapsulate the High Cohesion and loose coupling of the module ArrayAt the same time, it also completed a higher level of operations on the led_driver, so that each LED operated on stood at the abstract layer, rather than the underlying layer.

At the underlying layer, you need to consider how many times the timer is flipped to reach this time, and then use this time to turn on or off the LED, so that the problem to be considered is complex and prone to errors. In the abstraction layer, you only need to enable or disable the led to automatically complete the flip. Abstraction is also a way for the human brain to process information. For example, you may not know the color of the door or the style of the door handle. The human brain's processing of the door is abstract. It is a door that can be opened and closed. You only need to know that you can enter the home without remembering the color of the door.

There are several macro definitions in the header of this module to centrally manage the constants to be set. The code can be transplanted. Here we define four LEDs, which can be easily changed to eight. You only need to modify them once, instead of fixing the mysterious numbers everywhere in the code, reduces the possibility of errors. At the same time, the use of macro definitions damages the loose coupling between modules. The same macro definition may be referenced in multiple modules. Unexpected problems may occur if you do not pay attention to it, this makes it impossible to locate problems in a module. Relatively speaking, the parameter quantity (parameter) is used instead of the macro definition to define the mysterious numbers of the same constants in a module, so that the complexity can be managed for centralized modification and the modules are loosely coupled. The advantage of macro definition is to set the related constants to the beginning. During transplantation, you only need to modify them in the same place to avoid finding parameters everywhere in the code. Therefore, the principle here is to prioritize the use of parameter quantities to define Mysterious Numbers and control constants in a centralized manner. Then, use the macro definition in the abstract process as needed. A constant that does not need to be modified is defined as a parameter.

Led_control module:

This is the core part of a module that is a time series logical circuit. The general template is like this. From the perspective of always, generally the timing logic sometimes has the clock and reset signal, so the standard always header is written in this way. The clock rising edge works, and the reset descent edge is asynchronously reset.Use the if reset condition to reset all registers in the always block. These registers are defined on the always block. Where the principle is used and where it is defined. We recommend that you define and use variables on a single screen to reduce the life cycle and span of variables, and manage the number of variables at the same time.

Here I, j, and K are used to simulate the structured design. Generally I is used to represent the execution sequence. J is used to calculate the number of cycles and perform loop jump. In this way, the Order, selection, and cyclic structure of the structured design can be imitated. If you need nested calls, you can use I as the execution sequence of the outer layer, and J as the execution sequence of the inner layer. k is used for cyclic counting. In modeling, these three variables are not used for other purposes. In general, nesting more than three layers is difficult to manage. In this case, the nested layer should be converted into a module call in advance. Generally, these three variables are enough to cope with many situations.

The function of the case statement is similar to that of the state machine to jump between States through input changes. But the idea here is not a traditional state machine. In this way, I borrowed the idea of sequential Modeling in those events in the "those events in the Tilde. The algorithms implemented by the state machine are essentially the same as those implemented by the software and can be converted to each other. However, the traditional state machine needs to analyze various situations and then draw a state transition diagram to map the state to the corresponding code. There are many redundant idling parts in the state machine, and two clocks are required to switch to another State. With this sequential modeling idea, algorithms can be directly mapped to code, skipping the redundant part of the traditional state machine. The conversion between steps requires only one clock. At this time, the design and understanding are more in line with the logical thinking. For example, in the case code, the first step is to call the serial flow lamp task and return the result after the task is completed. Step 2: Call the streamline flow lamp task and return after the task is finished. Step 3: Call the parallel flow lamp task and return after the task is finished. Step 4: repeat the first step. The structured design in programming is introduced into the hardware modeling, so that the logic algorithm implemented by hardware becomes as simple as the program design, and the hardware can easily be pipelines and parallel processing. Make full use of the advantages of hardware logic and eliminate the complicated process of hardware implementation algorithms.

The final assign block is generally used to model the logic of the combination. There is no time sequence control, and the input is output immediately, but the output time cannot be controlled. In this case, it is usually used to assign values to the output signal of the module. The output signal is not declared as Reg type, but the amount of time series logic in the always block is transferred to the output wire type of the assign block through the registers of the intermediate variable. This technique separates the combination logic from the time series logic to manage complexity. The number of generated modules is the same.

The code behind the assign block is the specific implementation process of the preceding three call tasks. Before being encapsulated as a task, a prototype is created in the always block. After the implementation function is tested repeatedly, the task is encapsulated. At the task interface, you must modify the input parameters. The J and K variables in the task are not encapsulated by passing parameters. Instead, they are shared with the module and managed in a unified manner. Because more input and output variables are required by passing parameters, the complexity increases. Therefore, no encapsulation is performed here.

This is a simulation of the cyclic control structure in the task, similar to the JMP usage in assembly language. There is no loop structure in assembly languages like in advanced languages, and structured control can be simulated through conditions and jumps. A similar idea is used here. Here we use a type-until loop (similar to do... While (), you can also easily implement when loop (while () and count loop (for () through conditions and jump ()). Similar Condition structure (if... Else ...) It can also be simulated. In this way, three basic structures of structured programming are formed. It can simulate any program. However, the simulation here will also have a problem similar to the GOTO statement in C language. There is no syntax limit for this jump method. You can execute the previous code and the code that follows it later. Therefore, when using this method, you must follow the top-down structure design philosophy, avoid logical confusion. The general jump statement only redirects backward. The loop structure in this Code does not violate this principle, because the loop structure is repeated for multiple times in the same code segment. After the code is circled in the same place, it continues to be executed and does not jump to the previous part. In general, this code is structured. It has been proved that any program can be implemented through a structured design. Therefore, statements like Goto jump randomly only increase complexity and cause logical confusion.

Loop is mentioned here, and there are also the while and for statements similar to the C language in VerilogHDL, but these statements are different from the loop statements in the advanced language. The advanced language is executed sequentially, so repeated code of the loop statement can be executed multiple times. The while and for statements in verlioghdl generate duplicate instance originals, which cannot achieve multiple executions. Here we need to differentiate and understand, but it looks the same, actually it is different.

The two tasks Implement Parallel Processing pipelines and multiple pipeline structures. VerilogHDL can easily implement pipeline processing and improve data processing speed. However, there must be some restrictions on the establishment of the pipeline, and each step of the pipeline must be synchronized in order to maximize the performance. If the pipeline is not synchronized, the data in the second step is not processed, and the data in the first step is rushed out. Here, the interlock mechanism and the FIFO synchronization mechanism can be used to solve the problem of non-synchronization. However, in this way, the maximum processing efficiency of the pipeline cannot be realized, but parallel processing is much faster than serial processing. This is a way of exchanging space for time. For the development of ultra-large-scale integrated circuits, it will not have a great impact on the price, but improve the performance.

Here we can draw a conclusion that when processing in a sequence similar to the led, the operations in each step can be converted to the corresponding pipeline to improve the data processing capability. Similar examples of multiplier and divider that require continuous shift operations can be converted into a pipeline design. So that different steps can work at the same time.

This led_control module has been very long. Although task encapsulation of intermediate applications greatly reduces complexity, it is also complex enough. The three tasks are all written in an always block. The complexity is hard to imagine, and errors may occur if you are careful, and the time cost of searching for errors in hundreds of lines of code is also high. If you want to add more functions to this function module, You Need To encapsulate these functions into different function call modules, and then use a control module to call them. The principle of separation and governance is a function module. Similar functions use a function to centrally manage calls. Different functional modules are divided into parts. Through this encapsulation, the idea of High Cohesion and loose coupling is highly abstract, making it possible to establish a super large scale system.

Led_control module:

The led_control module is the core of the entire led flow lamp, but it is much simpler. Because it has achieved high abstraction, it only requires a set time and start signal to work. Led_driver_control is used to coordinate the conversion from the external time to the Internal flash cycle, and the output of an Internal flash end signal. It is like creating a fence between the interior and the exterior to map the interior and exterior. Hiding the internal information so that the external can only see the interface, but cannot see how the internal operation works. The advantage of doing so is that when the external device needs to be mounted to another controller, you only need to modify the fence and no major internal adjustment is required. Without this barrier, internal and external changes may lead to reconstruction of the entire interior to adapt to changes. This idea is similar to the three-level database mode and two-level ing and firewall principle. It is very valuable to build a barrier to implement encapsulation.

Next, the timer module and the LED interface module are all very simple steps that are not used for implementation by always.

The timer is the basis of the time series logic circuit, and the generation of accurate timing is the guarantee that the upper layer can work normally. This is the timer for counting Another timer. Note the position of the start signal and the expression in the else condition. The else condition in IF and the default condition in case statements are prone to errors. Therefore, consider carefully. And what signal count (msin )? When will the count be cleared? Here the condition for clearing is that when (setMSTimes-1) msin arrives, clearing the counter. What is prone to errors here is the number of numbers, from 0 to setmstimes. A total of setmstimes + 1 msin. Here, the deviation 1 (off by one) is prone to errors. It can be solved by counting a small number, for example, 5 times, from 0 to 4, so here the number of setmstimes times should be counted from 0 to setMSTimes-1.

The long Boolean expression (msin & (countnms = (setMSTimes-1 'd1 ))),

This involves two decisions and one subtraction in an expression. The length is acceptable. If there are seven or eight logical judgments and addition and subtraction operations for the Boolean expression. This Boolean expression is put here, and some of the following assign blocks are the same. Obviously, this situation is more complex than acceptable. Here we need to use a line network variable with an alternative expression to transfer complexity to control complexity.

Just like extracting the same part and replacing it with a variable name. Although several lines of code are added, the Logical Circuits implemented are the same. It also improves the readability of the Code. This makes the logic clearer. In this case, you only need to adjust the condition for clearing the counter in the corresponding assign block, without considering the other two parts. Here, I started to use the name function in programming to encapsulate the Boolean expression. The result is a completely different circuit, and the desired effect cannot be achieved. The reason is that the VerilogHDL function cannot return the wire variable and cannot implement the desired combination logic. Functions in programming languages are different from function calls in VerilogHDL. Pay special attention when using functions in verilogdhl. It is best not to use functions to avoid errors. Function functions in programming languages are replaced by task and assign blocks.

In the modeling process, each module contains a file, which limits the number of lines of code to a certain number. Limits the complexity of simultaneous attention. After the debugging is complete, all modules are concentrated in one file to facilitate packaging and publishing.

Summary:

The sequential operation, pipeline operation (Time Parallel), and multiple pipeline operations (space parallel) are achieved through the basic flow lamp experiment ). It also verifies the feasibility of structured modeling through VerilogHDL, and can directly convert algorithms into corresponding modules, saving the tedious design process of traditional state machines. The idea of managing complexity as the primary task of programming in software engineering is also suitable for hardware modeling. In addition, the software control complexity method can be introduced into hardware modeling. This improves the efficiency of hardware modeling.

Many of the articles in this article have their own ideas, and I hope to point out some mistakes.

Email [email protected] blog http://blog.csdn.net/d442130165

FPGA flow lamp Experiment

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.