Forum Discussion
Altera_Forum
Honored Contributor
13 years agoHelp in CRC custom instructions please.
Hello,
I am a new bie in the custom instruction development for Altera and was looking into the way the CRC method is implemented as per the link altera.com/support/examples/nios2/exm-custom-instruction.html I see the main C file which calls the custom instruction as crc_main.c and the custom instruction is crcCI. That function is defined in the file ci_crc.c. In that function, the macro CRC_CI_MACRO is called with the arguments. The macro is defined in the same file as:# define CRC_CI_MACRO(n, A) __builtin_custom_ini(ALT_CI_CRC_INST_N + (n & 0x7), (A)) The macro is being assigned to a built in gnu gcc custom function (if my understanding is correct). My questions are as follows: Where can I see the gnu built in custom function (I mean, in which file). It should expand like a driver level function I guess. And where is the macro ALT_CI_CRC_INST_N being defined? If all the custom gnu gcc functions are in-built, then how is it really a custom instruction? I am struck at this point of thought, please give me some pointers. That would be a huge help.29 Replies
- Altera_Forum
Honored Contributor
Probably doesn't really matter at all.
Just start from a working version of one of the simple Altera configs. Unfortunately none of those seem to pass the timing constraints - so you can't (easily) tell if your logic is too slow! I remember having to drop the clock from 100MHz to 50MHz to get rid of some very strange errors! Although I wrote the custom instruction vhdl (the only vhdl I've actually written) and tested it on one of the cyclone III boards, it got built into out main image which runs on an arria II (I think) by the hw team. Writing custom instructions is probably a good way for reasonably experienced software engineers to get to understand VHDL. If there were better examples it would help! - Altera_Forum
Honored Contributor
Hello,
I have experimented with the altera examples of CRC and was successful in bringing up the custom instruction on the DE1 board. Now I have questions on the way in which I should implement the custom instruction for arbitrary precision integer addition (say 128 bit) What I plan is to do a 32 bit + 32 bit addition (since the dataa and datab signals are 32 bit, I dont intend to change the base unit size, let it be 32 bits) for a clock cycle and do the same for 4 clock cycles, so that 32 * 4 = 128 bits in total. Hence I can try to implement a multicycle custom instruction which runs for four clock cycles and after that, returns the 'result' signal. Here, I would have to save the 'carry out' bit and the 'result' signals for each and every stage. I think since the 'result' port is an output port, that data can be saved somehow. However, the 'carry out' bit has to propagate to the next stage of adder as the 'carry in' bit. I was wondering how to do this? Do I have to use External Interface Custom Instructions ? I read that a multicycle Custom Instructions Allow the Addition of an External Interface. Figure 1.9 in the NIOS II custom instruction user guide. I sentence which captivated me was "Custom instruction logic can perform various tasks such as storing intermediate results or reading memory to control the custom instruction operation." Please give me some pointers here, that would be a great help. Thank You, Akhil - Altera_Forum
Honored Contributor
You could generate logic that has a single accumulator, with separate instructions to add/subtract (etc) the input A:B (or B:A !) value from it.
Use the rC field (with writerc unset) to decide what to do. These instructions could return 'done' immediately, and carry on any processing in the subsequent clocks. You might want to add a 'stall' if the previous instruction hasn't finished. To read the result use the A or B field (unset readra/readrb) to select which 32bit result to return, and set writerc to the value is actually written to the register file. - Altera_Forum
Honored Contributor
Hello dsl,
Can you please explain to me a little bit more? I am still trying to understand the ways in which it can be implemented. I believe you intend me to use the 'Internal Register File Custom Instructions' than the 'External Interface Custom Instructions'. And by pulling the 'writerc' signal low, we can save the SUM output value to an internal register which can be addressed by c[4:0]. Please note that my full adder module can have a 'Carry Out' bit as well, which has to be propagated from one adder module to another. I was wondering how to store this? Since there is only one output port to a custom instruction (that is 'result') and that port is already used to store the SUM. The design I planned to use was something like this: Say if I need a 128 bit adder, then I will cascade 4 32 bit full adders. Please see the attached Full Adder Design text file which is attached. I am having a lot of questions here, like is it possible to cascade the four custom instruction blocks, or a better approach is to have a counter inside the custom design and do the instructions for four clock cycles, in each and every clock, read the cout bit and update the cout bit. In this case I guess I will have a space inside my accumulator where I can store intermediate carry out and result values. And raise the 'Done' signal after counting 4 clock cycles and doing the operations with it. Please advice me here, that will be a huge help. Thank You, Akhil - Altera_Forum
Honored Contributor
If your instruction has writerc low, then the cpu fabric doesn't do anything with any value on the 'data out' lines at the end of the instruction.
What the c[4:0] bits are then used for is entirely up to the implementation of your custom instruction. You could choose to use them to index some local register file, OTOH you could use them for anything else you want to - maybe as an internal opcode. I'd consider using the c[4:0] bits (with writerc low) to determine what to do with the A and B values. And the b[4:0] bits (with writerc high, readrb might as well be low) to determine which value to return. Or some similar scheme. You might want to use a second combinatorial custom instruction for the reads, that would avoid the 'late result' penalty. - Altera_Forum
Honored Contributor
Hello dsl,
Thank you for the reply! I think I am able to understand what you are saying here. I believe I have to come up with some sort of accumulator design to store the intermediate values between the clocks. I have a couple of questions here as well. 1) How to give the input ports c[4:0] some value when we call the corresponding macro from the custom instruction from the application C code in NIOS II IDE? I designed a small verilog with c[4:0] and writerc ports in it. However after a build in NIOS II I looked into the 'system.h' file and see my custom instruction macro as: # define ALT_CI_CUSTOM_COMPONENT_ADD_INST(n,A,B) __builtin_custom_inii(ALT_CI_CUSTOM_COMPONENT_ADD_INST_N+ (n&ALT_CI_CUSTOM_COMPONENT_ADD_INST_N_MASK),(A),(B)) I was wondering how the processor will act as the master and gives the signals like clk, clk_en, reset, start, writerc, c[4:0] etc to the verilog modules. Is there some way in which I can set those values while running the code from NIOS II or even from the Quartus SOPC builder? The custom instruction manual does not give any clue regarding these. 2) Is there a pin trace (like gtk wave utility) from NIOS II using which I can see the port values while running the code from NIOS II IDE. That will really help me a lot to understand the signals. I hope the questions are clear here. Thanks in advance for your response. Thank You, Akhil Kalathungal - Altera_Forum
Honored Contributor
Hello,
I think I have to stop looking into the custom instruction implementation for the arbitrary precision logic since the custom instructions are not really flexible. In my case if the custom instruction lasts for four clock cycles, I need to sample the new values for dataa and datab every clock cycle. However, the definition of a multicycle custom instruction needs the operands dataa and datab to remain constant for that many number of clock cycles for which the custom instruction runs. So in this case, I might have to wait for four clock cycles to get the result of first 32 bit + 32 bit addition which does not serve the purpose of accelerating the speed of the instruction. Another approach is to make the custom instruction hardware modules combinatorial and write to memory every time the sum and the carry and read from memory (the earlier carry) for the next set of 32 bit operands addition. This will also have the bottleneck of making the verilog hardware modules talk to the memory for each and every clock cycle. So I guess I have to look into some other mode of Hardware Acceleration. I think I shall try to implement some hardware accelerators (IP cores) from the SOPC builder. Please try to correct me if I am going in a wrong direction here. Any inputs are appreciated. Thank you, Akhil - Altera_Forum
Honored Contributor
Hello,
Can someone reply in this thread please? I would really appreciate if I get some ideas. Since I am a beginner (dumb :() in this area, I would like someone to comment which will be really helpful. Thanks. - Altera_Forum
Honored Contributor
I agree with your assessment, using custom instructions can be very restrictive. You will have a lot more flexibility if you design your own SOPC component with an Avalon Memory Mapped slave interface. You can have as many registers as you want and use as many cycles as you want to perform your operation.
If you have big transfers between your core and the main memory you could also implement a Memory Mapped master interface that can directly read/write to the memory but it is a bit more tricky to implement. I think the SOPC user manual as an example with a checksum hardware core that does exactly this. - Altera_Forum
Honored Contributor
Hello Daixiwen,
Thank you for the reply. And I think I have seen that checksum hardware accelerator example in the SOPC user manual. The issue with that is, that is too much a high level for a beginner to start with. It does not explain how to create a sw.tcl file and the *.c and *.h driver files (I think all those files are to be hand-coded). Also the build process explains a NIOS II SBT build, and which is specific for a Cyclone IV device. I use the DE1 board here, which has the Cyclone II device in it. So is there any simple example for the SOPC builder component which I can refer to? That would be a huge help. Thank You, Akhil