URL
https://opencores.org/ocsvn/tcp_socket/tcp_socket/trunk
Subversion Repositories tcp_socket
[/] [tcp_socket/] [trunk/] [chips2/] [docs/] [source/] [tutorial/] [index.rst] - Rev 4
Compare with Previous | Blame | View Log
Tutorial========Create and Test a C component-----------------------------Why not start with a simple example. With your favourite text editor, create afile count.c and add the following::void count(){for(i=1; i<=10; i++){report(i);}}You can convert C components into Verilog components using the C2Verilogcompiler. The *iverilog* option causes the generated Verilog component to becompiled using Icarus Verilog. The *run* option causes simulation to be run::~$ c2verilog iverilog run test.c12345678910When a design is reset, execution starts with the last function defined inthe C file. This need not be called *main*. The name of the last functionwill be used as the name for the generated Verilog component. The C program willappear to execute in sequence, although the compiler may execute instructionsconcurrently if it does not affect the outcome of the program. This will allowyour component to take advantage of the inherent parallelism present in a hardwaredesign.The *report* function is a *built-in* function which is helpful for debug, itwill print the value of a variable on the console during simulations, when yousynthesise the design it will be ignored.This component doesn't have any inputs or outputs, so it isn't going to be veryuseful in a real design. You can add inputs and outputs to a components usingfunction calls with special names. Functions that start with the name *input_*or *output_* are interpreted as inputs, or outputs respectively.::int temp;temp = input_spam(); //reads from an input called spamtemp = input_eggs(); //reads from an input called eggsoutput_fish(temp); //writes to an output called fishReading or writing from inputs and outputs causes program execution to blockuntil data is available. This synchronises data transfers with other componentsexecuting in the same device, this method of passing data between concurrentprocesses is much simpler than the mutex/lock/semaphore mechanisms used inmultithreaded applications.If you don't want to commit yourself to reading and input and blockingexecution, you can check if data is ready::int temp;if(ready_spam()){temp = input_spam();}There is no equivalent function to check if an output is ready to receive data,this could cause deadlocks if both the sending and receiving end were waitingfor one another.We can now construct some basic hardware components quite simply. Here's a counter for instance::void counter(){while(1){for(i=1; i<=10; i++){output_out(i);}}}We can generate an adder like this::void added(){while(1){output_z(input_a()+input_b());}}Or a divider like this (yes, you can synthesise division)::void divider(){while(1){output_z(input_a()/input_b());}}We can split a stream of data into two identical data streams using a tee function::void tee(){int temp;while(1){temp = input_a();output_y(temp);output_z(temp);}}If we want to merge two streams of data, we could interlace them::void interlace(){int temp;while(1){temp = input_a();output_z(temp);temp = input_b();output_z(temp);}}or we could prioritise one stream over the other::void arbiter(){int temp;while(1){if( ready_a() ){temp = input_a();output_z(temp);} else if( ready_b() ){temp = input_b();output_z(temp);}}}
