I'm trying to get two outputs (pulse(0) and pulse(1)) to deliver a short one clock pulse. The latency between these pulses needs to be controlled by some input value. So 0x1 = 1 clock cycle etc.
At the moment, once the trigger switches on, it stays on
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
use work.ipbus.all;
<...snip>
architecture rtl of trig_latency is
signal ack : std_logic;
signal s_level : unsigned(pulse'range);
signal s_level_d1 : std_logic;
signal bit_shift : std_logic_vector(addr_width downto 0);
signal latency: integer:=5;
begin
latency <= to_integer(unsigned(in_data(addr_width -1 downto 0))) when addr_width > 0 else 0;
process(clk)
begin
if rising_edge(clk) then
if ipbus_in.ipb_strobe='1' and ipbus_in.ipb_write = '1' then
s_level <= s_level + 1;
s_level_d1<=s_level(s_level'left);
else
s_level<=(others=>'0);
end if;
bit_shift <= bit_shift(bit_shift'high-1 downto 0) & (s_level(s_level'left) and (not s_level_d1));
ipbus_out.ipb_rdata <= (others => '0');
ack <= ipbus_in.ipb_strobe and not ack;
pulse(0) <= s_level(s_level'left) and (not s_level_d1);
pulse(1)<=bit_shift(latency);
end if;
end process;
ipbus_out.ipb_ack <= ack;
ipbus_out.ipb_err <= '0';
end rtl;
Why can't you just shift your bits the whole way and ignore the fact that they go above N. The usual VHDL shifter uses the & to concatenate the shifted register with the new value:
bit_shift <= bit_shift(bit_shift'high-1 downto 0) & s_level;
That should produce your shift register just fine.
The pulse(1) <= bit_shift(N) ought to work fine.
Related
I am unfortunately new to VHDL but not new to software development. What is the equivalency to functions in VHDL? Specifically, in the code below I need to debounce four push buttons instead of one. Obviously repeating my process code four times and suffixing each of my signals with a number to make them unique for the four instances is not the professional nor correct way of doing this. How do I collapse all this down into one process "function" to which I can "pass" the signals so I can excise all this duplicate code?
----------------------------------------------------------------------------------
-- Debounced pushbutton examples
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity pushbutton is
generic(
counter_size : integer := 19 -- counter size (19 bits gives 10.5ms with 50MHz clock)
);
port(
CLK : in std_logic; -- input clock
BTN : in std_logic_vector(0 to 3); -- input buttons
AN : out std_logic_vector(0 to 3); -- 7-segment digit anodes ports
LED : out std_logic_vector(0 to 3) -- LEDs
);
end pushbutton;
architecture pb of pushbutton is
signal flipflops0 : std_logic_vector(1 downto 0); -- input flip flops
signal flipflops1 : std_logic_vector(1 downto 0);
signal flipflops2 : std_logic_vector(1 downto 0);
signal flipflops3 : std_logic_vector(1 downto 0);
signal counter_set0 : std_logic; -- sync reset to zero
signal counter_set1 : std_logic;
signal counter_set2 : std_logic;
signal counter_set3 : std_logic;
signal counter_out0 : std_logic_vector(counter_size downto 0) := (others => '0'); -- counter output
signal counter_out1 : std_logic_vector(counter_size downto 0) := (others => '0');
signal counter_out2 : std_logic_vector(counter_size downto 0) := (others => '0');
signal counter_out3 : std_logic_vector(counter_size downto 0) := (others => '0');
signal button0 : std_logic; -- debounce input
signal button1 : std_logic;
signal button2 : std_logic;
signal button3 : std_logic;
signal result0 : std_logic; -- debounced signal
signal result1 : std_logic;
signal result2 : std_logic;
signal result3 : std_logic;
begin
-- Make sure Mercury BaseBoard 7-Seg Display is disabled (anodes are pulled high)
AN <= (others => '1');
-- Feed buttons into debouncers
button0 <= BTN(0);
button1 <= BTN(1);
button2 <= BTN(2);
button3 <= BTN(3);
-- Start or reset the counter at the right time
counter_set0 <= flipflops0(0) xor flipflops0(1);
counter_set1 <= flipflops1(0) xor flipflops1(1);
counter_set2 <= flipflops2(0) xor flipflops2(1);
counter_set3 <= flipflops3(0) xor flipflops3(1);
-- Feed LEDs from the debounce circuitry
LED(0) <= result0;
LED(1) <= result1;
LED(2) <= result2;
LED(3) <= result3;
-- Debounce circuit 0
process (CLK)
begin
if (CLK'EVENT and CLK = '1') then
flipflops0(0) <= button0;
flipflops0(1) <= flipflops0(0);
if (counter_set0 = '1') then -- reset counter because input is changing
counter_out0 <= (others => '0');
elsif (counter_out0(counter_size) = '0') then -- stable input time is not yet met
counter_out0 <= counter_out0 + 1;
else -- stable input time is met
result0 <= flipflops0(1);
end if;
end if;
end process;
-- Debounce circuit 1
process (CLK)
begin
if (CLK'EVENT and CLK = '1') then
flipflops1(0) <= button1;
flipflops1(1) <= flipflops1(0);
if (counter_set1 = '1') then -- reset counter because input is changing
counter_out1 <= (others => '0');
elsif (counter_out1(counter_size) = '0') then -- stable input time is not yet met
counter_out1 <= counter_out1 + 1;
else -- stable input time is met
result1 <= flipflops1(1);
end if;
end if;
end process;
-- Debounce circuit 2
process (CLK)
begin
if (CLK'EVENT and CLK = '1') then
flipflops2(0) <= button2;
flipflops2(1) <= flipflops2(0);
if (counter_set2 = '1') then -- reset counter because input is changing
counter_out2 <= (others => '0');
elsif (counter_out2(counter_size) = '0') then -- stable input time is not yet met
counter_out2 <= counter_out2 + 1;
else -- stable input time is met
result2 <= flipflops2(1);
end if;
end if;
end process;
-- Debounce circuit 3
process (CLK)
begin
if (CLK'EVENT and CLK = '1') then
flipflops3(0) <= button3;
flipflops3(1) <= flipflops3(0);
if (counter_set3 = '1') then -- reset counter because input is changing
counter_out3 <= (others => '0');
elsif (counter_out3(counter_size) = '0') then -- stable input time is not yet met
counter_out3 <= counter_out3 + 1;
else -- stable input time is met
result3 <= flipflops3(1);
end if;
end if;
end process;
end pb;
VHDL has functions but function calls are expressions and not statements or expression statements as in some programming languages. A function call always returns a value of a type and an expression can't represent a portion of a design hierarchy.
Consider the other subprogram class procedures which are statements instead.
The debouncer processes and associated declarations can also be simplified without using a procedure:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity pushbutton is
generic (
counter_size: integer := 19 -- The left bound of debounce counters
);
port (
clk: in std_logic;
btn: in std_logic_vector(0 to 3);
an: out std_logic_vector(0 to 3);
led: out std_logic_vector(0 to 3)
);
end entity pushbutton;
architecture pb1 of pushbutton is
-- There are two flip flops for each of four buttons:
subtype buttons is std_logic_vector(0 to 3);
type flip_flops is array (0 to 1) of buttons;
signal flipflops: flip_flops;
signal counter_set: std_logic_vector(0 to 3);
use ieee.numeric_std.all;
type counter is array (0 to 3) of
unsigned(counter_size downto 0);
signal counter_out: counter := (others => (others => '0'));
begin
an <= (others => '1');
counter_set <= flipflops(0) xor flipflops(1);
DEBOUNCE:
process (clk)
begin
if rising_edge (clk) then
flipflops(0) <= btn;
flipflops(1) <= flipflops(0);
for i in 0 to 3 loop
if counter_set(i) = '1' then
counter_out(i) <= (others => '0');
elsif counter_out(i)(counter_size) = '0' then
counter_out(i) <= counter_out(i) + 1;
else
led(i) <= flipflops(1)(i);
end if;
end loop;
end if;
end process;
end architecture pb1;
Moving part of the design specification into a procedure:
architecture pb2 of pushbutton is
-- There are two flip flops for each of four buttons:
subtype buttons is std_logic_vector(0 to 3);
type flip_flops is array (0 to 1) of buttons;
signal flipflops: flip_flops;
signal counter_set: std_logic_vector(0 to 3);
use ieee.numeric_std.all;
type counter is array (0 to 3) of
unsigned(counter_size downto 0);
signal counter_out: counter := (others => (others => '0'));
procedure debounce (
-- Can eliminate formals of mode IN within the scope of their declaration:
-- signal counter_set: in std_logic_vector (0 to 3);
-- signal flipflops: in flip_flops;
signal counter_out: inout counter;
signal led: out std_logic_vector(0 to 3)
) is
begin
for i in 0 to 3 loop
if counter_set(i) = '1' then
counter_out(i) <= (others => '0');
elsif counter_out(i)(counter_size) = '0' then
counter_out(i) <= counter_out(i) + 1;
else
led(i) <= flipflops(1)(i);
end if;
end loop;
end procedure;
begin
an <= (others => '1');
counter_set <= flipflops(0) xor flipflops(1);
DEBOUNCER:
process (clk)
begin
if rising_edge (clk) then
flipflops(0) <= btn;
flipflops(1) <= flipflops(0);
-- debounce(counter_set, flipflops, counter_out, led);
debounce (counter_out, led);
end if;
end process;
end architecture pb2;
Here the procedure serves as a collection of sequential statements and doesn't save any lines of code.
Sequential procedure calls can be useful to hide repetitious clutter. The clutter has been removed already by consolidating declarations and using the loop statement. There's a balancing act between the design entry effort, code maintenance effort and user readability, which can also be affected by coding style. Coding style is also affected by RTL constructs implying hardware.
Moving the clock evaluation into a procedure would require the procedure call be be a concurrent statement, similar to an instantiation, which you already have. It doesn't seem worthwhile here should you consolidate signals declared as block declarative items in the architecture body or when using a loop statement.
Note that result and button declarations have been eliminated. Also the use of package numeric_std and type unsigned for the counters prevents inadvertent assignment to other objects with the same subtype. The counter values are treated as unsigned numbers while counter_set for instance is not.
Also there's an independent counter for each input being debounced just as in the original. Without independent counters some events might be lost for independent inputs when a single counter is repetitively cleared.
This code hasn't been validated by simulation, lacking a testbench. With the entity both architectures analyze and elaborate.
There doesn't appear to be anything here other than sequential statements now found in a for loop that would benefit from a function call. Because a function call returns a value the type of that value would either need to be a composite (here a record type) or be split into separate function calls for each assignment target.
There's also the generate statement which can elaborate zero or more copies of declarations and concurrent statements (here a process) as block statements with block declarative items. Any signal used only in an elaborated block can be a block declarative item.
architecture pb3 of pushbutton is
begin
DEBOUNCERS:
for i in btn'range generate
signal flipflops: std_logic_vector (0 to 1);
signal counter_set: std_logic;
signal counter_out: unsigned (counter_size downto 0) :=
(others => '0');
begin
counter_set <= flipflops(0) xor flipflops(1);
DEBOUNCE:
process (clk)
begin
if rising_edge (clk) then
flipflops(0) <= btn(i);
flipflops(1) <= flipflops(0);
if counter_set = '1' then
counter_out <= (others => '0');
elsif counter_out(counter_size) = '0' then
counter_out <= counter_out + 1;
else
led(i) <= flipflops(1);
end if;
end if;
end process;
end generate;
end architecture pb3;
Addendum
The OP pointed out an error made in the above code due to a lack of simulation and complexity hidden by abstraction when synthesizing architecture pb2. While the time for the debounce counter was given at 10.5 ms (50 MHz clock) the name of the generic (counter_size) is also actually the left bound of the counter (given as an unsigned binary counter using type unsigned).
The mistake (two flip flops in the synchronizer for each of four buttons) and simply acceding to the OP's naming convention with respect to the counter has been corrected in the above code.
The OP's synthesis error in the comment relates to the requirement there be a matching element for each element on the left hand or right hand of an aassignment statement.
Without synthesizing the code (which the OP did) the error can't be found without simulation. Because the only thing necessary to find the particular error assigning flipflops(0) is the clock a simple testbench can be written:
use ieee.std_logic_1164.all;
entity pushbutton_tb is
end entity;
architecture fum of pushbutton_tb is
signal clk: std_logic := '0';
signal btn: std_logic_vector (0 to 3);
signal an: std_logic_vector(0 to 3);
signal led: std_logic_vector(0 to 3);
begin
CLOCK:
process
begin
wait for 0.5 ms;
clk <= not clk;
if now > 50 ms then
wait;
end if;
end process;
DUT:
entity work.pushbutton (pb2)
generic map (
counter_size => 4 -- FOR SIMULATION
)
port map (
clk => clk,
btn => btn,
an => an,
led => led
);
STIMULUS:
process
begin
btn <= (others => '0');
wait for 20 ms;
btn(0) <= '1';
wait for 2 ms;
btn(1) <= '1';
wait for 3 ms;
btn(2) <= '1';
wait for 6 ms;
btn(3) <= '1';
wait;
end process;
end architecture;
The corrected code and a testbench to demonstrate there are no matching element errors in assignment during simulation.
Simulation was provided for both architectures with identical results.
The generic was used to reduce the size of the debounce counters using a 1 millisecond clock in the testbench (to avoid simulation time with 50 MHz clock events that don't add to the narrative).
Here's the output of the first architecture's simulation:
The caution here is that designs should be simulated. There's a class of VHDL semantic error conditions that are checked only at runtime (or in synthesis).
Added abstraction for reducing 'uniquified' code otherwise identically performing can introduce such errors.
The generate statement wouldn't have that issue using names in a design hierarchy:
The concurrent statements and declarations found in a generate statement are replicated in any generated block statements implied by the generate statement. Each block statement represents a portion of a design hierarchy.
There's been a trade off between design complexity and waveform display organization for debugging.
A design description depending on hiding repetitious detail should be simulated anyway. Here there are two references to the generate parameter i used in selected names, susceptible to the same errors as ranges should parameter substitution be overlooked.
A multiple bit debouncing circuit might look like this:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.Utilities.all;
entity Debouncer is
generic (
CLOCK_PERIOD_NS : positive := 10;
DEBOUNCE_TIME_MS : positive := 3;
BITS : positive
);
port (
Clock : in std_logic;
Input : in std_logic_vector(BITS - 1 downto 0);
Output : out std_logic_vector(BITS - 1 downto 0) := (others => '0')
);
end entity;
architecture rtl of Debouncer is
begin
genBits: for i in Input'range generate
constant DEBOUNCE_COUNTER_MAX : positive := (DEBOUNCE_TIME_MS * 1000000) / CLOCK_PERIOD_NS;
constant DEBOUNCE_COUNTER_BITS : positive := log2(DEBOUNCE_COUNTER_MAX);
signal DebounceCounter : signed(DEBOUNCE_COUNTER_BITS downto 0) := to_signed(DEBOUNCE_COUNTER_MAX - 3, DEBOUNCE_COUNTER_BITS + 1);
begin
process (Clock)
begin
if rising_edge(Clock) then
-- restart counter, whenever Input(i) was unstable within DEBOUNCE_TIME_MS
if (Input(i) /= Output(i)) then
DebounceCounter <= DebounceCounter - 1;
else
DebounceCounter <= to_signed(DEBOUNCE_COUNTER_MAX - 3, DebounceCounter'length);
end if;
-- latch input bit, if input was stable for DEBOUNCE_TIME_MS
if (DebounceCounter(DebounceCounter'high) = '1') then
Output(i) <= Input(i);
end if;
end if;
end process;
end generate;
end architecture;
In stead of a counter size, it expects the user to provide a frequency (as period in nanoseconds) and a debounce time (in milliseconds).
The referenced package implements a log2 function.
I've created this simple mod16 counter using basys3 board and something is not right with my clock. The code itself do works, however one count (changing from "1" to "2" etc.) last 40 seconds, instead of 1 second! I've tried to lower the "clk_vector" if condition to 1 but it didn't help either.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity mod_16_k is
Port ( switch : in STD_LOGIC_VECTOR (3 downto 0);
CLK1 : in STD_LOGIC;
reset : in STD_LOGIC;
led : out STD_LOGIC_VECTOR (15 downto 0));
end mod_16_k;
architecture Behavioral of mod_16_k is
signal clk_vector :integer;
signal clk_vec2 :std_logic_vector(15 downto 0);
begin
zegar_wew : process(CLK1)
begin
if(CLK1'event and CLK1 = '1') then
clk_vector <= clk_vector + 1;
if(clk_vector = 100000000) then
clk_vec2 <= std_logic_vector(unsigned(clk_vec2) + 1);
end if;
end if;
end process;
led <= clk_vec2;
end Behavioral;
The .XDC lines for clock are:
If we check the basys3 datasheet, the clock is connected to "W5" port.
Do you have any idea, what might be the problem in here? It might be connected with detecting the rising edge of an clk, however all of the changes (from 1 to 2 etc.) last ~40 seconds.
This is because you forget to reset clk_vector once it reaches 1 second. Because it is an integer, it is 32 bits, thus will count 2^32 instead of 100000000.
This should work:
If(CLK1'event and CLK1 = '1') then
if(clk_vector = 100000000-1) then
clk_vector <= 0;
clk_vec2 <= std_logic_vector(unsigned(clk_vec2) + 1);
else
clk_vector <= clk_vector + 1;
end if;
end if;
Also, notice that to count 1 second, you need to count up to 100000000-1, we start counting from zero!
I am writing a VHDL code to control AD7193 via SPI communication. ADC is controlled and configured via number of con-chip registers, DOUT/RDY (SPI_miso) goes low to indicate the completion of conversion. These are the code and timing characteristics (Please see Here) of AD7193.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity MainADC is port (
clk : in std_logic; -- OSC 50MHz
rst : in std_logic; -- Reset clock
sclk : out std_logic; -- out clock
cs : out std_logic; -- Chip select
spi_mosi: out std_logic; -- Write register
start : in std_logic; -- Start Conversion
spi_miso: in std_logic); -- Read register/Single channel, 24 bits
end MainADC;
architecture Behavior of MainADC is
signal outclk : std_logic;
signal clk_sel : std_logic; -- Clock Control
signal CommMode: std_logic_vector(7 downto 0) :="00001000"; -- Communications register==> next stage: Mode Register
signal Mode : std_logic_vector(23 downto 0) := "001010000000000001100000"; -- Single conversion mode
signal CommRead: std_logic_vector(7 downto 0) := "01011000"; -- Communications register==> next stage: Read Data
begin
cs <= '0'; -- Hardwired low
process(clk, rst) -- Clock_gen 500KHz
variable cnt : integer range 0 to 500 :=1;
begin
if (rst='1') then
cnt := 0;
outclk <= '0';
elsif (clk = '1' and clk'event) then
cnt := cnt + 1;
if (cnt = 50) then
cnt := 0;
outclk <= not outclk;
end if;
end if;
end process;
process(clk_sel)
begin
if (clk_sel='0') then
sclk <= '1'; --Clock Idle High
else
sclk <= outclk; --Provide Clock Cycles
end if;
end process;
process (outclk) -- SPI Comm
variable i : integer :=0;
variable data_temp: std_logic_vector(23 downto 0) :=(others=>'0');
begin
if (start = '0') then
clk_sel <= '0';
i:=0;
else
if falling_edge(outclk) then
i:=i+1;
if (i>=0 and i<=7) then -- Communications register==> next stage: Mode Register (8 bits)
clk_sel <= '1';
CommMode(7 downto 1) <= CommMode(6 downto 0);
CommMode(0) <= CommMode(7);
spi_mosi <= CommMode(7);
elsif (i=8) then
clk_sel <= '0'; --Clock Idle High
elsif (i>=9 and i<=32) then -- Single conversion mode (24 bits)
clk_sel <= '1';
Mode(23 downto 1) <= Mode(22 downto 0);
Mode(0) <= Mode(23);
spi_mosi <= Mode(23);
elsif (i=33) then
clk_sel <= '0'; --Clock Idle High
wait until (spi_miso'event and spi_miso='0'); --Wait for Ready Read Signal (DOUT/DRY)
elsif (i>=34 and i<= 41) then -- Communications register==> next stage: Read Data
clk_sel <= '1';
CommRead(7 downto 1) <= CommRead(6 downto 0);
CommRead(0) <= CommRead(7);
spi_mosi <= CommRead(7);
elsif (i=42) then
clk_sel <= '0'; --Clock Idle High
elsif (i>=43 and i<= 66) then
clk_sel <= '1';
data_temp(23 downto 0) := data_temp(22 downto 0) & spi_miso; --Read Data
elsif (i>=66 and i<=566) then -- Waiting for ADC Power Up after Conversion (~1ms)
clk_sel <= '0'; --Clock Idle High
elsif (i=567) then
i:=0;
end if;
end if;
end if;
end process;
end Behavior;
As far as I know Wait Until statement supports for vhdl synthesis, but I received this error: "Error (10441): VHDL Process Statement error at Main ADC.vhd(53): Process Statement cannot contain both a sensitivity list and a Wait Statement". How can I solve this error? Is there any other way to hold counter and waiting for DOUT/RDY event to know when conversion is complete for read data? Any opinions are appreciated! Thank you.
The error message is due to a VHDL language semantic restriction.
The wait until implies you're using spi_miso as a clock, and it looks like you're requiring a flip flop to toggle as a result of i counter reaching 33, before progressing to 34.
The error about the sensititvity list item (outclock) and the wait statement is telling you you can't use two different clocks in this process.
If there is no metastability issue with outclk, instead of waiting don't increment i unless spio_miso = 0 when i = 33. You could also evaluate i before incrementing it (the equivalent of making i a signal).
This may deserve simulation before synthesis. There may be other issues lurking in there.
Your VHDL analyzes with a couple of changes:
if falling_edge(outclk) then
if ( i /= 33 or spi_miso = '0' ) then
i:= i + 1;
end if;
if (i>=0 and i<=7) then -- Communications register==> next stage: Mode Register (8 bits)
clk_sel <= '1';
CommMode(7 downto 1) <= CommMode(6 downto 0);
CommMode(0) <= CommMode(7);
spi_mosi <= CommMode(7);
elsif (i=8) then
clk_sel <= '0'; --Clock Idle High
elsif (i>=9 and i<=32) then -- Single conversion mode (24 bits)
clk_sel <= '1';
Mode(23 downto 1) <= Mode(22 downto 0);
Mode(0) <= Mode(23);
spi_mosi <= Mode(23);
-- elsif (i=33) then
-- clk_sel <= '0'; --Clock Idle High
-- wait until (spi_miso'event and spi_miso='0'); --Wait for Ready Read Signal (DOUT/DRY)
elsif (i>=34 and i<= 41) then -- Communications register==>
(And I normally wouldn't put parentheses around an if statement expression.)
I'm trying to make a grid on the screen using this VHDL.
I can make two lines now, but when I refresh the screen, the lines move.
I'm not sure where the error is, can someone help or offer any pointers?
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.std_logic_unsigned.all;
--use IEEE.std_logic_arith.all; --VVVVVVV
use IEEE.NUMERIC_STD.all; --^^^^^^^
entity SCRN is
port(
clk : in STD_LOGIC;
vga : OUT STD_LOGIC_VECTOR (7 downto 0);
Hsync : OUT STD_LOGIC;
Vsync : OUT STD_LOGIC
);
end SCRN;
architecture Behavioral of SCRN is
type PLC_HOLD is array (1 to 800, 1 to 525) of STD_LOGIC_VECTOR(7 downto 0);
signal scrn : PLC_HOLD;
signal s_clk : std_logic_vector (1 downto 0) := (others => '0');
signal xx_vga : std_logic_vector (7 downto 0);
signal xx_h : std_logic;
signal xx_v : std_logic;
signal X : std_logic_vector (9 downto 0) := (others => '1');
signal Y : std_logic_vector (9 downto 0) := (others => '1');
-- signal test : ieee.numeric_std.unsigned
-- test now works with mod
begin
NW_CLK: process (clk) is
begin
if rising_edge (clk) then
s_clk <= (s_clk + "01");
end if;
end process NW_CLK;
--###############################--
scrn_loc :
process (s_clk(1)) is
begin
if RISING_EDGE (s_clk(1)) then
X <= X + "0000000001";
if (X = "1100100000") then --if x = 800
X <= "0000000001";
Y <= (Y + "0000000001");
elsif (Y = 525) then -- if y = 525
X <= "0000000001";
Y <= "0000000001";
end if;
end if;
end process;
--###############################--
draw :
process (X,Y) is
-- h and v sync process
begin
if (X > 640) then -- and (X <= 752) then -- low for sync pulse at 656 to 752 -- 96 pixel
xx_h <= '0';
else
xx_h <= '1';
end if;
if (Y> 490) and (Y <= 492) then -- low for sync puls at 490 to 492
xx_v <= '0';
else
xx_v <= '1';
end if;
-- (CONV_INTEGER((X)) mod 10)
-- CONV_INTEGER(Y) mod 10
-- if X = 1 then
-- xx_vga <= "00111000";
---- elsif Y = 1 or Y = 480 then
---- xx_vga <= "11101011";
-- else
-- xx_vga <= "11100000";
-- end if;
end process;
--###############################--
scrn(CONV_INTEGER(X),CONV_INTEGER(Y)) <= "00111000" when X = 1 else
"11100101" when Y = 2 else
"00000111" when X = 640 else
"11001101";
Hsync <= xx_h;
Vsync <= xx_v;
vga <= scrn(CONV_INTEGER(X),CONV_INTEGER(Y));
end Behavioral;
Hmmm... What happens if you move the line where you assign to scrn(CONV_INTEGER(X),CONV_INTEGER(Y)) <= "00111000" when X = 1 else ... to somewhere inside your process?
Also there is no need to use binary literals in your code (e.g., if (X = "1100100000")). Just use integer literals, or decimal bit-string literals. Better yet, define all your numeric values as integers or naturals. As a bonus, your code will be cleaner because you won't need all those conversion functions.
You are creating a clock from a clock, which is a bad idea. It seems you are trying to divide by 4? Instead create an enable pulse:
NW_CLK: process (clk) is
variable divider : integer range 0 to 3;
begin
if rising_edge (clk) then
if divider = 3 then
divider := 0;
screen_process_enable <= '1';
else
divider := divider + 1;
screen_process_enable <= '0';
end if
end if;
end process NW_CLK;
Then in the screen process:
scrn_loc : process (clk) is
begin
if RISING_EDGE (clk) and screen_process_enable = '1' then
etc...
Not related to your question, but I'll comment on it here anyway: You seem to be trying to hold the entire screen in memory - that's quite a lot of storage you are asking for in a real chip (it'll be fine in simulation).
For producing a grid you can just do it on the fly, by assigning to the VGA output depending on the values of your x and y counters. Because you have both the assignment to scrn and vga outside of a process, the synthesiser is probably clever enough to figure out that you never make use of the memory storage you've asked for and has optimised it away. If at some future point you come to use scrn as a true framebuffer, you may run up against performance or resource limitations, depending on your device.
Check chapter 15 (VHDL Design of VGA Video Interfaces) of "Circuit Design and Simulation with VHDL", which shows detailed VGA theory followed by a number of experiments using VHDL and VGA monitors.
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;