Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

FSK Modulation in VHDL

Status
Not open for further replies.

Vijay Vinay

Member level 5
Joined
Mar 21, 2014
Messages
85
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Activity points
781
Hello,
I have a VHDL block that performs FSK modulation. It looks like this

fsk_mod.png.

The operation of the VHDL block goes like this. Fsk_data selects Fsk_u or Fsk_l depending upon its bit value( either 0 or 1). The 'Logik' block decides which bit of fsk_data to be used to set this multiplexer. What I need to do is to implement the counter function for this Logik block that increases with every clock cycle and when reached the maximum value will start again with zero.

The architecture of my VHDL code is as follows:


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
signal cnt_s    : std_logic_vector(21 downto 0);
signal temp_s   : std_logic_vector(7 downto 0);
begin
 
process(reset_n_i, clk_128meg_i,cnt_s)
 
begin
 
if(reset_n_i='0') then
    cnt_s <= (others=>'0');
elsif (clk_128meg_i'event and clk_128meg_i ='1') then
    if(enable_i='1') then
        cnt_s <= std_logic_vector(unsigned(cnt_s)+1);


But, after this I don't have any idea how to proceed. My point is that I need to point the next address of the fsk_data register using the cnt_s (cnt_s acts as a pointer here) in order to select either fsk_u or fsk_l. I need to know whether my point is right. Help is appreciated in proceeding this code.
 
Last edited by a moderator:

First use rising_edge(clk_128meg_i) instead of the 'event and ... = '1' stuff, it handles 'U'/'Z'/'X' => '1' transitions properly.

Your counter cnt_s has no logic to reset back to (others => '0') on the terminal count of 21 (0 to 21) assuming that you mean to index into the fsk_data using a counter. That counter cnt_s doesn't need any more than 5-bits as that can represent a value of 0-31. If you use a real counter like you already have in the code then you'll need a 32:1 multiplexer, which you will only need the first 22-bit of the inputs.

If you instead change the cnt_s to a shift register (initialized on reset to 1 and the MSB feed back to the LSB) you can avoid any multiplexers just use the cnt_s as a mask (I'd rename it to something other than cnt_s) and bit-wise AND it to the fsk_data followed by a reduction OR operation to generate your 0/1 select value. Something like that should be pretty efficiently implemented by the tools.
 
Hello ads-ee,
Thank you for the information. But I am bit confused with these lines " and bit-wise AND it to the fsk_data followed by a reduction OR operation to generate your 0/1 select value. Something like that should be pretty efficiently implemented by the tools".

However, as you have already mentioned I need to index each bit of the fsk_data one by one whenever the counter is incremented. Help is appreciated.
 

Don't use a counter use a shift register with the first bit set as 1 and all others set as 0. If you AND each bit (bit-wise AND)...
Code:
shift reg:    00 0000 0000 0000 0000 0001
fsk_data:     ab cdef ghij klmn opqr stuv
bitwise AND:  00 0000 0000 0000 0000 000v
reduction OR: v

shift reg:    00 0000 0000 0000 0000 0010
fsk_data:     ab cdef ghij klmn opqr stuv
bitwise AND:  00 0000 0000 0000 0000 00u0
reduction OR: u

etc..
Now if you OR all the bits in the bitwise AND value you will have only one output bit in the first case v and the second case u.


Thank you for the information. But what I actually need is that I need to select either fsk_u or fsk_l based on the logic of cnt_s. For example, if the cnt_s value is 5, then I need to push the 5th bit of fsk_data. And based on the pushed value (either 1 or 0), I need to select fsk_l or fsk_u.

Can I write a line directly like this:


Code VHDL - [expand]
1
2
3
4
5
if(fsk_data_i(unsigned(cnt_s))='0') then
        temp_s <= std_logic_vector(fsk_u_i);
else
        temp_s <= std_logic_vector(fsk_l_i);
end if;

 
Last edited by a moderator:

Don't use a counter use a shift register with the first bit set as 1 and all others set as 0. If you AND each bit (bit-wise AND)...
Code:
shift reg:    00 0000 0000 0000 0000 0001
fsk_data:     ab cdef ghij klmn opqr stuv
bitwise AND:  00 0000 0000 0000 0000 000v
reduction OR: v

shift reg:    00 0000 0000 0000 0000 0010
fsk_data:     ab cdef ghij klmn opqr stuv
bitwise AND:  00 0000 0000 0000 0000 00u0
reduction OR: u

etc..
Now if you OR all the bits in the bitwise AND value you will have only one output bit in the first case v and the second case u.

- - - Updated - - -

If you insist on a counter then you'll have to make it rollover at 21, which you didn't implement and you need to add a large 22:1 multiplexer. You also don't need a 22-bit counter which will count from 0 to 4194303 back to 0.

It seem that you have not been exposed to digital design concepts or is this your first exposure to it?

- - - Updated - - -

Thank you for the information. But what I actually need is that I need to select either fsk_u or fsk_l based on the logic of cnt_s. For example, if the cnt_s value is 5, then I need to push the 5th bit of fsk_data. And based on the pushed value (either 1 or 0), I need to select fsk_l or fsk_u.

Can I write a line directly like this:


Code VHDL - [expand]
1
2
3
4
5
if(fsk_data_i(unsigned(cnt_s))='0') then
        temp_s <= std_logic_vector(fsk_u_i);
else
        temp_s <= std_logic_vector(fsk_l_i);
end if;

Yes and this results in a big multiplexer, though due to your lack of digital design knowledge you don't see this is the case.

I give up, I told you the best way I can see how to do this. Do it whatever way you want.
 
@ads-ee, thanks for the info. According to my FSK block I need to design the multiplexer by using only a counter and not a shift register. The 'Logik' function should only be a counter and not anything else. I have changed the counter to std_logic_vector(4 downto 0).

My problem is that I can't design the counter in such a manner that it points each bit (like 1st bit, 2nd bit, 3rd bit (from LSB).....). I tried writing different codes for this, but still I couldn't solve this problem since I need to write a synthesizable code. I tried "when.. else" as well as "with...select" statements. But I have an error like these constructs are valid only in 2008 (something like that, I am not sure). I don't know how it works with for loops since I have defined cnt as a signal.

Help is appreciated.
 

hi vijay vinay,
use loglk is shift register,take single bit out, you can easily solve the problem
 
@ads-ee, thanks for the info. According to my FSK block I need to design the multiplexer by using only a counter and not a shift register. The 'Logik' function should only be a counter and not anything else. I have changed the counter to std_logic_vector(4 downto 0).
Is this a requirement of the design (i.e. The logik function shall contain a counter based selection...), or some self imposed requirement because you decided that is what is needed?

My problem is that I can't design the counter in such a manner that it points each bit (like 1st bit, 2nd bit, 3rd bit (from LSB).....). I tried writing different codes for this, but still I couldn't solve this problem since I need to write a synthesizable code. I tried "when.. else" as well as "with...select" statements. But I have an error like these constructs are valid only in 2008 (something like that, I am not sure). I don't know how it works with for loops since I have defined cnt as a signal.

Help is appreciated.
What your class notes or VHDL book don't have any information on multiplexers? That is a basic design element that any decent tutorial, book, or instructor should show you. If you've never been exposed to a multiplexer then you need find a better tutorial, book, or instructor. Try looking at the following https://www.mil.ufl.edu/3701/examples/vhdl/VHDL_examples.pdf which show multiple different ways to write the code for a multiplexer. I suggest using the case method. The counter needs to select the appropriate connection. I've pretty much already told you how to do this, outside of writing the code for you (which I refuse to do).

Here are some other coding examples for basic building blocks of digital circuits https://asic-world.com/examples/vhdl/index.html.
 

@ads-ee, thank you anyways, I have written the code.
 

I have another doubt. How to implement this shifting operation such that each bit is shifted after every 1024th clock cycle. Help is appreciated.
 

A counter that cycles from 0 to 1023 back to 0 and only enable the shift on a count of 1023.
 
@ads-ee,
Thanks for the information. Do you have any idea of how to continue the same process like shifting another bit at the next 1024th clock cycle after shifting the first bit at the first 1024th clock cycle.

I have written the code like this, but still the next bit is not shifted in the next 1024th clock cycle but it is shifted in the next clock cycle at once. The code looks likes this,


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity fsk_mod is
 
    port(   clk_128meg_i        : in std_logic;
        reset_n_i       : in std_logic;
        enable_i        : in std_logic;     
        fsk_u_i         : in std_logic_vector (7 downto 0);
        fsk_l_i         : in std_logic_vector (7 downto 0);
        fsk_data_i      : in std_logic_vector (21 downto 0);
        fsk_mod_o       : out std_logic_vector (7 downto 0));
 
end fsk_mod;
 
 
architecture rtl of fsk_mod is
 
signal cnt_s    : std_logic_vector(4 downto 0) := (others=> '0');
 
signal temp_s   : std_logic_vector(7 downto 0);
 
signal cntdiv_s : integer :=0;
 
begin
 
process(reset_n_i, clk_128meg_i)
 
begin
 
    if(reset_n_i='0') then
        cntdiv_s <= 0;
                
    elsif (clk_128meg_i'event and clk_128meg_i ='1') then
        if(enable_i='1') then           
            cntdiv_s <=cntdiv_s+1;
        else 
            cntdiv_s <= 0;
        end if;
        
    end if;
 
end process;    
                    
process(reset_n_i, clk_128meg_i)
 
begin
 
    if(reset_n_i='0') then
        temp_s <= (others=>'0');
        cnt_s <= (others=>'0');     
    elsif (clk_128meg_i'event and clk_128meg_i ='1') then
        if(enable_i='1') then
                cnt_s <= std_logic_vector(unsigned(cnt_s)+1);   
                if(cntdiv_s >= 1023) then
                    
                    if (fsk_data_i(to_integer((unsigned(cnt_s))))='1') then
                        temp_s <= std_logic_vector(fsk_u_i);
                    else
                        temp_s <= std_logic_vector(fsk_l_i);
                    end if;
                else 
                    cnt_s <= (others=>'0');
                end if;
        else
            temp_s <= (others=>'0');            
        end if;
    
    end if;
    
end process;
 
fsk_mod_o <= std_logic_vector(temp_s) ;
 
end rtl;




I am not sure how to solve this problem. Help is appreciated.
 
Last edited by a moderator:

You are using the wrong type (i.e. integer). VHDL is strongly typed and there are specific types used for specific purposes (you should review that).


Code VHDL - [expand]
1
2
3
4
5
if (enable_i = '1') then
    cntdiv_s <=cntdiv_s+1;  -- count from 0 to 4294967295 when enabled
else
    cntdiv_s <= 0;  -- clear counter when disabled
end if;



This won't be a good counter for cycling over 0-1023-0. you need a 10-bit counter. As you are correctly using numeric_std...
Code:
cntdiv_s : unsigned (9 downto 0);
If you want the first output early then just compare to if (cntdiv_s = "0000000001") then ... instead of the current >= 1023 stuff.

Also use the function rising_edge(clk_128meg_i) instead of what you are using it doesn't suffer from interpreting clock edges if the clock goes from 'X' => '1', 'U' => '1'
 

@ads-ee,
but what if I try to use "integer range 0 to 1023" instead of the above mentioned code, and use the same if condition of "if(cntdiv_s >= 1023)" because the counter is not working properly. Will the counter works properly.
 

I don't think it will rollover from 1023 to 0 if it is integer (nominally 32-bit value), I think it will just produce an error as 1024 and above is a valid integer but exceeds the valid range you allow for cntdiv_s. Integer is not supposed to be used to implement hardware counters...use the correct type (unsigned).
 

Wrap around operation in vhdl

Hello,
I am designing a fsk modulation block in VHDL consisting of a multiplexer and ,a counter within the multiplexer, which shifts each bit of the i/p value that's used as the select lines for the above multiplexer. I have written the code such that each bit is shifted and the multiplexer operation is performed. I need to perform a wrap around operation here in such a manner that each bit is shifted after "every 1024th clock cycle".

I have used

Code VHDL - [expand]
1
unsigned(10 downto 0)

as well as the if statement looks like this

Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
if(cntdiv_s >="1111111111" ) then
                    
                    if (fsk_data_i(to_integer((unsigned(cnt_s))))='1') then
                        temp_s <= std_logic_vector(fsk_u_i);
                    else
                        temp_s <= std_logic_vector(fsk_l_i);
                    end if;
                else 
                    cnt_s <= (others=>'0');
                end if;

, but the problem is that I can't shift each and every bit after every 1024th clock cycle. Help is appreciated.
 
Last edited by a moderator:

Your problem is unclear. Are you trying to bit shift the fsk_data_i by a bit or what? You aren't being specific enough. Your code is also going to be a large 22:1 multiplexer.

Also you should have an error on if (cntdiv_s >= "1111111111") if it is defined as unsigned(10 downto 0) (this is 11 bits not 10).
 

Hi,
I need to shift fsk_data_i by every bit but at the same time each bit should be shifted only after every 1024th clock value. When I do as above, only the first bit is shifted after 1024th clock value, but all the remaining bit values ae shifted after every clock value like the 1st bit is shifted at 1024th clock value, 2nd bit is shifted after 1025th clock value. 3rd bit at 1026th clock value and so on. But I need to shift the 1st bit in the 1024th clock value , 2nd bit in the 2048th(first 1024th+next 1024th) clock value, 3rd bit at 3072nd clock value and so on. I don't know where I have committed the mistake. Help is appreciated.
 

Perhaps you keep shifting because cntdiv_s is 11-bits and counts from 0-2047 when you are comparing against >= 1023?

I don't think you understand that >= 1023 means any thing that is between 1023 and 2047 will cause that branch of the if statement to be taken each time, (i.e. after the first 1023 you will always do the shift)

I think your counter code is not well thought out. This is how I code a counter that cycles with a period of 1024.

Code VHDL - [expand]
1
2
3
4
5
if (cnt < 1024-1) then -- 1024 would normally be a constant like MAX_CNT so I would use MAX_CNT-1
  cnt <= cnt + 1;
else
  cnt <= (others => '0');
end if;



I don't think you are debugging your code correctly you need to be looking at the signals that are part of the if and how they interact with which branch of the if statements your code takes.

And this is how I would do something only every 1024 clock cycles.

Code VHDL - [expand]
1
2
3
if (cnt = 1023) then
  -- do something every 1024 counts
end if;



Though I thought you wanted to have it start with a shift then another after 1024 counts, if so then compare with 1 (if you are resetting the count to 0) instead of 1023 to remove that initial latency of 1024 before the first shift.
 
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top