Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12745 Discussions

multicycle instruction FSM with nios and the done variable

Altera_Forum
Honored Contributor II
2,455 Views

I have been trying for weeks to figure out how the done variable works and it seems like it has no effect whatsoever on the program. Can anyone explain how it works.  

 

Here's an example i've been working on: 

 

if (reset = '1') then 

state <= s0; 

ELSIF (clk'EVENT AND clk = '1') THEN 

CASE state IS 

WHEN s0 => 

IF (start = '1' AND n = '0') THEN 

io_148194546 <= dataa; 

io_277277265 <= datab; 

state <= s0; 

done <= '1'; 

ELSIF (start = '1' AND n = '1') THEN 

io_109970892 <= dataa; 

io_19111827 <= datab; 

state <= s1; 

done <= '1'; 

ELSE 

state <= s0; 

done <= '0'; 

END IF; 

WHEN s1 => 

result <= io_1298736395; 

done <= '1'; 

state <= s0; 

WHEN OTHERS => 

report "Invalid State"; 

END CASE; 

END IF; 

END PROCESS; 

 

When I do something like: 

ALT_CI_CI_HARDWARE_INST(0,2,4); 

y = ALT_CI_CI_HARDWARE_INST(1,5,8); 

 

i can't the result from the past operation in y. So if i want to get the actualy value of y, i need to do something like 

ALT_CI_CI_HARDWARE_INST(0,2,4); 

y = ALT_CI_CI_HARDWARE_INST(1,5,8); 

y = ALT_CI_CI_HARDWARE_INST(1,5,8); 

 

Thanks
0 Kudos
8 Replies
Altera_Forum
Honored Contributor II
874 Views

Here's the whole code. To summarize last post: 

Have to do y = ci(1,x,y) twice to get the result. Otherwise I get the result from the alst operation. 

 

-- Generated VHDL code to implement Custom Instructions -- CREATED: Thu Dec 02 10:20:48 EST 2010 library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; ENTITY CI_HARDWARE IS PORT ( SIGNAL clk : IN STD_LOGIC; SIGNAL reset : IN STD_LOGIC; SIGNAL clk_en : IN STD_LOGIC; SIGNAL start : IN STD_LOGIC; SIGNAL done : OUT STD_LOGIC; SIGNAL dataa : IN STD_LOGIC_VECTOR(31 DOWNTO 0); SIGNAL datab : IN STD_LOGIC_VECTOR(31 DOWNTO 0); SIGNAL result : OUT STD_LOGIC_VECTOR(31 DOWNTO 0); SIGNAL n : IN STD_LOGIC ); END CI_HARDWARE; ARCHITECTURE behavior OF CI_HARDWARE IS TYPE state_type is (s0,s1); SIGNAL STATE : state_type; SIGNAL io_148194546 : STD_LOGIC_VECTOR(31 DOWNTO 0); SIGNAL io_277277265 : STD_LOGIC_VECTOR(31 DOWNTO 0); SIGNAL io_109970892 : STD_LOGIC_VECTOR(31 DOWNTO 0); SIGNAL io_19111827 : STD_LOGIC_VECTOR(31 DOWNTO 0); SIGNAL io_1556901833 : STD_LOGIC_VECTOR(31 DOWNTO 0); SIGNAL io_1685984552 : STD_LOGIC_VECTOR(31 DOWNTO 0); SIGNAL io_1298736395 : STD_LOGIC_VECTOR(31 DOWNTO 0); COMPONENT lpm_add_sub GENERIC ( lpm_direction : STRING; lpm_hint : STRING; lpm_representation : STRING; lpm_type : STRING; lpm_width : NATURAL ); PORT ( dataa : IN STD_LOGIC_VECTOR(31 DOWNTO 0); datab : IN STD_LOGIC_VECTOR(31 DOWNTO 0); result : OUT STD_LOGIC_VECTOR(31 DOWNTO 0) ); END COMPONENT; COMPONENT lpm_mult GENERIC ( lpm_hint : STRING; lpm_representation : STRING; lpm_type : STRING; lpm_widtha : NATURAL; lpm_widthb : NATURAL; lpm_widthp : NATURAL ); PORT ( dataa : IN STD_LOGIC_VECTOR(31 DOWNTO 0); datab : IN STD_LOGIC_VECTOR (31 DOWNTO 0); result : OUT STD_LOGIC_VECTOR(31 DOWNTO 0) ); END COMPONENT; BEGIN lpm_sub_0 : lpm_add_sub GENERIC MAP ( lpm_direction => "SUB", lpm_hint => "ONE_INPUT_IS_CONSTANT=NO, CIN_USED=NO", lpm_representation => "SIGNED", lpm_type => "LPM_ADD_SUB", lpm_width => 32 ) PORT MAP (io_148194546, io_277277265, io_1556901833); lpm_mul_0 : lpm_mult GENERIC MAP ( lpm_hint => "MAXIMIZE_SPEED=5", lpm_representation => "SIGNED", lpm_type => "LPM_MULT", lpm_widtha => 16, lpm_widthb => 16, lpm_widthp => 32 ) PORT MAP (io_1685984552, io_1556901833, io_1298736395); lpm_add_0 : lpm_add_sub GENERIC MAP ( lpm_direction => "ADD", lpm_hint => "ONE_INPUT_IS_CONSTANT=NO, CIN_USED=NO", lpm_representation => "SIGNED", lpm_type => "LPM_ADD_SUB", lpm_width => 32 ) PORT MAP (io_109970892, io_19111827, io_1685984552); PROCESS (reset, clk) BEGIN if (reset = '1') then state <= s0; ELSIF (clk'EVENT AND clk = '1') THEN CASE state IS WHEN s0 => IF (start = '1' AND n = '0') THEN io_148194546 <= dataa; io_277277265 <= datab; state <= s0; done <= '1'; ELSIF (start = '1' AND n = '1') THEN io_109970892 <= dataa; io_19111827 <= datab; state <= s1; done <= '1'; ELSE state <= s0; done <= '0'; END IF; WHEN s1 => result <= io_1298736395; done <= '1'; state <= s0; WHEN OTHERS => report "Invalid State"; END CASE; END IF; END PROCESS; END behavior;
0 Kudos
Altera_Forum
Honored Contributor II
874 Views

The timing of the done bit is probably off. I recommend simulating the instruction by itself so that you'll be able to see the behavior of the done bit. If nothing shows up as wrong then try simulating the system and seeing how it behaves hooked up to the Nios II core.

0 Kudos
Altera_Forum
Honored Contributor II
874 Views

I've been testing it on a DE0 board using a NIOS 2/e core with the custom instruction added. Out of testing it on the board, nothing happens if i remove it completely, have it all 0s, have it all 1s, it's like the done bit doesn't do anything at all...

0 Kudos
Altera_Forum
Honored Contributor II
874 Views

Running it in hardware isn't going to tell you what the problem is. The done bit tells the processor when to complete the instruction and latch the result. 

 

Judging by the statemachine it looks like done bit is stuck high. Again a simulation would catch this easily.
0 Kudos
Altera_Forum
Honored Contributor II
874 Views

oops, i posted the wrong version of the FSM code. the only diff is that i have done <= '0' in the n=1 case in state s0. The simulation also works as I expect it to, an image of it is included at the bottom. But if I run the code on a nios II core on the DE0 board, it doesn't work. The results are delayed as described above with the same code. 

 

here's the good version of the code: 

PROCESS (reset, clk) BEGIN if (reset = '1') then state <= s0; ELSIF (clk'EVENT AND clk = '1') THEN CASE state IS WHEN s0 => IF (start = '1' AND n = '0') THEN io_148194546 <= dataa; io_277277265 <= datab; state <= s0; done <= '1'; ELSIF (start = '1' AND n = '1') THEN io_109970892 <= dataa; io_19111827 <= datab; state <= s1; done <= '0'; ELSE state <= s0; done <= '1'; END IF; WHEN s1 => result <= io_1298736395; done <= '1'; state <= s0; WHEN OTHERS => report "Invalid State"; END CASE; END IF; END PROCESS; END behavior; http://skiareatrailmaps.com/images/simulation.JPG
0 Kudos
Altera_Forum
Honored Contributor II
874 Views

Start shouldn't be asserted for more than one clock cycle. So you should see a start strobe with a valid dataa and datab input, then when your custom instruction is complete you preset the valid data output with the done signal asserted.

0 Kudos
Altera_Forum
Honored Contributor II
874 Views

Hello, thanks for helping 

 

If i put start=1 just for one clock cycle, there is no result given in the simulation. If I put start for both of the 2 sets of inputs (so 2 cycles), i get the results i expect as shown in the image below (Fig 1). Maybe I don't have the SOPC set up correctly.  

 

-I have a NIOS2/e core to which i added the custom instruction as a CI slave and didn't change any of the settings there. Maybe there needs to be a variable in "Clock Cycles" when i add the CI as shown in Fig2. 

-on chip memory 

-sysid 

-jtag uart 

 

As i said, the CI works from NIOS in the c program, but the result is delayed by a call, so i have to call (1,x,y) twice to get the result.  

 

http://skiareatrailmaps.com/images/simulation2.JPG  

http://skiareatrailmaps.com/images/compoment_editor.JPG  

 

Also, tried changing the code to this, but no change. Don't know if I understood what you meant. 

 

if (reset = '1') then state <= s0; ELSIF (clk'EVENT AND clk = '1') THEN CASE state IS WHEN s0 => IF (start = '1' AND n = '0') THEN io_148194546 <= dataa; io_277277265 <= datab; state <= s0; done <= '1'; ELSIF (start = '1' AND n = '1') THEN io_109970892 <= dataa; io_19111827 <= datab; state <= s1; done <= '0'; ELSE state <= s0; done <= '1'; END IF; WHEN s1 => result <= io_1298736395; done <= '1'; state <= s0; WHEN OTHERS => report "Invalid State"; END CASE; END IF; END PROCESS;  

 

Thanks again!
0 Kudos
Altera_Forum
Honored Contributor II
874 Views

But the Nios II custom instruction master will only assert 'start' for one clock cycle. You pasted an image from component editor that shows this so if you attempt to simulate with the start signal asserted for longer than that you are not even mimicking what the processor will drive into the custom instruction which seems like a waste of time to do. 

 

For more details: http://www.altera.com/literature/ug/ug_nios2_custom_instruction.pdf 

 

Page 12-13 describe the timing of a multicycle custom instruction.
0 Kudos
Reply