so I seem to be having a problem in regards to flag signal getting asserted. So basically I am implementing i2c interface between 2 fpga's. My master will send over 50 bytes. On my slave side I want to store the byte coming in into an array. So I check when ever the whole byte is read and available i put it into an array. Now the problem is that after i fill up the whole array i want to assert a signal that should activate a process. My problem is that when the signal is asserted and the process is activated that that I am stuck in the idle loop forever, which confuses me because I was under the assumption that when i enter the process and check the flag signal assertion condition that it is suppose to be high. So is the problem that my signal is not activating the process or is my problem that the by the time i check the flag assertion conditional that the flag already went back to 0?
I have attached some code:
signal i : integer range 0 to 49 := 0;
type field_array is array(0 to 49) of std_logic_vector(7 downto 0);
begin
process(clk,rst)
begin
if( rst = '1') then
i <= 0;
elsif (rising_edge(clk)) then
if(data_available = '1') then
array_of_data(i) <= Master_Data;
i <= i + 1;
end if;
if(i = 49) then
i <= 0; -- reset index back to zero
end if;
end if;
end process;
flag <= '1' when i = 49 else '0';
process(state,flag)
begin
next_state <= state;
case (state) is
when idle =>
if(flag = '1') then
next_state <= Send_data;
end if;
when Send_data =>...
There is a bounds check failure on your assignment, i <= i+1;. It is trying to evaluate it before the check that is performed later (if i=49...).
Change the synchronous part of you code to:
elsif rising_edge(clk) then
if data_available = '1' then
array_of_data(i) <= Master_Data;
if i = 49 then
i <= 0;
else
i <= i + 1;
end if;
end if;
end if;
EDIT:
You can see that the flag is being asserted and the state changes here.
Further EDIT:
Consider making your state machine synchronous and removing the next_state signal. eg.
type state_t is (idle_s, send_s, others_s);
signal state : state_t := idle_s;
...
process(clk,rst)
begin
if rst = '1' then
-- rst
elsif rising_edge(clk) then
case (state) is
when idle_s =>
if flag = '1' then
state <= send_s;
else
state <= idle_s;
end if;
when send_s =>
-- Do stuff
when others =>
-- stuff
end case;
end if;
end process;
If you want to assign your outputs as soon as your state changes, you can use a two process state machine. One of the processes (synchronous) is used to control state transitions, the other is used to control the output (combinational). You would effectively have another process similar to the first:
process(state)
begin
case state is
when idle_s =>
my_output <= '0';
when send_s =>
-- Assign output as necessary
my_output <= '1';
when others =>
--assign output
end case;
end process;
An example is shown here.
Related
I'm trying to simulate a pulse width modulate (PMW) waveform generator and getting a syntax error in ISE. Checked fuse.xmsgs and found out it's near counter. Can someone point out the syntax error, please?
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.numeric_std.all;
entity pwm_gen is
port
(
clock, reset : in std_logic;
width : in std_logic_vector(7 downto 0);
pwm : out std_logic);
end pwm_gen;
architecture bhv of pwm_gen is
type counter is range 0 to 255;
counter count := 0;
begin
process (clock)
begin
if (reset = '1') then
count <= 0;
elsif (clock'event and clock = '1') then
if (count <= width) then
count <= count + 1;
pwm <= '1';
else
count <= count + 1;
pwm <= '0';
end if;
end if;
end process;
end bhv;
counter count := 0;
This is illegal syntax, as you didnt declare the object class (signal, constant, variable). You need to use the format:
signal count : counter := 0
This is also illegal, as you are comparing an integer to a std_logic_vector that you havent included a package for. You need to convert the slv to an unsigned
if (count <= unsigned(width)) then
And finally, reset is missing from the sensitivity list
Well, I'm trying to make a module in VHDL language, so far I have the internal clock (100MHz) and a control signal called IN (std_logic), and I need an output signal OUT (std_logic) of arbitrary width, said wide I want to control counting the clock rising_edge, I don't have a good programming base, that's why I'm stuck with this, if anyone can help me I thank you
I enclose an illustrative image of how I wish to have the output, where delta / \ is an arbitrary interval that does not depend on the IN input, when IN goes low, the OUT signal must remain on until the counter finishes its purpose..
https://imgur.com/a/NoPZZjP
So you basically what to create an off delay?
Note: VHDL 2008 migth apply (my usual language)
entity off_delay is
generic(
n : natural : 2 -- off delay
);
port(
clk : in std_logic;
a : in std_logic;
b : out std_logic
);
end entity;
clk _/¯\__/¯\_/¯\_/¯\_/¯\_/¯\_/¯\_/¯\_/¯\_/¯\_/¯\_/¯\_/¯\
a _____/¯¯¯\________________________________
b _________/¯¯¯¯¯¯¯¯¯¯¯¯\___________________
architecture synkron of off_delay is
signal delay: std_logic_vector(n downto 0); -- 1+n cycles out signal
begin
b <= delay(0);
process(clk)
begin
if rising_edge(clk) then
delay <= (others => '1') when a else ('0' & delay(delay'left downto 1));
end if;
end process;
end architecture;
clk _/¯\__/¯\_/¯\_/¯\_/¯\_/¯\_/¯\_/¯\_/¯\_/¯\_/¯\_/¯\
a _____/¯¯¯\_____________________________
b _____/¯\¯\¯¯¯¯¯¯¯¯¯¯\___________________
architecture asynkron of off_delay is
signal delay: std_logic_vector(n-1 downto 0); -- n cycles off delay
begin
b <= delay(0) or a;
process(clk)
begin
if rising_edge(clk) then
delay <= (others => '1') when a else ('0' & delay(delay'left downto 1));
end if;
end process;
end architecture;
Note: The asynkron solution will be dependent on stable a as it will be susceptible to glitches.
Note: The asynkron solution will introduce a delta delay that might be hard to debug
Note: Those are the simplest soulutions. To get technical a SR latch could be implemented to set by a in an asynkron fassion and reset by the synkron delay line. OBS Latches are strongly adviced against in fpga design!
Here is another solution which use more ressources with a low width but less with a high width and with width as an input instead of generic :
entity top is
port
(
i_rst : in std_logic;
i_clk : in std_logic;
i_din : in std_logic;
i_width : in std_logic_vector(7 downto 0);
o_dout : out std_logic
);
end top;
architecture Behavioral of top is
signal counter : unsigned(7 downto 0);
signal oe : std_logic;
begin
process(i_clk)
begin
if i_rst = '1' then
counter <= (others => '0');
oe <= '0';
elsif rising_edge(i_clk) then
if oe = '1' then
counter <= counter + 1;
if counter = unsigned(i_width) - 1 then
counter <= (others => '0');
oe <= '0';
end if;
elsif i_din = '1' then
if unsigned(i_width) > x"01" then
counter <= counter + 1;
oe <= '1';
end if;
end if;
end if;
end process;
o_dout <= oe or i_din;
end Behavioral;
But as Halfow told you, use combinational just before the output makes your module very sensitive to glitches.
module accumulator (
input [7:0] A ,
input reset,
input clk,
output reg carryout,
output reg overflow,
output reg [8:0] S,
output reg HEX0,
output reg HEX1,
output reg HEX2,
output reg HEX3
);
reg signA;
reg signS;
reg [7:0] magA;
reg [7:0] magS;
reg Alarger;
initial begin
S = 9'b000000000;
end
always_ff # (posedge clk, posedge reset) begin
if (reset) begin
S = 9'b000000000;
end
else begin
begin
signA <= A[7]; //Is A negative or positive
signS <= S[7];
S <= A + S;
end
if (signA == 1) begin //A is negative so magnitude is of 2s compliment
magA <= (~A[7:0] + 1'b1);
end
else begin
magA <= A;
end
if (signS == 1) begin //sum is negative so magnitude is of 2s compliment
magS <= (~S[7:0] + 1'b1);
end
else begin
magS <= S;
end
if (magA > magS) begin
Alarger <= 1'b1; //Magnitude of A is larger than magnitude of sum
end
else begin
Alarger <= 1'b0;
end
if ((signA == 1) & (Alarger == 1) & (S[7] == 0)) begin
overflow <= 1'b1;
end
else begin
overflow <= 1'b0;
end
if ((signS == 1) & (Alarger == 0) & (S[7] == 0)) begin
overflow <= 1'b1;
end
else begin
overflow <= 1'b0;
end
if ((signS == 1) & (signA == 1) & (S[7] == 0)) begin
overflow <= 1'b1;
end
else begin
overflow <= 1'b0;
end
if ((signS == 0) & (signA == 0) & (S[7] == 1)) begin
overflow <= 1'b1;
end
else begin
overflow <= 1'b0;
end
if (S[8] == 1) begin //carryout occurred
carryout <= 1'b1;
overflow <= 1'b0;
S <= 9'b000000000; //sum no longer valid
end
else begin
carryout <= 1'b0;
end
display_hex h1 //display of A
(
.bin (magA),
.hexl (HEX2),
.hexh (HEX3)
);
display_hex h2 //display of sum
(
.bin (S[7:0]),
.hexl (HEX0),
.hexh (HEX1)
);
end
end
endmodule
I am trying to make an accumulator that adds A (8 digit binary value that can be signed or unsigned) repeatedly to the sum. Once the sum is computed, then sum and A should display the value on 4 hex display LEDs (2 LEDs for A and 2 LEDs for sum). However, I am having a hard time getting it to compile. I have searched the error code and it seems like a general error for a syntax error and can have several meanings.
The error is the result of these two lines:
display_hex h1 //display of A
(
.bin (magA),
.hexl (HEX2),
.hexh (HEX3)
);
display_hex h2 //display of sum
(
.bin (S[7:0]),
.hexl (HEX0),
.hexh (HEX1)
);
Here, it appears you have a module named display_hex which converts an 8-bit value into the needed digits for a seven segment display. You are trying to use the module as if it were a function and modules are very much NOT functions. Modules in Verilog (or SystemVerilog as you are using, but the difference is really token at this point) can be though of as a group of hardware that takes in some inputs and spits out some outputs; and its important to note that they are static things. They either exist in the design or they do not; just like using ICs on a breadboard. The top module is the breadboard and the modules you declare under that module are components you are plugging into the board. The inputs and outputs are the various connections (pins) you must wire up to make everything work.
That said, always blocks (like the always_ff you are using) form a way of describing the logic and registers inside modules. Thus, you do thinks like assign logic/reg variables inside them to describe how the hardware behaves. If you look at your logic, you'll notice that the module declarations are dependent on reset; ie if reset is asserted, these modules wont exist, which doesnt make any sense. Electrical signals don't make entire ICs in a circuit disappear! Thus, you need to pull your module declaration out of your logical description of your acculumator, like so:
module accumulator (
...
);
...
display_hex h1 //display of A
(
.bin (magA),
.hexl (HEX2),
.hexh (HEX3)
);
display_hex h2 //display of sum
(
.bin (S[7:0]),
.hexl (HEX0),
.hexh (HEX1)
);
...
always_ff #(posedge clk, posedge reset) begin
// Your accumulator logic here
...
end
endmodule
Notice that the module declarations for the display_hex modules are stand alone, as I am declaring these modules exist, not dependence on anything!
However, there are a number of issues with your design besides that:
As you are using SystemVerilog constructs (always_ff), you should declare all of your variables type logic, not reg or left blank (ie, input clk should be input logic clk, reg signA should be logic signA). The logic type just makes everything easier, so use it :)
In your always_ff block, you do reset correctly except that the assignment should really be NBA (use S <= 9'b0;, not S = 9'b0; in the if (reset))
You use NBA inside your always_ff, which is correct, however, it appears you need to use these values right away in the following logic. This will not work as you expect, or at least it will not act within the same clock cycle. To fix this, youll need to decide what should be a register and what should just be values resulting from intermediate logic, then create a separate always_comb for the intermediate values.
I am making the assumption that the HEX variables are meant for seven segment displays, so they should probably declared at least [6:0] HEXn
I was not able to reproduce the exact error, but moving the instantiations of display_hex outside always_ff resolves the main issue:
module accumulator
(
/* ... */
);
// ...
always_ff # (posedge clk, posedge reset) begin
/* ... */
end
display_hex h1 (
/* ... */
);
display_hex h2 (
/* ... */
);
endmodule
Another thing: The code drives variable S from initial as well as always. This creates multiple drivers and the code will not compile. To fix this, remove the initial completely, you don't need it since S will be set to 0 when reset is asserted.
OR
You can move all the logic into the initial block; it'd look something like this (but this, most probably, won't synthesize):
initial begin
S = 0;
forever begin
wait #(posedge clock);
// Do stuff here ..
end
end
I'm new to VHDL and I thought I could try to make a slave SPI device as training, but it's not working quite as expected. Below my current code. It's compiles and upload just fine, but it's not working as intended. Right now I have the leds connected to the signal "bitnumber", bitnumber is supposed to increment on each rising edge of CLK and then reset to zero when the SS pin is pulled LOW (indicating that the transfer is complete), but it doesn't do that. I've connected my Altera DE0-nano to my arduino which is simply pulling the SS LOW, sends four clock pulses and then pulls the SS back high, I've put a 1s delay between each transition. The leds on my altera board does change it's pattern every second, but it does so on both rising and falling edge of the clock, also the led pattern seems completely random, even showing some leds in a dimmed state. The leds become black when the SS pin goes back HIGH though, that's good.
enter code here
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity SPI2 is
PORT (LED : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
GPIO_0 : IN STD_LOGIC_VECTOR(7 DOWNTO 0));
end SPI2;
architecture SPI2_beh of SPI2 is
signal SPIdataregister : STD_LOGIC_VECTOR(7 DOWNTO 0);
signal bitnumber : STD_LOGIC_VECTOR(7 DOWNTO 0);
begin
LED <= bitnumber;
process(GPIO_0(5), GPIO_0(3))
begin
if ((GPIO_0(5)) = '1') then
bitnumber <= (bitnumber + '1');
end if;
if ((GPIO_0(3)) = '1') then
bitnumber <= "00000000";
end if;
end process;
process(bitnumber)
begin
case bitnumber is
when "00000001" => SPIdataregister(0) <= GPIO_0(7);
when "00000010" => SPIdataregister(1) <= GPIO_0(7);
when "00000011" => SPIdataregister(2) <= GPIO_0(7);
when "00000100" => SPIdataregister(3) <= GPIO_0(7);
when "00000101" => SPIdataregister(4) <= GPIO_0(7);
when "00000110" => SPIdataregister(5) <= GPIO_0(7);
when "00000111" => SPIdataregister(6) <= GPIO_0(7);
when "00001000" => SPIdataregister(7) <= GPIO_0(7);
when others => SPIdataregister <= SPIdataregister;
end case;
end process;
end SPI2_beh;
enter code here
I would start by changing the main process to:
process(GPIO_0(5), GPIO_0(3))
variable change_flag : STD_LOGIC := 1;
begin
if GPIO_0(3) = '1' then
bitnumber <= "00000000";
else
if GPIO_0(5) = '0' --btw here, GPIO_0(3) = '0' also
change_flag := '1';
else --btw here, GPIO_0(3) = '0' and GPIO_0(5) = '1'
if change_flag = '1' then
bitnumber <= bitnumber + 1;
change_flag := '0';
end if;
end if;
end if;
end process;
The variable change_flag introduces memory, to ensure the process only reacts once to specifically a rising edge of GPIO_0(5). Without memory implemented like this, you could get the desired effect by having two processes: one dependent on GPIO_0(5) and one dependent on GPIO_0(3). The risk then is of both changing at the same time and causing a conflict: two signals trying to control/change the same output. The above way is better and should be reliable for your purposes.
Secondly, increment bitnumber using
bitnumber <= bitnumber + 1;
note, use the 1 without the quotes. The quotes indicate binary '1' and '0' from what I understand.
Good luck!!
I've written a few components to move a stepper motor back and forwards. I've simulated it in modelsim and it works as expected, but it won't work the same in hardware at all.
Basically I have a motor driving component, which takes a command of number of steps, hold time and speed and then performs the movement. Then I have the control_arbiter, which is just an intermediate bridge that connects components wanting access to the motors and the motor driving components.
Finally I have a 'search pattern' component, which basically issues the commands to move the motor back and forth.
My problem is that I can't seem to get direction to change when it's running in hardware, regardless of it working in simulation.
Any help with this would be greatly appreciated
Motor driver:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity motor_ctrl is
port( clk: in std_logic;
-- Hardware ports
SCLK, CW, EN: out std_logic; -- stepper driver control pins
-- Soft ports
Speed, steps: in integer;
dir: in std_logic; -- 1 = CW; 0 = CCW;
hold_time: in integer; -- if > 0, steppers will be held on for this many clock periods after moving
ready: out std_logic; -- indicates if ready for a movement
activate: in std_logic; -- setting activate starts instructed motion.
pos_out: out integer -- starts at 2000, 180deg = 200 steps, 10 full rotations trackable
);
end motor_ctrl;
architecture behavioural of motor_ctrl is
type action is (IDLE, HOLD, MOVE);
signal motor_action: action := IDLE;
signal clk_new: std_logic;
signal position: integer := 2000;
signal step_count: integer := 0;
signal drive: boolean := false;
begin
-- Clock divider
clk_manipulator: entity work.clk_divide port map(clk, speed, clk_new);
-- Drive motors
with drive select
SCLK <= clk_new when true,
'0' when false;
pos_out <= position;
process(clk_new)
-- Counter variables
variable hold_count: integer := 0;
begin
if rising_edge(clk_new) then
case motor_action is
when IDLE =>
-- reset counter vars, disable the driver and assert 'ready' signal
hold_count := 0;
step_count <= 0;
drive <= false;
EN <= '0';
ready <= '1';
-- When activated, start moving and de-assert ready signal
if(activate = '1') then
motor_action <= MOVE;
end if;
when HOLD =>
-- Stop the step clock signal
ready <= '0';
drive <= false;
-- Hold for given number of clock periods before returning to idle state
if(hold_count = hold_time) then
motor_action <= IDLE;
end if;
-- increment counter
hold_count := hold_count + 1;
when MOVE =>
-- Enable driver, apply clock output and set direction
ready <= '0';
EN <= '1';
drive <= true;
CW <= dir;
-- track the position of the motor
--if(dir = '1') then
-- position <= steps + step_count;
--else
-- position <= steps - step_count;
--end if;
-- Increment count until complete, then hold/idle
if(step_count < steps-1) then
step_count <= step_count + 1;
else
motor_action <= HOLD;
end if;
end case;
end if;
end process;
end behavioural;
Control_arbiter:
entity Control_arbiter is
port (clk: in std_logic;
EN, RST, CTRL, HALF, SCLK, CW: out std_logic_vector(2 downto 0)
-- needs signals for levelling and lock
);
end Control_arbiter;
architecture fsm of Control_arbiter is
type option is (INIT, SEARCH);
signal arbitration: option := INIT;
-- Motor controller arbiter signals
-- ELEVATION
signal El_spd, El_stps, El_hold, El_pos: integer;
signal El_dir, El_rdy, El_run: std_logic;
-- Search signals
signal search_spd, search_stps, search_hold: integer;
signal search_dir, search_Az_run, search_El_run: std_logic := '0';
-- status
signal lock: std_logic := '0';
begin
-- Motor controller components
El_motor: entity work.motor_ctrl port map(clk, SCLK(0), CW(0), EN(0),
El_spd, El_stps, El_dir, El_hold, El_rdy, El_run);
-- Search component
search_cpmnt: entity work.search_pattern port map( clk, '1', search_dir, search_stps, search_spd, search_hold,
El_rdy, search_El_run);
process(clk, arbitration)
begin
if rising_edge(clk) then
case arbitration is
when INIT =>
-- Initialise driver signals
EN(2 downto 1) <= "11";
CW(2 downto 1) <= "11";
SCLK(2 downto 1) <= "11";
RST <= "111";
CTRL <= "111";
HALF <= "111";
-- Move to first stage
arbitration <= SEARCH;
when SEARCH =>
-- Map search signals to motor controllers
El_dir <= search_dir;
El_stps <= search_stps;
El_spd <= search_spd;
El_hold <= search_hold;
El_run <= search_El_run;
-- Pass control to search
-- Once pointed, begin search maneuvers
-- map search signals to motor controllers
-- set a flag to begin search
-- if new pointing instruction received, break and move to that position (keep track of change)
-- On sensing 'lock', halt search
-- return to holding that position
end case;
end if;
end process;
end fsm;
Search Pattern:
entity search_pattern is
generic (step_inc: unsigned(7 downto 0) := "00010000"
);
port (clk: in std_logic;
enable: in std_logic;
dir: out std_logic;
steps, speed, hold_time: out integer;
El_rdy: in std_logic;
El_run: out std_logic
);
end search_pattern;
architecture behavioural of search_pattern is
type action is (WAIT_FOR_COMPLETE, LATCH_WAIT, MOVE_EL_CW, MOVE_EL_CCW);
signal search_state: action := WAIT_FOR_COMPLETE;
signal last_state: action := MOVE_EL_CCW;
begin
hold_time <= 1;
speed <= 1;
steps <= 2;
process(clk)
begin
if rising_edge(clk) then
-- enable if statement
case search_state is
when LATCH_WAIT =>
-- Make sure a GPMC has registered the command before waiting for it to complete
if(El_rdy = '0') then -- xx_rdy will go low if a stepper starts moving
search_state <= WAIT_FOR_COMPLETE; -- Go to waiting state and get ready to issue next cmd
end if;
when WAIT_FOR_COMPLETE =>
-- Wait for the movement to complete before making next
if(El_rdy = '1') then
-- Choose next command based on the last
if last_state = MOVE_EL_CCW then
search_state <= MOVE_EL_CW;
elsif last_state = MOVE_EL_CW then
search_state <= MOVE_EL_CCW;
end if;
end if;
when MOVE_EL_CW =>
dir <= '1';
El_run <= '1';
last_state <= MOVE_EL_CW;
search_state <= LATCH_WAIT;
when MOVE_EL_CCW =>
dir <= '0';
El_run <= '1';
last_state <= MOVE_EL_CCW;
search_state <= LATCH_WAIT;
when others =>
null;
end case;
-- else step reset on not enable
end if;
end process;
end behavioural;
Sim: http://i.imgur.com/JAuevvP.png
scanning quickly through your code, there are some things that you should change for synthesis:
1) clock divider: make your motor_driver process sensitive to clk instead of clk_new. to divide the clock, generate a one-clock-cycle enable signal every n clocks. the begin of the process could look as follows:
process(clk)
...
begin
if rising_edge(clk) then
if enable='1' then
case motor_action is
...
2) initializations of the form
signal position: integer := 2000;
only work for simulations but don't work for synthesis. for initialization in synthesis use a reset signal within the process.
3) add to all your state machines a "when others" clause, where the state is set to a defined value (e.g. search_state<=INIT).