FPGA Intellectual Property
PCI Express*, Networking and Connectivity, Memory Interfaces, DSP IP, and Video IP
6260 Discussions

How to implement a C routine to VHDL?

Honored Contributor II


I am trying to rewrite C routine for ethernet (sending of a packet) to VHDL. And I would like to know, how can I write command for setting up some configuration in ethernet driver registry. 

For example I have this function in C: 


void iow(unsigned int reg, unsigned int data) { IOWR(DM9000A_BASE,IO_addr,reg); usleep(STD_DELAY); IOWR(DM9000A_BASE,IO_data,data); }  


Specifically without constant: 

void iow(unsigned int reg, unsigned int data) { IOWR(0x11000,0,0x01); usleep(20); //us IOWR(0x11000,1,0xFF); }  


In the datasheet for DM9000A there are pins: 

iow (write), cs (chipselect), cmd (commad - index or data), sd0~7 (data) 


In compare with C: 

iow = IOWR 

cmd = IO_ADDR or IO_DATA 

sd0~7 = reg or data in argument of function 


So VHDL should be: 

iow <= '0' -- active in low for writting cs <= '0' -- active in low cmd <= '0' -- i want to write index ... -- delay 10ns sd <= x"01" -- i want registry with offset 0x01 .. -- delay 20us cmd <= '1' -- i want to write data ... -- delay 10ns sd <= x"FF" -- i want set registry to value 0xFF  


And my questions are: 

What is correct way to implement this? 

How can I implement a delay like usleep() in C? 

Can I put this sequence in VHDL to some procedure? 


I would be glad for your advice
0 Kudos
6 Replies
Honored Contributor II

Synthesizable VHDL has no concept of delays or sequential programming like in C. 

Only things that can be implemented with sequential (flip-flops, RAM) and combinatory logic. 


Therefore, you need to implement a state machine and counters to implement the delay. 

Something like this: 


process (clk) -- 100 MHz clock, 10 ns period 

if rising_edge(clk) then 


if state = state:1 then 

iow <= '0'; cs <= '0'; cmd <= '0';  

state <= state_2; 

elsif state = state_2 then 

sd <= x"02", 

delay_counter <= 2000; -- 2000 * 10 ns = 20 µs 

state <= state_3; 

elsif state = state3 then 

if counter = 0 then 

state <= state_4; 


counter <= counter - 1; 

elsif state = state_4 then 

cmd <= '1'; 

state <= state_5; 

elsif state = state_5 then 

sd <= x"FF; 


end if; 

end process
0 Kudos
Honored Contributor II

And is it appropriate to use a state machine with a lot of states if I have more these "register settings"? Or I should use for example procedure set_reg(reg,value)? I am afraid of its influence on the complexity of structure in FPGA.

0 Kudos
Honored Contributor II

As a first point, you should study the DM9000 bus timing requirements. Your above example won't work correctly, because it doesn't keep the IOW setup- and hold times. Using a state machine for the elementary read and write access sequence sounds reasonable. Most likely a second state machine should be responsible to schedule the command sequences.

0 Kudos
Honored Contributor II


In the attachment, there is a timing of DM9000A IOW, I suppose that there is a requirement for setup and holt time only in "sd" data case (10ns for setup and 3ns for hold)? 

And as you said - second state machine, do you thing something like this (example)? I think If I have a maximum delay 10ns, so one clk period with 50MHz frequency (T = 20ns) should be enough, right? 


IF (clk'EVENT AND clk = '1') THEN CASE state IS WHEN s0=> IF input = '1' THEN state <= s1; ELSE state <= s0; END IF; WHEN s1=> IF input = '1' THEN state <= s2; ELSE state <= s1; END IF; WHEN s2=> IF input = '1' THEN state <= s0; ELSE state <= s2; END IF; END CASE; END IF; END PROCESS; PROCESS (state) BEGIN CASE state IS WHEN s0 => -- delay 10ns WHEN s1 => -- delay 20ns WHEN s2 => -- delay 5us END CASE; END PROCESS;  


* sorry for small image in the attachment, I haven't got enough of posts for url.
0 Kudos
Honored Contributor II


--- Quote Start ---  

I suppose that there is a requirement for setup and holt time only in "sd" data case 

--- Quote End ---  


Your initial example is also violating T1. 


There are some more points to consider, I won't elaborate a single detail now. If you want to squeeze DM9000 timing, you possibly should provide a faster clock for the state machine. Or implement double data rate output registers for some signals to achieve a finer timing control. 


P.S.: I just realized the difference between DM9000 (which I previously used) and DM9000A. The timing has been considerably improved.
0 Kudos
Honored Contributor II

I found out, that if I want to intialize DM9000A from Nios, I have to solve some addressing.  

My intention is to make a interface which receives data from stream, makes a ethernet packet from data and sends it to the DM9000A. 

But at the beginning I have to initialize my "transceiver" with MAC, IP address, IP header... and DM9000 with some settings too (interrupts, etc). 

I have Avalon master -> my VHDL transceiver -> DM9000A, transceiver is addressable, but DM9000A not. So I have to place some bidirectional Avalon parallel I/O port between my transceiver and DM9000A because of addressing its ports from Nios. 



1. Initialize my transceiver from Nios 

2. Initialize DM9000A from Nios via parallel port between transceiver and DM9000A 

3. No more initalizion. Transfer data from stream to DM9000A 


Is Avalon parallel port in front of DM9000A right way for initialization at the beginnig?
0 Kudos