EmbDev.net

Forum: FPGA, VHDL & Verilog Serial/parallel converter VHDL


von Giuseppe R. (owner)


Rate this post
useful
not useful
Hi,
i have an exercise to solve. The specifications are this:
-input serial_in that receives the input bit
-input clock 1200 HZ
-input reset
-output ready
-output parallel_out, a word of 16 bit

the input serial_in read 300 bit/s and present 16 bit on the 
parallel_out and set ready = 1. The convertitor remains in this state 
until reset = 1 and clock = 1 (rising edge), in this case starts a new 
conversion.

I write the following VHDL code. I would to know if it's a correct and a 
possible solution:
1
 
2
library ieee;
3
use ieee.std_logic_1164.all;
4
5
entity convertitore is
6
  port(serial_in, clock, reset: in std_logic;
7
      parallel_out: out std_logic_vector (15 downto 0);
8
      ready: out std_logic);
9
end entity convertitore;
10
11
architecture device of convertitore is
12
  variable output: std_logic_vector(15 downto 0);
13
  begin
14
  
15
    clock: process
16
    begin
17
      clock <= '0', '1' after 416.5 ms;
18
      wait for 833 ms;
19
    end process clock;
20
    
21
    main: process(clock, reset)
22
    begin
23
      if(ready /= '1') 
24
      then
25
        for i in 0 to 15 loop
26
          output(i) := serial_in;
27
          wait for 3.5 ms;
28
        end loop;
29
        parallel_out <= output;
30
        ready <= '1';
31
      end if;
32
      
33
      if(clock'event and clock ='1') then
34
        if(reset'event and reset = '1') then 
35
          ready <= '0';
36
        end if;
37
      end if;
38
    end process main;
39
  end architecture device;

Thank you

: Edited by Moderator
von Vancouver (Guest)


Rate this post
useful
not useful
Giuseppe R. wrote:
> I would to know if it's a correct and a
> possible solution:

No. This is a mixture of a testbench and something else. Why do you have 
a clock input and then generate the clock internally? Why do you trigger 
on the rising edges of reset AND clock? And what do you expect when the 
for loop in the main process is executed? Have you tried a simulation?

I think you should have a very deep look into your VHDL course material 
and start with simpler examples. Write a testbench and a 
device-under-test and have clear interfaces between them. And make 
yourself familar with the use of processes. And avoid using variables as 
long as you are a VHDL beginner.

von Giuseppe R. (owner)


Rate this post
useful
not useful
I need to generate the clock, now i separate a "clock generator" and i 
understand the error.
I also understand that in my case i don't need the sensitivity list, 
because i check inside the process the value of clock and reset.

i didn't undestand the error on loop....

von Giuseppe R. (owner)


Rate this post
useful
not useful
Maybe i can use a internal clock for the 300 bit/s, then i use a process 
triggered by rising time of this internal clock without using a for 
loop?

von Giuseppe R. (owner)


Rate this post
useful
not useful
Something like this:
"i" is a integer counter initialized to 0
"int_clock" is the internal clock for 300 bit/s
"clock" is the clock input
1
 
2
   main: process
3
    begin
4
      if(ready /= '1') 
5
      then
6
        if(int_clock'event and int_clock = '1') then
7
          output(i) := serial_in;
8
          i := i + 1;
9
        end if;
10
        if(i = 15) then
11
          parallel_out <= output;
12
          ready <= '1';
13
          i := 0;
14
        end if;
15
      end if;
16
      
17
      if(clock'event and clock ='1') then
18
        if(reset'event and reset = '1') then 
19
          ready <= '0';
20
        end if;
21
      end if;
22
    end process main;

: Edited by Moderator
von Lothar M. (Company: Titel) (lkmiller) (Moderator)


Rate this post
useful
not useful
Giuseppe R. wrote:
> i didn't undestand the error on loop....
Which error?

The major problem here is, that you are "programming" VHDL like a 
procedural programming language (e.g. C, Basic, Java). That will not 
work. Never!

VHDL is a hardware DESCRIPTION language. And to DESCRIBE something you 
must have a picture of it.

Start with a simple counter mapped to LEDs, simulate it and transfer it 
to hardware. Have a look at the RTL-schematic. It shows you, how the 
synthesizer did understand your DESCRIPTION.
Then change the counters code to count up while a button is pressed and 
to count down while the button is released.
Then sync in and debounce the button and use it to count up your 
counter.
Validate your solutions always with a testbench before going on 
hardware, and have a look at the RTL schmematics.


A few words to some line of your code:
Have a look how a testbench invokes a "device under test". You will need 
knowledge about components for that.

This here is nuts:
1
      if(clock'event and clock ='1') then
2
        if(reset'event and reset = '1') then 
3
          ready <= '0';
This will never go into real hardware, because it is impossible in two 
ways:
1. never ever you will have two rising edges of two signals at the 
very same moment.
2. there is no "double clock flipflop" with two seperate clock inputs on 
any FPGA/CPLD.

Having a second look, the whole code here is nuts:
1
   main: process
2
      begin
3
      ...
4
   end process main;
Its a process with no sensitivity list, it invokes three clocks, a latch 
for parallel out and last, but not least: an async combinatorial reset 
for ready. Each of them is bad, all of them together a valuable reason 
for "you are fired!"  ;-)


Giuseppe R. wrote:
> -input clock 1200 HZ
> the input serial_in read 300 bit/s
Is the serial data synchronous to the input clock?
Looks like with every 4 clock cycles 1 data bit comes in.

Whats the systems clock? 1200Hz? Or xxMHz (with xx in 10..100)?
Whats the target hardware? FPGA? CPLD?


BTW:
Forget loops and variables. You don't need them here in this simple 
project.

: Edited by Moderator
von Giuseppe R. (owner)


Rate this post
useful
not useful
Can i simulate my code in hardware with Quartus prime? Or i need a 
physical hardware? I'll write the solution on a paper during the exam, i 
don't have the simulator....

How can i use the same clock (or a fraction of it) for two different 
purpose?

Yes clock is 1200Hz. I could count the rising edge and when i reach the 
fourth i'll read the input? In this way i need a variable. I don't 
understand why i can't use variable also on a simple project. If the 
specifications tell me that i'll present the output after reading 16 bit 
i need to save this 16 bit and THEN present it on parallel out.

: Edited by User
von Lothar M. (Company: Titel) (lkmiller) (Moderator)


Attached files:

Rate this post
useful
not useful
Giuseppe R. wrote:
> Can i simulate my code in hardware with Quartus prime?
You get some kind of ModelSim with it.

> Or i need a physical hardware?
As I said: physical hardware i the last step.

> In this way i need a variable.
Aha, the software programmer.
I myself (as the hardware guy) would use some flipflops to store values. 
Those flipflops arranged together in a proper manner result in a 
counter. And that ist, what you need.

> In this way i need a variable.
Be sure: a variable in VHDL is not what you need. A variable in VHDL 
behaves somewhat strange to software programmers.

Meanwhile I did a little fingertwist and it resultet in the attachments. 
As expected the synthesizer says it eats up 23 flipflops: 16 for the 
parallel_out, 4 for the bit counter 0..15, 2 for the cycle counter 0..3 
and one for the ready-flag.

Don't try to serve this pieces of code to your teacher. She/he will get 
distrustful. Just use it as a "howto" to get the idea...  ;-)

Of course you can use my testbench to check your design. Thats the 
trick: when the testbench is ok, you simply must get your module to go 
through without an error.

von Giuseppe R. (owner)


Rate this post
useful
not useful
Thank you. I had already corrected my code like sipo.vhd with the only 
difference that I used variables instead of signals. So every time I 
think of using a variable I could replace it with a signal? Will this 
serve for the next test bench? Probably we used variables because it's 
not required the test bench during the exam, but i know that is not a 
good cause.

I'm a computer science graduate, that's probably why I struggle a bit ;(

von Lothar M. (Company: Titel) (lkmiller) (Moderator)


Rate this post
useful
not useful
Giuseppe R. wrote:
> I had already corrected my code like sipo.vhd
Just being a little bit nosy: can you post that code? ;-)

> with the only difference that I used variables instead of signals.
> So every time I think of using a variable I could replace it with a signal?
> Will this serve for the next test bench?
Of course you can do the same with variables. This code together with 
the test bench from yesterday gives the very same output:
1
architecture Behavioral2 of sipo is
2
begin
3
   process (clock, reset)
4
   variable ccnt : integer range 0 to 3  := 0; -- cycle counter for dividing the clock by 4
5
   variable bcnt : integer range 0 to 15 := 0; -- bit counter for the 16 bits
6
   variable rdy : std_logic := '0';
7
   begin
8
      if reset='1' then
9
         rdy   := '0';
10
         ccnt  := 2;   -- in the middle of those 4 clock cycles we have a stable signal
11
         bcnt  := 0;
12
      elsif rising_edge(clock) then
13
         if rdy='0' then  -- not yet finished?
14
         
15
            if ccnt<3 then         -- do we have enough clocks for the next bit?
16
               ccnt := ccnt+1;     -- no: count on 
17
            else                   -- yes: 
18
               ccnt := 0;          -- reset cycle counter
19
               parallel_out(bcnt) <= serial_in; -- store the bit
20
               if bcnt=15 then     -- do we handle the last bit?
21
                  rdy := '1';      -- yes: were done!
22
               else 
23
                  bcnt := bcnt+1;  -- no: increment index
24
               end if;
25
            end if;
26
            
27
         end if;
28
      end if;
29
      ready <= rdy;        -- map internal ready signal to output
30
   end process;
31
   
32
end Behavioral2;
The major drawback with variables is, that they are invisible outside 
the process.

> Probably we used variables because it's not required
> the test bench during the exam, but i know that is not a good cause.
Particularly for learning VHDL the use of the simulator is absolutely 
necessary. Its the FPGA debugger.

von Giuseppe R. (owner)


Rate this post
useful
not useful
This is my code. I use also a variable for the output because if i need 
to present the output only when i read the 16 bit, i can't store the 
single bit directly in the output, isn't it?

1
 
2
library ieee;
3
use ieee.std_logic_1164.all;
4
5
entity convertitore is
6
  port(serial_in, reset, clock: in std_logic;
7
      parallel_out: out std_logic_vector (15 downto 0);
8
      ready: out std_logic);
9
end entity convertitore;
10
11
architecture device of convertitore is
12
  variable output: std_logic_vector(15 downto 0);
13
  variable count: integer range 0 to 15 := 0;
14
  variable rising: integer range 0 to 4 := 0;
15
  
16
  begin
17
    main: process(clock)
18
    begin
19
      if(clock'event and clock = '1') then
20
        if(reset = '1') then 
21
          ready <= '0';
22
        end if;
23
        rising := rising + 1;
24
      end if;
25
      if(ready /= '1' and rising = 4) then
26
        output(i) := serial_in;
27
        rising := 0;
28
        if(i = 15) then
29
          parallel_out <= output;
30
          ready <= '1';
31
          i := 0;
32
        else
33
          i := i + 1;
34
        end if;
35
      end if;
36
    end process main;
37
  end architecture device;

: Edited by Moderator
von Lothar M. (Company: Titel) (lkmiller) (Moderator)


Attached files:

Rate this post
useful
not useful
Few words to your code (which would result in a reasonably bad grade 
when I was your teacher...;-)

Its a bad idea to combine synchronous and asynchonous parts in 1 
process:
1
    main: process(clock)
2
    begin
3
      if(clock'event and clock = '1') then -- clocked section
4
         :
5
      end if;
6
      if(ready /= '1' and rising = 4) then -- combinatorial section
7
         : 
8
      end if;
9
    end process main;
For sure you will not see this coding style in any book.

Beside the fact, that you cannot read back the output port "ready" you 
have a incomplete sensitivity list due to that special coding style. 
Therefore the simulation will not match the reality.

Much worse is, that you have a combinatorial loop on the variable i. And 
the simulator is not possible to show it. Because i should be in the 
sensitivity list, but variables cannot be taken in there, because 
variables must be declared in the process.

After having fixed the very obviously errors I get something to 
simulate:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity sipo is
6
  port( serial_in, clock, reset: in std_logic;
7
        parallel_out: out std_logic_vector (15 downto 0);
8
        ready: out std_logic);
9
end sipo;
10
11
architecture device of sipo is
12
signal rdy : std_logic := '0';
13
begin
14
    main: process(clock)
15
    variable output: std_logic_vector(15 downto 0);
16
    variable i: integer range 0 to 15 := 0;
17
    variable rising: integer range 0 to 4 := 0;
18
    begin
19
      if(clock'event and clock = '1') then
20
        if(reset = '1') then 
21
          rdy <= '0';
22
        end if;
23
        rising := rising + 1;
24
      end if;
25
      if(rdy /= '1' and rising = 4) then
26
        output(i) := serial_in;
27
        rising := 0;
28
        if(i = 15) then
29
          parallel_out <= output;
30
          rdy <= '1';
31
          i := 0;
32
        else
33
          i := i + 1;
34
        end if;
35
      end if;
36
    end process main;
37
38
    ready <= rdy; -- map internal ready signal to output
39
40
end architecture device;
So having fixed most of the "problems" the simulation looks nearly fine 
at first sight, but from the synthesizer you will get a error like:
ERROR:Xst:1534 - Sequential logic for node <rdy> appears to be 
controlled by multiple clocks.

And this is due to trying to write to "rdy" from a hidden combinatorial 
loop and from a synchronous reset.

So to sum up the two days: you cannot learn VHDL without pressing the 
"simulate" or at least the "synthesize" button now and then. And without 
having a look for the resulting messages...


BTW: pls use the [vhdl ] tags instead of the [c ] tags.

: Edited by Moderator
Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.