library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity RAM_controler is
port(
clk_50 : in std_logic;
clk_baud : in std_logic;
main_reset : in std_logic;
enable: in std_logic; --active high write enable
in_data : in std_logic_vector(7 downto 0);
W_order : out std_logic;
R_order : out std_logic;
Data_OUT : out std_logic_vector(7 downto 0);
Write_Address_OUT: out std_logic_vector(7 downto 0);
Read_Address_OUT: out std_logic_vector(7 downto 0)
);
end entity RAM_controler;
architecture Behavioral of RAM_controler is
type state is (reset,operation);
signal state_reg,next_state_reg : state;
signal write_address : std_logic_vector(W-1 downto 0):="00000000";
signal next_write_address : std_logic_vector(W-1 downto 0):="00000000";
begin
state_change : process(clk_50, main_reset)
begin
if (main_reset = '1') then
state_reg <= reset;
elsif (rising_edge(clk_50)) then
state_reg <= operation;
read_counter <= next_read_counter;
write_address<= next_write_address;
read_address <= next_read_address;
end if;
end process;
writecounter : process(clk_baud, main_reset,enable)
begin
if (main_reset='1') then
next_write_address <= "00000000";
Data_OUT <= "ZZZZZZZZ";
W_order <='0';
Write_Address_OUT <="ZZZZZZZZ";
elsif (rising_edge(clk_baud) and enable='1' ) then
W_order <='1';
Data_OUT <= in_data;
Write_Address_OUT <= write_address;
if (write_address = "11111111") then
next_write_address <= "00000000";
else
next_write_address <= write_address+1;
end if;
else
W_order <='0';
Write_Address_OUT <= "ZZZZZZZZ";
next_write_address <= write_address+1;
end if;
end process;
end Behavioral;
Above code is describing RAM controller.
The part of making problem is "elsif (rising_edge(clk_baud) and enable='1' ) then".
Error : Can`t inter register for "Write_Address_OUT" at RAM_controler.vhd because it does not hold its value outside the clock edge
I don`t know why that point is error.
Is there anyone who advice to me?
Thank you!
If you're coding sequential logic, it is wise to stick to a template. Here is one such template for sequential logic with an asynchronous reset, which all synthesis tools should understand:
process(clock, async_reset) -- nothing else should go in the sensitivity list
begin
-- never put anything here
if async_reset ='1' then -- or '0' for an active low reset
-- set/reset the flip-flops here
-- ie drive the signals to their initial values
elsif rising_edge(clock) then -- or falling_edge(clock)
-- put the synchronous stuff here
-- ie the stuff that happens on the rising or falling edge of the clock
end if;
-- never put anything here
end process;
So enable should not be in the senstivity list and it should not be tested in the same if statement as the asynchronous reset and the clock is tested.
The reason why your are getting this error:
Error : Can`t inter register for "Write_Address_OUT" at
RAM_controler.vhd because it does not hold its value outside the clock
edge
is because the last three assignments in your code:
W_order <='0';
Write_Address_OUT <= "ZZZZZZZZ";
next_write_address <= write_address+1;
can occur on the falling edge of the clock or (because you also had enable in your sensitivity list) independently of any clock at all. A logic synthesiser can't synthesise logic that behaves like that. If you stick to the template, you won't run into this kind of problem (and it makes you think a bit more carefully about what logic you are expecting the synthesiser to synthesise).
So, I would have coded your writecounter process more like this:
writecounter : process(clk_baud, main_reset)
begin
if (main_reset='1') then
next_write_address <= "00000000";
Data_OUT <= "ZZZZZZZZ";
W_order <='0';
Write_Address_OUT <="ZZZZZZZZ";
elsif rising_edge(clk_baud) then
if enable='1' then
W_order <='1';
Data_OUT <= in_data;
Write_Address_OUT <= write_address;
if (write_address = "11111111") then
next_write_address <= "00000000";
else
next_write_address <= write_address+1;
end if;
else
W_order <='0';
Write_Address_OUT <= "ZZZZZZZZ";
next_write_address <= write_address+1;
end if;
end if;
end process;
Though, I should emphasise that my code does not behave exactly like yours. I don't know your design intent, so I can only guess what you intended. If you intended some other behaviour, then you will have to implement that instead. My advice about sticking to a template is nevertheless important, whatever your design intent.
The final else in your code should actually be:
elsif (rising_edge(clk_baud) and enable='0' ) then
Related
Please forgive myself if you will find some trivial errors in my code .. I'm still a beginner with VHDL.
Well, I have to deal with a serial interface from an ADC. The interface is quite simple ... there is a wire for the serial data (a frame of 24 bits), a signal DRDY that tells me when the new sample data is available and a serial clock (SCLK) that push the bit into (rising edge). Everything is running continuously...
I need to capture correctly the 24 bit of the sample, put them on a parallel bus (shift register) and provide a "data valid" signal for the blocks that will process the samples ...
Due to the fact that my system clock is x4 the frequency of the serial interface, i was thinking that doing the job with a FSM will be easy ...
When you look into the code you will see a process to capture the rising edges of the DRDY and SCLK.
Then a FSM with few states (Init, wait_drdy, wait_sclk, inc_count, check_count).
I use a counter (cnt unsigned) to check if I've already captured the 24 bits, using also to redirect the states of the FSM in "check_count" state.
Here a picture:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity serial_ads1675 is
Port (
clk : in STD_LOGIC;
reset : in STD_LOGIC;
sclk : in std_logic;
sdata : in std_logic;
drdy : in std_logic;
pdata : out std_logic_vector(23 downto 0);
pdready : out std_logic
);
end serial_ads1675;
architecture Behavioral of serial_ads1675 is
-- Internal declarations
signal ipdata : std_logic_vector (23 downto 0);
signal ipdready : std_logic;
signal tmp1, tmp2, tmp3, tmp4 : std_logic;
signal rise_drdy, rise_sclk : std_logic;
signal cnt : unsigned (4 downto 0);
type state is (init, wait_drdy, wait_sclk, inc_count, check_count);
signal actual_state, next_state : state;
begin
-- Concurrent statements
pdata <= ipdata;
pdready <= ipdready;
rise_drdy <= '1' when ((tmp1 = '1') and (tmp2 = '0')) else '0';
rise_sclk <= '1' when ((tmp3 = '1') and (tmp4 = '0')) else '0';
-- Process
process (clk, reset)
begin
if(reset = '0') then
tmp1 <= '0';
tmp2 <= '0';
tmp3 <= '0';
tmp4 <= '0';
elsif (falling_edge(clk)) then
tmp1 <= drdy;
tmp2 <= tmp1;
tmp3 <= sclk;
tmp4 <= tmp3;
end if;
end process;
process (reset, clk)
begin
if (reset = '0') then
actual_state <= init;
elsif (rising_edge(clk)) then
actual_state <= next_state;
end if;
end process;
process (rise_sclk, rise_drdy) -- Next State affectation
begin
case actual_state is
when init =>
next_state <= wait_drdy;
ipdata <= (others => '0');
ipdready <= '0';
cnt <= (others => '0');
when wait_drdy =>
if (rise_drdy = '0') then
next_state <= actual_state;
else
next_state <= wait_sclk;
end if;
cnt <= (others => '0');
when wait_sclk =>
if (rise_sclk = '0') then
next_state <= actual_state;
else
next_state <= inc_count;
end if;
ipdready <= '0';
when inc_count =>
next_state <= check_count;
cnt <= cnt + 1;
ipdready <= '0';
ipdata(23 downto 1) <= ipdata(22 downto 0);
ipdata(0) <= sdata;
when check_count =>
case cnt is
when "11000" =>
next_state <= wait_drdy;
ipdready <= '1';
when others =>
next_state <= wait_sclk;
ipdready <= '0';
end case;
when others =>
next_state <= init;
end case;
end process;
end Behavioral;
My problem is during the check_count state ...
I'm expecting that this state should last one system clock cycle, but actually it last much more.
Here a snapshot of the behavioral simulation:
Due to the fact that this state last more than expected, i miss the following SCLK pulse and don't record the next bit ...
I don't understand why this state last so many system clock cycles instead of just one ...
Anyone has some clues and bring some light in my dark night ?
Thanks in advance.
Edit: I've tried to change the signal cnt for an integer variable internal to the process of the FSM ... Same results
The error is this:
process (rise_sclk, rise_drdy) -- Next State affectation
begin
-- code omitted, but does generally this:
next_state <= SOME_VALUE;
end process;
Because the sensitivity list includes only the signals rise_sclk and rise_drdy, the process is "executed" only if any of these signals changes. You can follow this in the wave diagram.
You don't have a synchronous design running on clk. Put clk on the sensitivity list and base the decisions on the levels of rise_sclk and rise_drdy. As an excerpt:
process (clk) -- Next State affectation
begin
if rising_edge(clk) then
case actual_state is
when init =>
next_state <= wait_drdy;
-- and so on
end case;
end if;
end process;
I write simple vhdl code for Uart receiver.
Simulation (iSIM) is fine but when implemented I have wrong reading behavior.
When synthetized ISE tell me there are latches on state machine end on data_fill(x).
have you any suggestion.
thanks in advance
gian
here the code
library ieee;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity rx_uart is
port (
clk : in STD_LOGIC;
rst : in STD_LOGIC;
rx_data : in STD_LOGIC;
data_out: out STD_LOGIC_VECTOR(7 downto 0)
);
end rx_uart;
architecture fizzim of rx_uart is
-- state bits
subtype state_type is STD_LOGIC_VECTOR(2 downto 0);
constant idle: state_type:="000"; -- receive_en=0 load_en=0 cnt_en=0
constant receive: state_type:="101"; -- receive_en=1 load_en=0 cnt_en=1
constant stop_load: state_type:="010"; -- receive_en=0 load_en=1 cnt_en=0
signal state,nextstate: state_type;
signal cnt_en_internal: STD_LOGIC;
signal load_en_internal: STD_LOGIC;
signal receive_en_internal: STD_LOGIC;
signal count : integer range 0 to 54686:=0;
signal cnt_en : STD_LOGIC;
signal load_en : STD_LOGIC;
signal receive_en : STD_LOGIC;
signal data_fill : STD_LOGIC_VECTOR(9 downto 0);
-- comb always block
begin
COUNTER_EN : process(clk,rst,cnt_en) begin
if (rst ='1') then
count <= 0;
elsif rising_edge(clk) then
if (cnt_en ='1') then
count <= count+1;
else
count <= 0;
end if;
end if;
end process;
LOADER: process(clk,rst,load_en) begin
if (rst='1') then
data_out <= (others =>'0');
elsif (rising_edge(clk) and load_en='1')then
data_out <= data_fill(8 downto 1);
end if;
end process;
ASSIGNATION : process(clk,rst,receive_en) begin
if (rst ='1') then
data_fill <= (others =>'0');
elsif (receive_en='1') then
case count is
when 7812 =>
data_fill(1) <= rx_data;
when 13020 =>
data_fill(2) <= rx_data;
when 18228 =>
data_fill(3) <= rx_data;
when 23436 =>
data_fill(4) <= rx_data;
when 28664 =>
data_fill(5) <= rx_data;
when 33852 =>
data_fill(6) <= rx_data;
when 39060 =>
data_fill(7) <= rx_data;
when 44268 =>
data_fill(8) <= rx_data;
when 49476 =>
data_fill(9) <= rx_data;
when others =>
data_fill(0) <= '0';
end case;
end if;
end process;
COMB: process(state,clk,count,rst,rx_data) begin
case state is
when idle =>
if (rx_data='0') then
nextstate <= receive;
elsif (rx_data='1') then
nextstate <= idle;
end if;
when receive =>
if (count<=54685) then
nextstate <= receive;
elsif (count>54685) then
nextstate <= stop_load;
end if;
when stop_load =>
nextstate <= idle;
when others =>
end case;
end process;
-- Assign reg'd outputs to state bits
cnt_en_internal <= state(0);
load_en_internal <= state(1);
receive_en_internal <= state(2);
-- Port renames for vhdl
cnt_en <= cnt_en_internal;
load_en <= load_en_internal;
receive_en <= receive_en_internal;
-- sequential always block
FF: process(clk,rst,nextstate) begin
if (rst='1') then
state <= idle;
elsif (rising_edge(clk)) then
state <= nextstate;
end if;
end process;
end fizzim;
You need to understand when latches are generated. Latches are generated when you have an incomplete assignment in combinational logic. Your case statements are combinational. You do not completely assign all possibilities of your data signal and your state machine. When you have an incomplete assignment in a combinational process you will always generate a latch. Latches are bad!
Use your when others properly to assign all of your signals under all conditions. Your data_fill signal will always generate a latch because you don't handle all conditions for data 0:9 on all cases.
Read more about how to avoid latches in VHDL
Edit: It seems too that you don't consistently create sequential logic in VHDL. You need to be creating a clocked process or remove clk from your sensitivity list in a combinational process.
your design has several bad code sites besides your latch problem. I'll number them for better reference.
(1)
Xilinx XST won't recognize the implemented state machine as a FSM. See your XST report or the *.syr file. There won't be a FSM section. If XST finds no FSM it's not able to choose "the best" state encoding and optimize your FSM.
You should use an enum as a state-type and also initialize your state signal:
type t_state is (st_idle, st_receive, st_stop);
signal state : t_state := st_idle;
signal nextstate : t_state;
Your FSM process also needs default assignments (see Russell's explanation) like
nextstate <= state;
(2)
asynchronous resets are no good design practice and complicate timing closure calculations.
(3)
you are handling raw input signals from outside you FPGA without any timing information. to prevent meta stability problems place two D-flip-flops on the rx_data path. you should also add the async-reg and no-srl-extract attribute to these 2 registers to prevent XST optimizations
SIGNAL I_async : STD_LOGIC := '0';
SIGNAL I_sync : STD_LOGIC := '0';
-- Mark register "I_async" as asynchronous
ATTRIBUTE ASYNC_REG OF I_async : SIGNAL IS "TRUE";
-- Prevent XST from translating two FFs into SRL plus FF
ATTRIBUTE SHREG_EXTRACT OF I_async : SIGNAL IS "NO";
ATTRIBUTE SHREG_EXTRACT OF I_sync : SIGNAL IS "NO";
[...]
BEGIN
[...]
I_async <= In WHEN rising_edge(Clock);
I_sync <= I_async WHEN rising_edge(Clock);
Let 'In' be your asynchronous input. Now you can use I_sync in your clock domain. I choose to describe these 2 registers in a one-liner, you can also use a classic process :) The suffix '_async' allows you to define a matching timing rule in your *.xcf and *.ucf files.
I am having problem with my VHDL code, I hope someone could help. See, the 'q' signal is supposed to detect whether the state has changed or not, but it never does. It is as if the state never gets from 'detecting' to 'idle'. The q signal remains on the '0' value, even though the state changes, while the reset is off and clk signal is on the upper edge. I hope you get to see where the problem is.
P.S. state_reg signal is for state at the moment and the next one is for the next state. qlevel_detected is the signal I used for debugging.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity detector is
port
(
clk, reset : in std_logic;
level : in std_logic;
q : out std_logic;
qlevel_detected : out std_logic
);
end detector;
architecture behavioral of detector is
type state is (idle, detecting);
signal state_reg, state_next : state;
signal level_detected_reg, level_detected_next : std_logic;
begin
process(clk, reset)
begin
if (reset = '1') then
state_reg <= idle;
elsif (clk'event and clk = '1') then
state_reg <= state_next;
level_detected_reg <= level_detected_next;
end if;
end process;
process(state_reg)
begin
state_next <= state_reg;
level_detected_next <= level_detected_reg;
case state_reg is
when idle =>
level_detected_next <= level;
state_next <= detecting;
when detecting =>
if (level /= level_detected_reg) then
state_next <= idle;
end if;
end case;
end process;
-- Output logic
q <= '0' when state_reg = idle else
'1' when state_reg = detecting;
qlevel_detected <= level_detected_reg;
end behavioral;
Your next state process is only sensitive to state_reg. As a combinational process it needs all of its inputs listed in the sensitivity list (or all with VHDL-2008).
process(state_reg, level, level_detected_reg)
begin
...
You are also missing an unconditional else on the assignment to q which will create a latch in synthesis.
I'm trying to send two data to PC according to a counter. I need to send this two data just once, so I'm using a signal called "New_data_s". But my problem is this signal stays "High" too much and the data is being sent more than once. I'm sending "Datafll_s" by the way.
This is a picture of the first simulation: Sim1
Then I added another signal called "Stop_s" to reset this "New_data_s". Okay it sends the data just once, but this time, I can't reset "Stop_s". Once it goes "High" it stays "High" until I press the button. So I can't send the second data.
This is a picture of the second simulation: Sim2
I know if I don't press the button this "ELSIF(Go_s='1' and Go_s_ff='0')Then" condition is not TRUE, so that's why "Stop_s" stays "High" until I press the button. But, I couldn't find a way to do this.
Counter part:
IF(Cnt_Spc_P1>15 and Cnt_Spc_P1<=30)Then
Three_spc_s<='1';
Seven_spc_s<='0';
ELSIF(Cnt_Spc_P1>30 and Cnt_Spc_P1<50)Then
Three_spc_s<='0';
Seven_spc_s<='1';
ELSIF(Cnt_Spc_P1=50)Then
Three_spc_s<='0';
Seven_spc_s<='1';
Enable_1_s<='0';
Cnt_Spc_P1<=0;
ELSE
Three_spc_s<='0';
Seven_spc_s<='0';
END IF;
Main part:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
-------------------------------------------------------------------------------
Entity Letters is
Port(
Clk: in std_logic;
Reset: in std_logic;
Dot: in std_logic;
Dash: in std_logic;
Error : out std_logic;
New_data: out std_logic;
three_spc: in std_logic;
seven_spc: in std_logic;
d_out_d: out std_logic_vector(6 downto 0);
d_out_a: out std_logic_vector(7 downto 0)
);
END Letters;
-------------------------------------------------------------------------------
Architecture Letters_a of Letters is
-------------------------------------------------------------------------------
Type state is (Start, Space, T, E);
Signal current_s: state;
Signal Go_s, Go_s_ff: std_logic:='0';
signal data_d : std_logic_vector(6 downto 0):="1100100";
signal data_a : std_logic_vector(7 downto 0):="00000000";
Signal Error_s, New_data_s : std_logic:='0';
Signal Stop_s : std_logic:='0';
-------------------------------------------------------------------------------
BEGIN
-------------------------------------------------------------------------------
PROCESS(Clk, three_spc, seven_spc, current_s, Reset)
BEGIN
IF(Reset='1')Then
current_s<=Start;
data_d<="0000000";
data_a<="00000000";
d_out_d<="1100100";
Error_s<='0';
New_data_s<='0';
Stop_s<='0';
ELSIF(Rising_Edge(Clk))Then
IF(three_spc='1')Then
d_out_d<=data_d;
d_out_a<=data_a;
New_data_s<='1';
Stop_s<='1';
current_s<=Start;
ELSIF(seven_spc='1')Then
current_s<=Space;
d_out_d<=data_d;
d_out_a<="00100000";
New_data_s<='1';
Stop_s<='1';
current_s<=Start;
ELSIF(Go_s='1' and Go_s_ff='0')Then
Case current_s is
When Start =>
New_data_s<='0';
Stop_s<='0';
IF(Dash='1')Then
current_s<=T;
data_d<="1100100";
data_a<="01010100";
Error_s<='0';
ELSIF(Dot='1')Then
current_s<=E;
Error_s<='0';
data_d<="0000110";
data_a<="01000101";
END IF;
-------------------------------------------------------------------------------
When T =>
IF(Dash='1')Then
current_s<=M;
data_d<="1100100";
data_a<="01001101";
ELSIF(Dot='1')Then
current_s<=N;
data_d<="0101011";
data_a<="01001110";
END IF;
-------------------------------------------------------------------------------
When E =>
IF(Dash='1')Then
current_s<=A;
data_d<="0001000";
data_a<="01000001";
ELSIF(Dot='1')Then
current_s<=I;
data_d<="1111001";
data_a<="01001001";
END IF;
When OTHERS =>
current_s <= Start;
Error_s<='1'; -- Unidentified letter.
data_d<="1100100";
New_data_s<='0';
Stop_s<='0';
END Case;
END IF;
IF(Stop_s='1')Then
New_data_s<='0';
END IF;
END IF;
END PROCESS;
-------------------------------------------------------------------------------
PROCESS(Clk, Dot, Dash, Reset)
BEGIN
Go_s<=Dash or Dot;
IF(Reset='1')Then
Go_s<='0';
Go_s_ff<='0';
ELSIF(Rising_Edge(Clk))Then
Go_s_ff<=Go_s;
END IF;
END PROCESS;
-------------------------------------------------------------------------------
Error<=Error_s;
New_data<=New_data_s;
-------------------------------------------------------------------------------
END Letters_a;
Thank you.
I see that you've declared an enumerated type state and instantiated a signal current_s of type state. The enumerated type includes the literals, (Start, Space, T, E), but you assign literals M, N and A to signal current_s which are not members of the state type. Your compiler should complain about that. Does it?
The fsm included in your code is a bit difficult to follow because state transition code is mixed with output signal logic. So, I've rewritten it and posted it below. My fsm may not exactly represent the functionality you're looking for, however, you can use it as a template. It illustrates how to generate a one clock wide edge detector for the dot and dash signals. It also illustrates how to control the data strobe signal that you were having difficulty switching on and off.
The output logic does not take full advantage of the default signal values that proceed the output logic case statement so that it will be easier for you to see what's happening. However, many of the statements within the case could be eliminated for compactness.
Also, I haven't compiled the code, so you may find a few syntax errors, but the template should be of use to you.
-- Note, not all signals are declared here, refer to the posted code for them
Type state_t is (Idle, start_dot, start_dash, E_dot, strobe_3spc_data,
wait_1, strobe_7spc_data, wait_2, E_dash);
signal state_snoop : state_t; -- use to monitor state in simulator
signal dash_ff : std_logic;
signal dash_pulse : std_logic;
signal dot_ff : std_logic;
signal dot_pulse : std_logic;
fsm: process (clk)
variable current_s : state_t;
begin
if rising_edge(clk) then
if Reset = '1' then
current_s := Idle;
else
case Idle is
when Idle =>
if dot_pulse = '1' then
current_s := start_dot;
elsif dash_pulse = '1' then
current_s := start_dash;
end if;
-- dot related states ----------------------
when start_dot =>
current_s := E_dot;
when E_dot =>
if three_spc = '1' then
current_s := strobe_3spc_data;
end if;
when strobe_3spc_data =>
if seven_spc = '1' then -- counter strobe from external source
current_s := wait_1;
end if;
when wait_1 =>
if seven_spc = '1' then -- counter strobe from external source
current_s := strobe_7spc_data;
end if;
when strobe_7spc_data =>
current_s := wait_2;
when wait_2 =>
current_s := idle;
-- dash related states ----------------------
when start_dash =>
current_s := E_dash;
when E_dash =>
if three_spc = '1' then
current_s := strobe_3spc_data;
end if;
end case;
end if;
end if;
state_snoop <= current_s; -- monitor state in simulator. variables are hard to monitor
-------------- outputs decoded from state variable -------------------
-- default signal values
New_data_s <= '0';
data_d <= "0000000"; data_a <= "00000000"; d_out_d <= "0000000";
Stop_s <= '0'; Error_s <= '0';
case current_s is
when Idle =>
data_d <= "0000000";
data_a <= "00000000";
d_out_d <= "1100100";
Error_s <= '0';
New_data_s <= '0';
when start_dot =>
data_d <= "0000110"; --'ACK'
data_a <= "01000101"; -- ascii dash -> 'E'
Error_s <= '0';
New_data_s <= '0';
when E_dot =>
data_d <= "1111001";
data_a <= "01001001";
when strobe_3spc_data =>
d_out_d <= data_d;
d_out_a <= data_a;
New_data_s <= '1';
when wait_1 => -- switch data strobe off for first data transmission
New_data_s <= '0';
when strobe_7spc_data =>
d_out_d <= data_d;
d_out_a <= "00100000";
New_data_s <= '1';
when wait_2 => -- switch data strobe off for second data transmission
New_data_s <= '0';
-- dash related outputs
when start_dash =>
data_d <= "1100100"; --'t'
data_a <= "01010100"; --'T'
Error_s <= '0';
New_data_s <= '0';
when E_dash =>
data_d <= "0001000";
data_a <= "01000001";
when others => null;
end case;
-- rising edge detector for dash and dot input.
if Reset = '1' then
dash_pulse <= '0'
else
dash_ff << not(Dash);
dash_pulse << dash_ff and dash;
end if;
if Reset = '1' then
dot_pulse <= '0'
else
dot_ff << not(dot);
dot_pulse << dot_ff and dot;
end if;
end process fsm
I am newbie to VHDL. I am implementing serial in serial out 72 bit shift register using VHDL. When the enable signal is high, I want the shift register to shift 72 times, irrespective of whether enable continues to be high or low. I have written the following code which is working only when the enable is high. Can anyone please help me to shift data once enable is high and then does not depend on enable to shift the data?
library ieee;
use ieee.std_logic_1164.all;
entity SR is
port(clk, din, rst, enable : in std_logic;
sr_out : inout std_logic_vector(71 downto 0));
end SR;
architecture behavioral of SR is
signal shift_reg: std_logic_vector(71 downto 0);
begin
process (clk, rst)
begin
if (rst = '0') then
shift_reg <= (others => '0');
elsif (clk'event and clk = '1') then
if enable= '1' then
shift_reg(70 downto 0) <= shift_reg(71 downto 1);
shift_reg(71) <= din;
end if;
end if;
end process;
sr_out <= shift_reg;
end behavioral;
Thanks a lot!
I think you need an RS-FlipFlop which is set by a start signal. Its output is your enable signal. The start signal also starts a 72 clock cycle counter. When the counter rolls over (or reaches zero, depending on its direction) you reset the FlipFlop which results in a disabled shift register.
edit: In addition you can add a gate to the start signal which blocks new start impulses while the counter is active. So you can be sure your data is only shifted with a multiple of 72 bits.
You need a two states machine to do so. Here's a very good idea of how to do it. I'm pretty sure it does what you need or is very close to.
library ieee;
use ieee.std_logic_1164.all;
entity SR is
port(
clk : in std_logic;
din : in std_logic;
rst : in std_logic;
enable : in std_logic;
sr_out : inout std_logic_vector(71 downto 0)
);
end SR;
architecture behavioral of SR is
signal shift_reg : std_logic_vector(71 downto 0);
signal shift_cnt : integer range 0 to 72 := 0;
type T_STATE_TYPE is (IDLE, COUNTING);
signal current_state : T_STATE_TYPE;
begin
p_shift_counter : process(clk,rst)
begin
if rst = '1' then
current_state <= IDLE;
shift_cnt <= 0;
elsif rising_edge(clk) then
if (current_state = IDLE) then --no enable detected yet
shift_cnt <= 0;
if enable = '1' then
current_state <= COUNTING;
end if;
elsif (current_state = COUNTING) then --will stay in that state until it finishes counting
if (shift_cnt < 72) then
shift_reg(0) <= din;
for i in 0 to 71 loop shift_reg(i+1) <= shift_reg(i); end loop; --shifting register
shift_cnt <= shift_cnt + 1;
else
current_state <= IDLE; --finished counting
end if;
end if;
end if;
end process;
sr_out <= shift_reg;
end behavioral;