From c423df7bf9ecca3677b2795882c71ab3a989552d Mon Sep 17 00:00:00 2001 From: T-moe Date: Mon, 16 May 2016 15:30:18 +0200 Subject: [PATCH 01/13] Some experiments with dds. probably useless. --- dds.sym | 26 ++++++++++ dds.vhd | 66 +++++++++++++++++++++++++ dds_tb.vhd | 109 +++++++++++++++++++++++++++++++++++++++++ helpers.vhd | 46 ++++++++++++++++++ yasg.gise | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++- yasg.xise | 24 +++++++-- 6 files changed, 403 insertions(+), 5 deletions(-) create mode 100644 dds.sym create mode 100644 dds.vhd create mode 100644 dds_tb.vhd create mode 100644 helpers.vhd diff --git a/dds.sym b/dds.sym new file mode 100644 index 0000000..09f9a87 --- /dev/null +++ b/dds.sym @@ -0,0 +1,26 @@ + + + BLOCK + 2016-5-16T9:25:36 + + + + + + + + + + + + + + + + + + + + + + diff --git a/dds.vhd b/dds.vhd new file mode 100644 index 0000000..77f1645 --- /dev/null +++ b/dds.vhd @@ -0,0 +1,66 @@ +---------------------------------------------------------------------------------- +-- Company: +-- Engineer: +-- +-- Create Date: 11:09:53 05/16/2016 +-- Design Name: +-- Module Name: dds - Behavioral +-- Project Name: +-- Target Devices: +-- Tool versions: +-- Description: +-- +-- Dependencies: +-- +-- Revision: +-- Revision 0.01 - File Created +-- Additional Comments: +-- +---------------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; + +-- Uncomment the following library declaration if instantiating +-- any Xilinx primitives in this code. +--library UNISIM; +--use UNISIM.VComponents.all; +use work.helpers.all; + +entity dds is + Generic (clk_freq: natural:= 50000000; + max_freq: natural := 100000; + adc_res: natural:=12; + vector_res: natural :=8 ); + Port ( clk : in STD_LOGIC; + freq : in unsigned (log2_int(max_freq)-1 downto 0); + form : in unsigned (1 downto 0); + amp : out unsigned (adc_res-1 downto 0); + update : out STD_LOGIC); +end dds; + +architecture Behavioral of dds is + constant clk2 : natural := clk_freq/(2**vector_res); + constant clk2_us :unsigned (log2_int(clk2)-1 downto 0) :=to_unsigned(clk2,log2_int(clk2)); + signal prescale,cnt_prescale :unsigned (log2_int(clk2)-1 downto 0) := (others => '0'); + signal m, idx : unsigned(vector_res -1 downto 0):= (others => '0'); + +begin + prescale <= divide(to_unsigned(clk2,prescale'length),freq); + m <= resize(divide(freq*prescale,to_unsigned(clk2,prescale'length)),m'length); + + P1: process(clk) + begin + if(rising_edge(clk)) then + if(cnt_prescale >= prescale) then + cnt_prescale <= to_unsigned(1, prescale'length); + idx <= (idx+m) mod (2**vector_res); + else + cnt_prescale <= cnt_prescale +1; + end if; + end if; + end process P1; + + +end Behavioral; + diff --git a/dds_tb.vhd b/dds_tb.vhd new file mode 100644 index 0000000..c954bbf --- /dev/null +++ b/dds_tb.vhd @@ -0,0 +1,109 @@ +-------------------------------------------------------------------------------- +-- Company: +-- Engineer: +-- +-- Create Date: 11:35:57 05/16/2016 +-- Design Name: +-- Module Name: /home/timo/vhdl-yasg/dds_tb.vhd +-- Project Name: yasg +-- Target Device: +-- Tool versions: +-- Description: +-- +-- VHDL Test Bench Created by ISE for module: dds +-- +-- Dependencies: +-- +-- Revision: +-- Revision 0.01 - File Created +-- Additional Comments: +-- +-- Notes: +-- This testbench has been automatically generated using types std_logic and +-- std_logic_vector for the ports of the unit under test. Xilinx recommends +-- that these types always be used for the top-level I/O of a design in order +-- to guarantee that the testbench will bind correctly to the post-implementation +-- simulation model. +-------------------------------------------------------------------------------- +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +USE ieee.numeric_std.ALL; + +ENTITY dds_tb IS +END dds_tb; + +ARCHITECTURE behavior OF dds_tb IS + + -- Component Declaration for the Unit Under Test (UUT) + + COMPONENT dds + PORT( + clk : IN std_logic; + freq : IN unsigned(16 downto 0); + form : IN unsigned(1 downto 0); + amp : OUT unsigned(11 downto 0); + update : OUT std_logic + ); + END COMPONENT; + + + --Inputs + signal clk : std_logic := '0'; + signal freq : unsigned(16 downto 0) := (others => '0'); + signal form : unsigned(1 downto 0) := (others => '0'); + + --Outputs + signal amp : unsigned(11 downto 0); + signal update : std_logic; + + -- Clock period definitions + constant clk_period : time := 10 ns; + +BEGIN + + -- Instantiate the Unit Under Test (UUT) + uut: dds PORT MAP ( + clk => clk, + freq => freq, + form => form, + amp => amp, + update => update + ); + + -- Clock process definitions + clk_process :process + begin + clk <= '0'; + wait for clk_period/2; + clk <= '1'; + wait for clk_period/2; + end process; + + + -- Stimulus process + stim_proc: process + begin + -- hold reset state for 100 ns. + wait for 100 ns; + + wait for clk_period*10; + freq <= to_unsigned(1,17); + wait for clk_period*10; + freq <= to_unsigned(10,17); + wait for clk_period*10; + freq <= to_unsigned(100,17); + wait for clk_period*10; + freq <= to_unsigned(1000,17); + wait for clk_period*10; + freq <= to_unsigned(10000,17); + wait for clk_period*10; + freq <= to_unsigned(50000,17); + wait for clk_period*10; + freq <= to_unsigned(100000,17); + + -- insert stimulus here + + wait; + end process; + +END; diff --git a/helpers.vhd b/helpers.vhd new file mode 100644 index 0000000..b0e3105 --- /dev/null +++ b/helpers.vhd @@ -0,0 +1,46 @@ + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; + +package helpers is + --helper function to calculate the log2 (truncated) of a integer + function log2_int(n:natural) return natural; + function divide (a : UNSIGNED; b : UNSIGNED) return UNSIGNED; +end helpers; + + + +package body helpers is + function log2_int(n:natural) return natural is + begin + if(n>1) then --we can stil divide n by 2 + return 1+log2_int(n/2); --recursivly call log2_int for the by two divided number. + end if; + return 1; --since we can no longer divide n, return 1 + end log2_int; + + --Source: http://vhdlguru.blogspot.ch/2010/03/vhdl-function-for-division-two-signed.html + function divide (a : UNSIGNED; b : UNSIGNED) return UNSIGNED is + variable a1 : unsigned(a'length-1 downto 0):=a; + variable b1 : unsigned(b'length-1 downto 0):=b; + variable p1 : unsigned(b'length downto 0):= (others => '0'); + variable i : integer:=0; + + begin + for i in 0 to b'length-1 loop + p1(b'length-1 downto 1) := p1(b'length-2 downto 0); + p1(0) := a1(a'length-1); + a1(a'length-1 downto 1) := a1(a'length-2 downto 0); + p1 := p1-b1; + if(p1(b'length-1) ='1') then + a1(0) :='0'; + p1 := p1+b1; + else + a1(0) :='1'; + end if; + end loop; + return a1; + end divide; +end helpers; + diff --git a/yasg.gise b/yasg.gise index cfaaefd..9b04e0d 100644 --- a/yasg.gise +++ b/yasg.gise @@ -21,8 +21,141 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/yasg.xise b/yasg.xise index 514e35c..87f2d52 100644 --- a/yasg.xise +++ b/yasg.xise @@ -16,21 +16,38 @@ + + + + + + + + + + + + + + + - - - + + + + + @@ -39,6 +56,7 @@ + From 22ebbdf9b9608e2dfdc1b1f1a8bfc4c78d518314 Mon Sep 17 00:00:00 2001 From: T-moe Date: Mon, 16 May 2016 20:38:11 +0200 Subject: [PATCH 02/13] Implemented triangle, saw-tooth and square wave in dds.vhd. --- dds.vhd | 46 ++++++++++++++++++++++++++++++---------------- dds_tb.vhd | 40 +++++++++++++++++++++++----------------- yasg.gise | 14 ++++++-------- 3 files changed, 59 insertions(+), 41 deletions(-) diff --git a/dds.vhd b/dds.vhd index 77f1645..cba5adf 100644 --- a/dds.vhd +++ b/dds.vhd @@ -31,33 +31,47 @@ entity dds is Generic (clk_freq: natural:= 50000000; max_freq: natural := 100000; adc_res: natural:=12; - vector_res: natural :=8 ); + acc_res: natural:=32; + phase_res: natural:=15); Port ( clk : in STD_LOGIC; freq : in unsigned (log2_int(max_freq)-1 downto 0); form : in unsigned (1 downto 0); - amp : out unsigned (adc_res-1 downto 0); + amp : out signed (adc_res-1 downto 0); update : out STD_LOGIC); end dds; -architecture Behavioral of dds is - constant clk2 : natural := clk_freq/(2**vector_res); - constant clk2_us :unsigned (log2_int(clk2)-1 downto 0) :=to_unsigned(clk2,log2_int(clk2)); - signal prescale,cnt_prescale :unsigned (log2_int(clk2)-1 downto 0) := (others => '0'); - signal m, idx : unsigned(vector_res -1 downto 0):= (others => '0'); - +architecture Behavioral of dds is + signal m, idx : unsigned(acc_res -1 downto 0):= (others => '0'); + signal idx_phase : unsigned(phase_res-1 downto 0) := (others => '0'); + signal amp_rect, amp_saw, amp_tria, amp_sin : signed (adc_res-1 downto 0); + begin - prescale <= divide(to_unsigned(clk2,prescale'length),freq); - m <= resize(divide(freq*prescale,to_unsigned(clk2,prescale'length)),m'length); + -- m = f0*2^n/fc + m <= resize(divide(shift_left(resize(freq,64),acc_res),to_unsigned(clk_freq,64)),m'length); + idx_phase <= idx(acc_res -1 downto acc_res - phase_res); + + amp_rect <= to_signed((2**(adc_res-1)) - 1,adc_res) when idx_phase(phase_res-1)='0' else + to_signed(-(2**(adc_res-1)),adc_res); + amp_saw <= to_signed(-(2**(adc_res-1)),adc_res) + + signed(resize(unsigned(((2**adc_res) -1)*idx_phase/2**phase_res),adc_res)) ; + + amp_tria <= to_signed(-(2**(adc_res-1)),adc_res) + + signed(resize(unsigned(((2**adc_res) -1)*idx_phase/2**(phase_res-1)),adc_res)) + when idx_phase(phase_res-1)='0' else + resize(to_signed((2**(adc_res))-1,adc_res+1) + - signed(resize(unsigned(((2**adc_res) -1)*idx_phase/2**(phase_res-1)),adc_res)),adc_res); + + + + amp <= amp_tria; + + + P1: process(clk) begin if(rising_edge(clk)) then - if(cnt_prescale >= prescale) then - cnt_prescale <= to_unsigned(1, prescale'length); - idx <= (idx+m) mod (2**vector_res); - else - cnt_prescale <= cnt_prescale +1; - end if; + idx <= (idx+m); end if; end process P1; diff --git a/dds_tb.vhd b/dds_tb.vhd index c954bbf..31fed4e 100644 --- a/dds_tb.vhd +++ b/dds_tb.vhd @@ -41,7 +41,7 @@ ARCHITECTURE behavior OF dds_tb IS clk : IN std_logic; freq : IN unsigned(16 downto 0); form : IN unsigned(1 downto 0); - amp : OUT unsigned(11 downto 0); + amp : OUT signed(11 downto 0); update : OUT std_logic ); END COMPONENT; @@ -53,11 +53,11 @@ ARCHITECTURE behavior OF dds_tb IS signal form : unsigned(1 downto 0) := (others => '0'); --Outputs - signal amp : unsigned(11 downto 0); + signal amp : signed(11 downto 0); signal update : std_logic; -- Clock period definitions - constant clk_period : time := 10 ns; + constant clk_period : time := 20 ns; --50mhz BEGIN @@ -86,21 +86,27 @@ BEGIN -- hold reset state for 100 ns. wait for 100 ns; - wait for clk_period*10; - freq <= to_unsigned(1,17); - wait for clk_period*10; - freq <= to_unsigned(10,17); - wait for clk_period*10; - freq <= to_unsigned(100,17); - wait for clk_period*10; - freq <= to_unsigned(1000,17); - wait for clk_period*10; - freq <= to_unsigned(10000,17); - wait for clk_period*10; - freq <= to_unsigned(50000,17); - wait for clk_period*10; + freq <= to_unsigned(100000,17); - + wait for 2000 ms; + + freq <= to_unsigned(10,17); + wait for 200 ms; + + freq <= to_unsigned(100,17); + wait for 20 ms; + + freq <= to_unsigned(1000,17); + wait for 2 ms; + + freq <= to_unsigned(10000,17); + wait for 1 ms; + + freq <= to_unsigned(50000,17); + wait for 1 ms; + + freq <= to_unsigned(100000,17); + wait for 1 ms; -- insert stimulus here wait; diff --git a/yasg.gise b/yasg.gise index 9b04e0d..6799a8a 100644 --- a/yasg.gise +++ b/yasg.gise @@ -41,6 +41,7 @@ + @@ -59,9 +60,8 @@ - + - @@ -80,7 +80,7 @@ - + @@ -88,11 +88,9 @@ - + - - @@ -100,7 +98,7 @@ - + @@ -135,7 +133,7 @@ - + From d28518a13ea3ba14982d8c7dc755d970f0b0b88f Mon Sep 17 00:00:00 2001 From: T-moe Date: Tue, 17 May 2016 12:25:10 +0200 Subject: [PATCH 03/13] Finalized first version of dds. --- dds.vhd | 56 ++++++++++++++++++++++++++++++++---------------------- dds_tb.vhd | 51 +++++++++++++++++++++++++------------------------ yasg.gise | 15 +++++++++------ 3 files changed, 68 insertions(+), 54 deletions(-) diff --git a/dds.vhd b/dds.vhd index cba5adf..7cae0f1 100644 --- a/dds.vhd +++ b/dds.vhd @@ -20,11 +20,7 @@ library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; - --- Uncomment the following library declaration if instantiating --- any Xilinx primitives in this code. ---library UNISIM; ---use UNISIM.VComponents.all; +use IEEE.MATH_REAL.ALL; use work.helpers.all; entity dds is @@ -36,38 +32,52 @@ entity dds is Port ( clk : in STD_LOGIC; freq : in unsigned (log2_int(max_freq)-1 downto 0); form : in unsigned (1 downto 0); - amp : out signed (adc_res-1 downto 0); - update : out STD_LOGIC); + amp : out unsigned (adc_res-1 downto 0)); end dds; architecture Behavioral of dds is signal m, idx : unsigned(acc_res -1 downto 0):= (others => '0'); signal idx_phase : unsigned(phase_res-1 downto 0) := (others => '0'); - signal amp_rect, amp_saw, amp_tria, amp_sin : signed (adc_res-1 downto 0); + signal amp_rect, amp_saw, amp_tria, amp_sin : unsigned (adc_res-1 downto 0); + + type storage is array (((2**phase_res)/4)-1 downto 0) of unsigned (adc_res-2 downto 0); + function gen_sin_wave return storage is + variable temp : storage; + begin + forLoop: for i in 0 to temp'high loop + temp(i) := to_unsigned(integer(real((2**(adc_res-1))-1)*sin((real(i)*MATH_PI/2.0)/real(temp'high))),adc_res-1); + end loop; + return temp; + end function gen_sin_wave; + constant sin_wave : storage := gen_sin_wave; begin - -- m = f0*2^n/fc + + -- m = fout*(2^n)/fclk m <= resize(divide(shift_left(resize(freq,64),acc_res),to_unsigned(clk_freq,64)),m'length); idx_phase <= idx(acc_res -1 downto acc_res - phase_res); - amp_rect <= to_signed((2**(adc_res-1)) - 1,adc_res) when idx_phase(phase_res-1)='0' else - to_signed(-(2**(adc_res-1)),adc_res); + amp_rect <= to_unsigned(0,adc_res) when idx_phase(phase_res-1)='0' else + to_unsigned((2**adc_res)-1,adc_res); - amp_saw <= to_signed(-(2**(adc_res-1)),adc_res) - + signed(resize(unsigned(((2**adc_res) -1)*idx_phase/2**phase_res),adc_res)) ; + amp_saw <= resize(unsigned(((2**adc_res) -1)*idx_phase/2**phase_res),adc_res) ; - amp_tria <= to_signed(-(2**(adc_res-1)),adc_res) - + signed(resize(unsigned(((2**adc_res) -1)*idx_phase/2**(phase_res-1)),adc_res)) + amp_tria <= resize(unsigned(((2**adc_res) -1)*idx_phase/2**(phase_res-1)),adc_res) when idx_phase(phase_res-1)='0' else - resize(to_signed((2**(adc_res))-1,adc_res+1) - - signed(resize(unsigned(((2**adc_res) -1)*idx_phase/2**(phase_res-1)),adc_res)),adc_res); + resize(unsigned((2**(adc_res+1)) - ((2**adc_res) -1)*idx_phase/2**(phase_res-1)),adc_res); - - - amp <= amp_tria; - - - + -- Modulo is only required to prevent a synthesizer warning, but the value is actually never > 2**phase_res/4 + amp_sin <= to_unsigned((2**(adc_res-1)) - 1,adc_res) + sin_wave(to_integer(idx_phase) mod ((2**phase_res)/4)) when idx_phase(phase_res-1 downto phase_res-2)="00" else + to_unsigned((2**(adc_res-1)) - 1,adc_res) + sin_wave(to_integer(((2**phase_res)/2)-idx_phase) mod ((2**phase_res)/4)) when idx_phase(phase_res-1 downto phase_res-2)="01" else + to_unsigned((2**(adc_res-1)) - 1,adc_res) - sin_wave(to_integer(idx_phase-((2**phase_res)/2)) mod ((2**phase_res)/4)) when idx_phase(phase_res-1 downto phase_res-2)="10" else + to_unsigned((2**(adc_res-1)) - 1,adc_res) - sin_wave(to_integer(((2**phase_res)-1)-idx_phase) mod ((2**phase_res)/4)); + + with form select amp <= amp_rect when "00", + amp_saw when "01", + amp_tria when "10", + amp_sin when others; + + P1: process(clk) begin if(rising_edge(clk)) then diff --git a/dds_tb.vhd b/dds_tb.vhd index 31fed4e..73b1259 100644 --- a/dds_tb.vhd +++ b/dds_tb.vhd @@ -41,8 +41,7 @@ ARCHITECTURE behavior OF dds_tb IS clk : IN std_logic; freq : IN unsigned(16 downto 0); form : IN unsigned(1 downto 0); - amp : OUT signed(11 downto 0); - update : OUT std_logic + amp : OUT unsigned(11 downto 0) ); END COMPONENT; @@ -53,8 +52,7 @@ ARCHITECTURE behavior OF dds_tb IS signal form : unsigned(1 downto 0) := (others => '0'); --Outputs - signal amp : signed(11 downto 0); - signal update : std_logic; + signal amp : unsigned(11 downto 0); -- Clock period definitions constant clk_period : time := 20 ns; --50mhz @@ -66,8 +64,7 @@ BEGIN clk => clk, freq => freq, form => form, - amp => amp, - update => update + amp => amp ); -- Clock process definitions @@ -87,27 +84,31 @@ BEGIN wait for 100 ns; - freq <= to_unsigned(100000,17); - wait for 2000 ms; - - freq <= to_unsigned(10,17); - wait for 200 ms; - - freq <= to_unsigned(100,17); - wait for 20 ms; - - freq <= to_unsigned(1000,17); - wait for 2 ms; - - freq <= to_unsigned(10000,17); - wait for 1 ms; - + + form <= "00"; freq <= to_unsigned(50000,17); - wait for 1 ms; - + wait for 40 us; freq <= to_unsigned(100000,17); - wait for 1 ms; - -- insert stimulus here + wait for 20 us; + + form <= "01"; + freq <= to_unsigned(50000,17); + wait for 40 us; + freq <= to_unsigned(100000,17); + wait for 20 us; + + form <= "10"; + freq <= to_unsigned(50000,17); + wait for 40 us; + freq <= to_unsigned(100000,17); + wait for 20 us; + + form <= "11"; + freq <= to_unsigned(50000,17); + wait for 40 us; + freq <= to_unsigned(100000,17); + wait for 20 us; + wait; end process; diff --git a/yasg.gise b/yasg.gise index 6799a8a..b11f790 100644 --- a/yasg.gise +++ b/yasg.gise @@ -60,7 +60,7 @@ - + @@ -80,7 +80,7 @@ - + @@ -88,9 +88,11 @@ - + + + @@ -98,9 +100,11 @@ - + + + @@ -133,9 +137,8 @@ - + - From b0f5d5fbca1012e6e65badd3063b0726f9f1f1ae Mon Sep 17 00:00:00 2001 From: T-moe Date: Tue, 17 May 2016 15:57:43 +0200 Subject: [PATCH 04/13] Added SPI driver. --- spi_driver.vhd | 85 +++++++++++++++++++++++++++++++++ spi_driver_tb.vhd | 118 ++++++++++++++++++++++++++++++++++++++++++++++ yasg.gise | 76 ++++++++++++++++------------- yasg.xise | 33 ++++++++----- 4 files changed, 269 insertions(+), 43 deletions(-) create mode 100644 spi_driver.vhd create mode 100644 spi_driver_tb.vhd diff --git a/spi_driver.vhd b/spi_driver.vhd new file mode 100644 index 0000000..3a6f817 --- /dev/null +++ b/spi_driver.vhd @@ -0,0 +1,85 @@ +---------------------------------------------------------------------------------- +-- Company: +-- Engineer: +-- +-- Create Date: 12:51:31 05/17/2016 +-- Design Name: +-- Module Name: spi_driver - Behavioral +-- Project Name: +-- Target Devices: +-- Tool versions: +-- Description: +-- +-- Dependencies: +-- +-- Revision: +-- Revision 0.01 - File Created +-- Additional Comments: +-- +---------------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; + +-- Uncomment the following library declaration if instantiating +-- any Xilinx primitives in this code. +--library UNISIM; +--use UNISIM.VComponents.all; + +entity spi_driver is + Generic (clk_freq: natural:= 50000000; + adc_res: natural:=12); + Port ( clk : in STD_LOGIC; + rst: in STD_LOGIC; + val : in unsigned (adc_res-1 downto 0); + sck : out STD_LOGIC; + cs : out STD_LOGIC; + mosi : out STD_LOGIC); +end spi_driver; + +architecture Behavioral of spi_driver is + type states is(S_IDLE, S_WORK); + signal state_reg, state_next: states := S_IDLE; + signal counter, counter_next: unsigned(5 downto 0) := (others => '0'); + signal data: unsigned(23 downto 0); +begin + REGS: process (clk, rst) is + begin -- process start + if rst = '1' then -- asynchronous reset (active high) + state_reg <= S_IDLE; + counter <= to_unsigned(0,counter'length); + elsif rising_edge(clk) then -- rising clock edge + state_reg <= state_next; + counter <= counter_next; + end if; + end process REGS; + + data(23 downto 20) <= "0011"; --Command: Write to and Update (Power Up) + data(19 downto 16) <= "0000"; --Adress: DAC0 + data(15 downto 4) <= val; -- DAC Value (12bit) + data(3 downto 0) <= "0000"; -- 4x don't care + + mosi <= data(23 - to_integer(counter srl 1)) when state_reg=S_WORK else '0'; + sck <= '1' when state_reg=S_WORK and counter(0)='1' else '0'; + cs <= '1' when state_reg =S_IDLE else '0'; + + NSL: process (state_reg, counter) is + begin + state_next <= state_reg; + counter_next <= counter; + case state_reg is -- switch on current state + when S_IDLE => -- currently in idle state + state_next <= S_WORK; + counter_next <= to_unsigned(0,counter'length); + when S_WORK => -- currently in work state + if(counter = 24*2 -1) then + state_next <= S_IDLE; + else + counter_next<= counter + 1; + end if; + when others => null; -- do nothing, if we are in a different state + end case; + end process NSL; + +end Behavioral; + diff --git a/spi_driver_tb.vhd b/spi_driver_tb.vhd new file mode 100644 index 0000000..a8c72b3 --- /dev/null +++ b/spi_driver_tb.vhd @@ -0,0 +1,118 @@ +-------------------------------------------------------------------------------- +-- Company: +-- Engineer: +-- +-- Create Date: 15:38:41 05/17/2016 +-- Design Name: +-- Module Name: /home/timo/vhdl-yasg/spi_driver_tb.vhd +-- Project Name: yasg +-- Target Device: +-- Tool versions: +-- Description: +-- +-- VHDL Test Bench Created by ISE for module: spi_driver +-- +-- Dependencies: +-- +-- Revision: +-- Revision 0.01 - File Created +-- Additional Comments: +-- +-- Notes: +-- This testbench has been automatically generated using types std_logic and +-- std_logic_vector for the ports of the unit under test. Xilinx recommends +-- that these types always be used for the top-level I/O of a design in order +-- to guarantee that the testbench will bind correctly to the post-implementation +-- simulation model. +-------------------------------------------------------------------------------- +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; + +-- Uncomment the following library declaration if using +-- arithmetic functions with Signed or Unsigned values +USE ieee.numeric_std.ALL; + +ENTITY spi_driver_tb IS +END spi_driver_tb; + +ARCHITECTURE behavior OF spi_driver_tb IS + + -- Component Declaration for the Unit Under Test (UUT) + + COMPONENT spi_driver + PORT( + clk : IN std_logic; + rst : IN std_logic; + val : IN unsigned(11 downto 0); + sck : OUT std_logic; + cs : OUT std_logic; + mosi : OUT std_logic + ); + END COMPONENT; + + + --Inputs + signal clk : std_logic := '0'; + signal rst : std_logic := '0'; + signal val : unsigned(11 downto 0) := (others => '0'); + + --Outputs + signal sck : std_logic; + signal cs : std_logic; + signal mosi : std_logic; + + -- Clock period definitions + constant clk_period : time := 20 ns; --50mhz + +BEGIN + + -- Instantiate the Unit Under Test (UUT) + uut: spi_driver PORT MAP ( + clk => clk, + rst => rst, + val => val, + sck => sck, + cs => cs, + mosi => mosi + ); + + -- Clock process definitions + clk_process :process + begin + clk <= '0'; + wait for clk_period/2; + clk <= '1'; + wait for clk_period/2; + end process; + + + -- Stimulus process + stim_proc: process + begin + -- hold reset state for 100 ns. + rst <= '1'; + wait for 100 ns; + rst <= '0'; + wait for clk_period*10; + + val <= to_unsigned(0,12); + wait for clk_period*64; + + val <= to_unsigned(7,12); + wait for clk_period*64; + + val <= to_unsigned(31,12); + wait for clk_period*64; + + val <= to_unsigned(128,12); + wait for clk_period*64; + + val <= to_unsigned(512,12); + wait for clk_period*64; + + -- insert stimulus here + + wait; + end process; + +END; diff --git a/yasg.gise b/yasg.gise index b11f790..20c0240 100644 --- a/yasg.gise +++ b/yasg.gise @@ -37,19 +37,30 @@ - - - + + + + + + + + + + + + + + @@ -60,100 +71,101 @@ - + + + - + - + - + - + + + - + - - - + + - + - - + - + - + - + - + - + - + - + - - - - - - - - - - + + + + + + + + + diff --git a/yasg.xise b/yasg.xise index 87f2d52..fff95c7 100644 --- a/yasg.xise +++ b/yasg.xise @@ -20,19 +20,29 @@ - - + + - - + + - + + + + + + + + + + + @@ -40,23 +50,24 @@ - - - + + + - - + + + - + From 71b8cdb490f26e9b3c970f6b36b20f3ada815f27 Mon Sep 17 00:00:00 2001 From: T-moe Date: Fri, 20 May 2016 13:53:24 +0200 Subject: [PATCH 05/13] Added some screenshots --- .gitignore | 1 + screenshots/V9-Nr2.png | Bin 0 -> 26749 bytes screenshots/V9-Nr3.png | Bin 0 -> 26461 bytes screenshots/V9-Nr4.png | Bin 0 -> 29270 bytes 4 files changed, 1 insertion(+) create mode 100755 screenshots/V9-Nr2.png create mode 100755 screenshots/V9-Nr3.png create mode 100755 screenshots/V9-Nr4.png diff --git a/.gitignore b/.gitignore index 72e9bfc..857ec81 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ !*.wcfg !*/ !documentation/* +!screenshots/* diff --git a/screenshots/V9-Nr2.png b/screenshots/V9-Nr2.png new file mode 100755 index 0000000000000000000000000000000000000000..3775dec307e91a98e029ddd60852582d016af15a GIT binary patch literal 26749 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 literal 0 HcmV?d00001 diff --git a/screenshots/V9-Nr3.png b/screenshots/V9-Nr3.png new file mode 100755 index 0000000000000000000000000000000000000000..6c9d047dead1fe99f6df1601aeef82cac66fc9cd GIT binary patch literal 26461 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 JzTUBV{(l Date: Fri, 20 May 2016 13:53:56 +0200 Subject: [PATCH 06/13] Added toplevel schema. DDS works at 1khz. Measured with oscilloscope --- dds.sym | 16 ++- dds.vhd | 2 +- io.ucf | 19 ++++ spi_driver.sym | 28 +++++ toplevel.jhd | 5 + toplevel.sch | 299 +++++++++++++++++++++++++++++++++++++++++++++++++ yasg.gise | 206 ++++++++++++++++++++++++++++++---- yasg.xise | 27 +++-- 8 files changed, 560 insertions(+), 42 deletions(-) create mode 100644 io.ucf create mode 100644 spi_driver.sym create mode 100644 toplevel.jhd create mode 100644 toplevel.sch diff --git a/dds.sym b/dds.sym index 09f9a87..e0064ee 100644 --- a/dds.sym +++ b/dds.sym @@ -1,26 +1,24 @@ BLOCK - 2016-5-16T9:25:36 + 2016-5-20T8:58:58 - + - - + - + + - + + - - - diff --git a/dds.vhd b/dds.vhd index 7cae0f1..ec2b843 100644 --- a/dds.vhd +++ b/dds.vhd @@ -30,7 +30,7 @@ entity dds is acc_res: natural:=32; phase_res: natural:=15); Port ( clk : in STD_LOGIC; - freq : in unsigned (log2_int(max_freq)-1 downto 0); + freq : in unsigned (16 downto 0); --log2_int(max_freq)-1 form : in unsigned (1 downto 0); amp : out unsigned (adc_res-1 downto 0)); end dds; diff --git a/io.ucf b/io.ucf new file mode 100644 index 0000000..5865944 --- /dev/null +++ b/io.ucf @@ -0,0 +1,19 @@ +NET "CLK_50MHZ" LOC = "E12"| IOSTANDARD = LVCMOS33 ; +NET "CLK_50MHZ" PERIOD = 20.0ns HIGH 40%; + + +NET "SPI_MOSI" LOC = "AB14" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ; +NET "SPI_SCK" LOC = "AA20" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ; +NET "DAC_CS" LOC = "W7" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ; +NET "DAC_CLR" LOC = "AB13" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ; +#NET "DAC_OUT" LOC = "V7" | IOSTANDARD = LVCMOS33 + + +NET "J18_IO1" LOC = "AA21" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ; +NET "J18_IO2" LOC = "AB21" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ; +NET "J18_IO3" LOC = "AA19" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ; +NET "J18_IO4" LOC = "AB19" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ; + +NET "LED0" LOC = "R20" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ; +NET "SW0" LOC = "V8" | IOSTANDARD = LVCMOS33 ; +NET "SW1" LOC = "U10"| IOSTANDARD = LVCMOS33 ; \ No newline at end of file diff --git a/spi_driver.sym b/spi_driver.sym new file mode 100644 index 0000000..9bd3cd8 --- /dev/null +++ b/spi_driver.sym @@ -0,0 +1,28 @@ + + + BLOCK + 2016-5-20T8:33:2 + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/toplevel.jhd b/toplevel.jhd new file mode 100644 index 0000000..5880a97 --- /dev/null +++ b/toplevel.jhd @@ -0,0 +1,5 @@ +MODULE toplevel + SUBMODULE spi_driver + INSTANCE XLXI_1 + SUBMODULE dds + INSTANCE XLXI_2 diff --git a/toplevel.sch b/toplevel.sch new file mode 100644 index 0000000..cdb795b --- /dev/null +++ b/toplevel.sch @@ -0,0 +1,299 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2016-5-20T8:33:2 + + + + + + + + + + + 2016-5-20T8:58:58 + + + + + + + + + + + 2006-1-1T10:10:10 + + + + + 2000-1-1T10:10:10 + + + + + + + + + 2000-1-1T10:10:10 + + + + + + + + 2000-1-1T10:10:10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/yasg.gise b/yasg.gise index 20c0240..64b62a6 100644 --- a/yasg.gise +++ b/yasg.gise @@ -23,19 +23,40 @@ + + + + + + + + + + + + + + + + + + + + + @@ -44,6 +65,7 @@ + @@ -52,17 +74,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -74,6 +142,10 @@ + + + + @@ -81,21 +153,30 @@ - + - + + + + + + + + + + @@ -103,72 +184,151 @@ - + + + + + + - + + + + - + - + + + + + + - + - + - + - + - - - - - + - - + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/yasg.xise b/yasg.xise index fff95c7..d2d0d17 100644 --- a/yasg.xise +++ b/yasg.xise @@ -21,11 +21,11 @@ - + - + @@ -35,7 +35,7 @@ - + @@ -43,6 +43,13 @@ + + + + + + + @@ -50,14 +57,14 @@ - - - + + + - - + + @@ -76,7 +83,9 @@ - + + + From bc78a4070832a1964b79579fa7eb2a7ba53f710e Mon Sep 17 00:00:00 2001 From: T-moe Date: Mon, 23 May 2016 19:22:33 +0200 Subject: [PATCH 07/13] Added rotary decoder and simple controller --- controller.sym | 28 +++++ controller.vhd | 70 +++++++++++ dds.vhd | 2 +- io.ucf | 5 +- rotary.vhd | 65 +++++++++++ rotary_dec.sym | 27 +++++ toplevel.jhd | 4 + toplevel.sch | 306 ++++++++++++++++++++++++++++--------------------- yasg.gise | 33 ++++-- yasg.xise | 12 +- 10 files changed, 409 insertions(+), 143 deletions(-) create mode 100644 controller.sym create mode 100644 controller.vhd create mode 100644 rotary.vhd create mode 100644 rotary_dec.sym diff --git a/controller.sym b/controller.sym new file mode 100644 index 0000000..edf28fc --- /dev/null +++ b/controller.sym @@ -0,0 +1,28 @@ + + + BLOCK + 2016-5-23T16:56:10 + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/controller.vhd b/controller.vhd new file mode 100644 index 0000000..437f611 --- /dev/null +++ b/controller.vhd @@ -0,0 +1,70 @@ +---------------------------------------------------------------------------------- +-- Company: +-- Engineer: +-- +-- Create Date: 18:47:36 05/23/2016 +-- Design Name: +-- Module Name: controller - Behavioral +-- Project Name: +-- Target Devices: +-- Tool versions: +-- Description: +-- +-- Dependencies: +-- +-- Revision: +-- Revision 0.01 - File Created +-- Additional Comments: +-- +---------------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; + +-- Uncomment the following library declaration if using +-- arithmetic functions with Signed or Unsigned values +use IEEE.NUMERIC_STD.ALL; + +-- Uncomment the following library declaration if instantiating +-- any Xilinx primitives in this code. +--library UNISIM; +--use UNISIM.VComponents.all; + +entity controller is + Port ( clk : in STD_LOGIC; + rst: in STD_LOGIC; + enc_updown : in STD_LOGIC; + enc_ce : in STD_LOGIC; + enc_err : in STD_LOGIC; + freq_out : out unsigned (16 downto 0)); +end controller; + +architecture Behavioral of controller is + signal freq_reg, freq_next : unsigned(16 downto 0) := to_unsigned(1000,17); +begin + + proc1: process(clk,rst) + begin + if(rst='1') then + freq_reg <= to_unsigned(1000,17); + elsif(rising_edge(clk)) then + freq_reg <= freq_next; + end if; + end process proc1; + + freq_out <= freq_reg; + + proc2: process(freq_reg,enc_updown,enc_ce,enc_err) + begin + freq_next <= freq_reg; + if(enc_ce='1' and enc_err='0') then + if(enc_updown='1') then + freq_next <= freq_reg + 1; + else + freq_next <= freq_reg - 1; + end if; + end if; + + end process proc2; + +end Behavioral; + diff --git a/dds.vhd b/dds.vhd index ec2b843..95b8798 100644 --- a/dds.vhd +++ b/dds.vhd @@ -55,7 +55,7 @@ begin -- m = fout*(2^n)/fclk m <= resize(divide(shift_left(resize(freq,64),acc_res),to_unsigned(clk_freq,64)),m'length); - idx_phase <= idx(acc_res -1 downto acc_res - phase_res); + idx_phase <= idx(acc_res -1 downto acc_res - phase_res); amp_rect <= to_unsigned(0,adc_res) when idx_phase(phase_res-1)='0' else to_unsigned((2**adc_res)-1,adc_res); diff --git a/io.ucf b/io.ucf index 5865944..24d0206 100644 --- a/io.ucf +++ b/io.ucf @@ -16,4 +16,7 @@ NET "J18_IO4" LOC = "AB19" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 NET "LED0" LOC = "R20" | IOSTANDARD = LVCMOS33 | SLEW = SLOW | DRIVE = 8 ; NET "SW0" LOC = "V8" | IOSTANDARD = LVCMOS33 ; -NET "SW1" LOC = "U10"| IOSTANDARD = LVCMOS33 ; \ No newline at end of file +NET "SW1" LOC = "U10"| IOSTANDARD = LVCMOS33 ; + +NET "ROT_A" LOC = "T13" | IOSTANDARD = LVCMOS33 | PULLUP; +NET "ROT_B" LOC = "R14" | IOSTANDARD = LVCMOS33 | PULLUP; \ No newline at end of file diff --git a/rotary.vhd b/rotary.vhd new file mode 100644 index 0000000..ca11399 --- /dev/null +++ b/rotary.vhd @@ -0,0 +1,65 @@ +----------------------------------------------------------------------------- +-- +-- Decoder für Drehgeber +-- +----------------------------------------------------------------------------- + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; + +entity rotary_dec is + Port ( clk : in std_logic; -- Systemtakt + A : in std_logic; -- Spur A + B : in std_logic; -- Spur B + up_down : out std_logic; -- Zaehlrichtung + ce : out std_logic; -- Clock Enable + error : out std_logic); -- illegaler Signalübergang +end rotary_dec; + +architecture Behavioral of rotary_dec is + +signal a_in, b_in, a_old, b_old: std_logic; + +begin + +-- Abtastung und Verzoegerung der Quadratursignale + +process(clk) +begin + if rising_edge(clk) then + a_old <= a_in; + a_in <= A; + b_old <= b_in; + b_in <= B; + end if; +end process; + +-- Dekodierung der Ausgaenge + +process(a_in, b_in, a_old, b_old) +variable state: std_logic_vector(3 downto 0); +begin + state := a_in & b_in & a_old & b_old; + case state is + when "0000" => up_down <= '0'; ce <= '0'; error <= '0'; + when "0001" => up_down <= '1'; ce <= '1'; error <= '0'; + when "0010" => up_down <= '0'; ce <= '1'; error <= '0'; + when "0011" => up_down <= '0'; ce <= '0'; error <= '1'; + when "0100" => up_down <= '0'; ce <= '1'; error <= '0'; + when "0101" => up_down <= '0'; ce <= '0'; error <= '0'; + when "0110" => up_down <= '0'; ce <= '0'; error <= '1'; + when "0111" => up_down <= '1'; ce <= '1'; error <= '0'; + when "1000" => up_down <= '1'; ce <= '1'; error <= '0'; + when "1001" => up_down <= '0'; ce <= '0'; error <= '1'; + when "1010" => up_down <= '0'; ce <= '0'; error <= '0'; + when "1011" => up_down <= '0'; ce <= '1'; error <= '0'; + when "1100" => up_down <= '0'; ce <= '0'; error <= '1'; + when "1101" => up_down <= '0'; ce <= '1'; error <= '0'; + when "1110" => up_down <= '1'; ce <= '1'; error <= '0'; + when "1111" => up_down <= '0'; ce <= '0'; error <= '0'; + when others => null; + end case; +end process; + +end Behavioral; + diff --git a/rotary_dec.sym b/rotary_dec.sym new file mode 100644 index 0000000..f48b8dc --- /dev/null +++ b/rotary_dec.sym @@ -0,0 +1,27 @@ + + + BLOCK + 2016-5-23T16:56:27 + + + + + + + + + + + + + + + + + + + + + + + diff --git a/toplevel.jhd b/toplevel.jhd index 5880a97..d1c361a 100644 --- a/toplevel.jhd +++ b/toplevel.jhd @@ -3,3 +3,7 @@ MODULE toplevel INSTANCE XLXI_1 SUBMODULE dds INSTANCE XLXI_2 + SUBMODULE controller + INSTANCE XLXI_42 + SUBMODULE rotary_dec + INSTANCE XLXI_43 diff --git a/toplevel.sch b/toplevel.sch index cdb795b..c2f21e0 100644 --- a/toplevel.sch +++ b/toplevel.sch @@ -6,11 +6,10 @@ + - - - - + + @@ -18,7 +17,6 @@ - @@ -28,8 +26,12 @@ - - + + + + + + @@ -42,6 +44,8 @@ + + 2016-5-20T8:33:2 @@ -64,11 +68,6 @@ - - 2006-1-1T10:10:10 - - - 2000-1-1T10:10:10 @@ -92,6 +91,33 @@ + + 2016-5-23T16:56:10 + + + + + + + + + + + 2016-5-23T16:56:27 + + + + + + + + + + + + + + @@ -100,26 +126,9 @@ - - - - - - - - - - - - - - - - - @@ -136,13 +145,13 @@ - - - + + + @@ -155,145 +164,186 @@ + + + + + + + + + + + + + + + + + + + - - + + - + - - - - + + + + - - + + - - - + + + - - - - + + + + - + - - - - + + + - + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + + + - - - - - - - - - - - - + - + - - - - + + - + - - + - - - - - + + + + - + - + - - - - + - + - + - - + - + - - - + + - - - - + + + + - + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/yasg.gise b/yasg.gise index 64b62a6..51e396f 100644 --- a/yasg.gise +++ b/yasg.gise @@ -30,6 +30,11 @@ + + + + + @@ -69,6 +74,11 @@ + + + + + @@ -144,6 +154,7 @@ + @@ -215,7 +226,7 @@ - + @@ -240,7 +251,7 @@ - + @@ -261,11 +272,11 @@ - + - + @@ -274,7 +285,7 @@ - + @@ -290,8 +301,9 @@ - + + @@ -304,7 +316,7 @@ - + @@ -316,13 +328,12 @@ - + + - - - + diff --git a/yasg.xise b/yasg.xise index d2d0d17..b50633d 100644 --- a/yasg.xise +++ b/yasg.xise @@ -21,7 +21,7 @@ - + @@ -45,11 +45,19 @@ - + + + + + + + + + From 58120b0a8535dd760c609f78abebb8bb667c115c Mon Sep 17 00:00:00 2001 From: T-moe Date: Tue, 24 May 2016 11:32:48 +0200 Subject: [PATCH 08/13] Simplified SPI driver. Uses no multiplexer now, but a d-ff. --- spi_driver.vhd | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/spi_driver.vhd b/spi_driver.vhd index 3a6f817..582de95 100644 --- a/spi_driver.vhd +++ b/spi_driver.vhd @@ -40,42 +40,49 @@ end spi_driver; architecture Behavioral of spi_driver is type states is(S_IDLE, S_WORK); signal state_reg, state_next: states := S_IDLE; - signal counter, counter_next: unsigned(5 downto 0) := (others => '0'); - signal data: unsigned(23 downto 0); + signal counter_reg, counter_next: unsigned(5 downto 0) := (others => '0'); + signal shift_reg, shift_next: unsigned(19 downto 0):= (others => '0'); begin REGS: process (clk, rst) is begin -- process start if rst = '1' then -- asynchronous reset (active high) state_reg <= S_IDLE; - counter <= to_unsigned(0,counter'length); + counter_reg <= to_unsigned(0,counter_reg'length); + shift_reg <= to_unsigned(0,shift_reg'length); elsif rising_edge(clk) then -- rising clock edge state_reg <= state_next; - counter <= counter_next; + counter_reg <= counter_next; + shift_reg <= shift_next; end if; end process REGS; - data(23 downto 20) <= "0011"; --Command: Write to and Update (Power Up) - data(19 downto 16) <= "0000"; --Adress: DAC0 - data(15 downto 4) <= val; -- DAC Value (12bit) - data(3 downto 0) <= "0000"; -- 4x don't care - - mosi <= data(23 - to_integer(counter srl 1)) when state_reg=S_WORK else '0'; - sck <= '1' when state_reg=S_WORK and counter(0)='1' else '0'; + mosi <= shift_reg(shift_reg'high) when state_reg=S_WORK else '0'; + sck <= '1' when state_reg=S_WORK and counter_reg(0)='1' else '0'; cs <= '1' when state_reg =S_IDLE else '0'; - NSL: process (state_reg, counter) is + NSL: process (state_reg, counter_reg, shift_reg, val) is begin state_next <= state_reg; - counter_next <= counter; + counter_next <= counter_reg; + shift_next <= shift_reg; case state_reg is -- switch on current state when S_IDLE => -- currently in idle state state_next <= S_WORK; - counter_next <= to_unsigned(0,counter'length); + counter_next <= to_unsigned(0,counter_reg'length); + + shift_next(19 downto 16) <= "0011"; --Command: Write to and Update (Power Up) + shift_next(15 downto 12) <= "0000"; --Adress: DAC0 + shift_next(11 downto 0) <= val; -- DAC Value (12bit) + --shift_next(0 downto -3) <= "XXXX"; -- 4x don't care + when S_WORK => -- currently in work state - if(counter = 24*2 -1) then + if(counter_reg = 24*2 -1) then state_next <= S_IDLE; else - counter_next<= counter + 1; + counter_next<= counter_reg + 1; + end if; + if(counter_reg(0)='1') then + shift_next <= shift_left(shift_reg,1); end if; when others => null; -- do nothing, if we are in a different state end case; From 57de5f7af713a86bb1dd0d46051770675baac6c6 Mon Sep 17 00:00:00 2001 From: T-moe Date: Tue, 24 May 2016 15:57:02 +0200 Subject: [PATCH 09/13] Removed divider from dds --- dds.vhd | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/dds.vhd b/dds.vhd index 95b8798..80054f2 100644 --- a/dds.vhd +++ b/dds.vhd @@ -25,12 +25,12 @@ use work.helpers.all; entity dds is Generic (clk_freq: natural:= 50000000; - max_freq: natural := 100000; - adc_res: natural:=12; - acc_res: natural:=32; - phase_res: natural:=15); + freq_res: natural:=17; -- width of frequency input (log2(max_freq)) + adc_res: natural:=12; -- width of the ouput signal (=adc resolution) + acc_res: natural:=32; -- width of the phase accumulator + phase_res: natural:=15); -- effective phase resolution for lookup tables Port ( clk : in STD_LOGIC; - freq : in unsigned (16 downto 0); --log2_int(max_freq)-1 + freq : in unsigned (freq_res-1 downto 0); form : in unsigned (1 downto 0); amp : out unsigned (adc_res-1 downto 0)); end dds; @@ -53,8 +53,12 @@ architecture Behavioral of dds is begin - -- m = fout*(2^n)/fclk - m <= resize(divide(shift_left(resize(freq,64),acc_res),to_unsigned(clk_freq,64)),m'length); + -- m = fout*(2^n)/fclk = fout*((2^n)*(2^k)/fclk)/(2^k) with k=ceil(log2(fclk)), n=acc_res + m <= resize( (resize(freq,64) + * + (shift_left(to_unsigned(1,64),acc_res + log2_int(clk_freq)) / clk_freq)) + /to_unsigned(2**log2_int(clk_freq),64),acc_res); + idx_phase <= idx(acc_res -1 downto acc_res - phase_res); amp_rect <= to_unsigned(0,adc_res) when idx_phase(phase_res-1)='0' else From 2c14209bb14b0c445f844a52affddb2d9e59f0a9 Mon Sep 17 00:00:00 2001 From: T-moe Date: Mon, 30 May 2016 20:24:44 +0200 Subject: [PATCH 10/13] Simplified dds. --- dds.vhd | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/dds.vhd b/dds.vhd index 80054f2..9224d52 100644 --- a/dds.vhd +++ b/dds.vhd @@ -59,22 +59,26 @@ begin (shift_left(to_unsigned(1,64),acc_res + log2_int(clk_freq)) / clk_freq)) /to_unsigned(2**log2_int(clk_freq),64),acc_res); - idx_phase <= idx(acc_res -1 downto acc_res - phase_res); - - amp_rect <= to_unsigned(0,adc_res) when idx_phase(phase_res-1)='0' else + + amp_rect <= to_unsigned(0,adc_res) when idx(acc_res-1)='0' else to_unsigned((2**adc_res)-1,adc_res); - amp_saw <= resize(unsigned(((2**adc_res) -1)*idx_phase/2**phase_res),adc_res) ; - - amp_tria <= resize(unsigned(((2**adc_res) -1)*idx_phase/2**(phase_res-1)),adc_res) - when idx_phase(phase_res-1)='0' else - resize(unsigned((2**(adc_res+1)) - ((2**adc_res) -1)*idx_phase/2**(phase_res-1)),adc_res); - + amp_saw <= idx(acc_res -1 downto acc_res - adc_res); + + + amp_tria <= idx(acc_res -2 downto acc_res - adc_res) & "0" + when idx(acc_res-1)='0' else + ((2**adc_res)-1)- (idx(acc_res -2 downto acc_res - adc_res) & "0"); + + + + --idx_phase <= idx(acc_res -1 downto acc_res - phase_res); + -- Modulo is only required to prevent a synthesizer warning, but the value is actually never > 2**phase_res/4 - amp_sin <= to_unsigned((2**(adc_res-1)) - 1,adc_res) + sin_wave(to_integer(idx_phase) mod ((2**phase_res)/4)) when idx_phase(phase_res-1 downto phase_res-2)="00" else - to_unsigned((2**(adc_res-1)) - 1,adc_res) + sin_wave(to_integer(((2**phase_res)/2)-idx_phase) mod ((2**phase_res)/4)) when idx_phase(phase_res-1 downto phase_res-2)="01" else - to_unsigned((2**(adc_res-1)) - 1,adc_res) - sin_wave(to_integer(idx_phase-((2**phase_res)/2)) mod ((2**phase_res)/4)) when idx_phase(phase_res-1 downto phase_res-2)="10" else - to_unsigned((2**(adc_res-1)) - 1,adc_res) - sin_wave(to_integer(((2**phase_res)-1)-idx_phase) mod ((2**phase_res)/4)); + --amp_sin <= to_unsigned((2**(adc_res-1)) - 1,adc_res) + sin_wave(to_integer(idx_phase) mod ((2**phase_res)/4)) when idx_phase(phase_res-1 downto phase_res-2)="00" else + -- to_unsigned((2**(adc_res-1)) - 1,adc_res) + sin_wave(to_integer(((2**phase_res)/2)-idx_phase) mod ((2**phase_res)/4)) when idx_phase(phase_res-1 downto phase_res-2)="01" else + -- to_unsigned((2**(adc_res-1)) - 1,adc_res) - sin_wave(to_integer(idx_phase-((2**phase_res)/2)) mod ((2**phase_res)/4)) when idx_phase(phase_res-1 downto phase_res-2)="10" else + -- to_unsigned((2**(adc_res-1)) - 1,adc_res) - sin_wave(to_integer(((2**phase_res)-1)-idx_phase) mod ((2**phase_res)/4)); with form select amp <= amp_rect when "00", amp_saw when "01", From f31bc7a855c8dab8b3a1dca8ce0bb97653b41b71 Mon Sep 17 00:00:00 2001 From: T-moe Date: Mon, 30 May 2016 21:15:03 +0200 Subject: [PATCH 11/13] Changed dds to store the whole sin wave in lookup table. works now. --- dds.vhd | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/dds.vhd b/dds.vhd index 9224d52..2c2c61b 100644 --- a/dds.vhd +++ b/dds.vhd @@ -28,7 +28,7 @@ entity dds is freq_res: natural:=17; -- width of frequency input (log2(max_freq)) adc_res: natural:=12; -- width of the ouput signal (=adc resolution) acc_res: natural:=32; -- width of the phase accumulator - phase_res: natural:=15); -- effective phase resolution for lookup tables + phase_res: natural:=10); -- effective phase resolution for sin lookup table Port ( clk : in STD_LOGIC; freq : in unsigned (freq_res-1 downto 0); form : in unsigned (1 downto 0); @@ -40,13 +40,16 @@ architecture Behavioral of dds is signal idx_phase : unsigned(phase_res-1 downto 0) := (others => '0'); signal amp_rect, amp_saw, amp_tria, amp_sin : unsigned (adc_res-1 downto 0); - type storage is array (((2**phase_res)/4)-1 downto 0) of unsigned (adc_res-2 downto 0); + --type storage is array (((2**phase_res)/4)-1 downto 0) of unsigned (adc_res-2 downto 0); + type storage is array (((2**phase_res))-1 downto 0) of unsigned (adc_res-1 downto 0); function gen_sin_wave return storage is variable temp : storage; begin forLoop: for i in 0 to temp'high loop - temp(i) := to_unsigned(integer(real((2**(adc_res-1))-1)*sin((real(i)*MATH_PI/2.0)/real(temp'high))),adc_res-1); - end loop; + --temp(i) := to_unsigned(integer(real((2**(adc_res-1))-1)*sin((real(i)*MATH_PI/2.0)/real(temp'high))),adc_res-1); + temp(i) := to_unsigned(integer(real(2**(adc_res-1) -1) + real((2**(adc_res-1))-1)*sin((real(i)*MATH_PI*2.0)/real(temp'high))),adc_res); + + end loop; return temp; end function gen_sin_wave; constant sin_wave : storage := gen_sin_wave; @@ -72,7 +75,8 @@ begin - --idx_phase <= idx(acc_res -1 downto acc_res - phase_res); + idx_phase <= idx(acc_res -1 downto acc_res - phase_res); + amp_sin <= sin_wave(to_integer(idx_phase)); -- Modulo is only required to prevent a synthesizer warning, but the value is actually never > 2**phase_res/4 --amp_sin <= to_unsigned((2**(adc_res-1)) - 1,adc_res) + sin_wave(to_integer(idx_phase) mod ((2**phase_res)/4)) when idx_phase(phase_res-1 downto phase_res-2)="00" else From 17fa0fb90fc2b0b993eccb25c5f199193c917003 Mon Sep 17 00:00:00 2001 From: T-moe Date: Fri, 3 Jun 2016 14:04:43 +0200 Subject: [PATCH 12/13] Simplified dds to store only 1/4 of a sin wave in storage. works now. --- dds.vhd | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/dds.vhd b/dds.vhd index 2c2c61b..9512513 100644 --- a/dds.vhd +++ b/dds.vhd @@ -40,14 +40,14 @@ architecture Behavioral of dds is signal idx_phase : unsigned(phase_res-1 downto 0) := (others => '0'); signal amp_rect, amp_saw, amp_tria, amp_sin : unsigned (adc_res-1 downto 0); - --type storage is array (((2**phase_res)/4)-1 downto 0) of unsigned (adc_res-2 downto 0); - type storage is array (((2**phase_res))-1 downto 0) of unsigned (adc_res-1 downto 0); + type storage is array (((2**phase_res)/4)-1 downto 0) of unsigned (adc_res-2 downto 0); + --type storage is array (((2**phase_res))-1 downto 0) of unsigned (adc_res-1 downto 0); function gen_sin_wave return storage is variable temp : storage; begin forLoop: for i in 0 to temp'high loop - --temp(i) := to_unsigned(integer(real((2**(adc_res-1))-1)*sin((real(i)*MATH_PI/2.0)/real(temp'high))),adc_res-1); - temp(i) := to_unsigned(integer(real(2**(adc_res-1) -1) + real((2**(adc_res-1))-1)*sin((real(i)*MATH_PI*2.0)/real(temp'high))),adc_res); + temp(i) := to_unsigned(integer(real((2**(adc_res-1))-1)*sin((real(i)*MATH_PI/2.0)/real(temp'high))),adc_res-1); + --temp(i) := to_unsigned(integer(real(2**(adc_res-1) -1) + real((2**(adc_res-1))-1)*sin((real(i)*MATH_PI*2.0)/real(temp'high))),adc_res); end loop; return temp; @@ -76,20 +76,19 @@ begin idx_phase <= idx(acc_res -1 downto acc_res - phase_res); - amp_sin <= sin_wave(to_integer(idx_phase)); - -- Modulo is only required to prevent a synthesizer warning, but the value is actually never > 2**phase_res/4 - --amp_sin <= to_unsigned((2**(adc_res-1)) - 1,adc_res) + sin_wave(to_integer(idx_phase) mod ((2**phase_res)/4)) when idx_phase(phase_res-1 downto phase_res-2)="00" else - -- to_unsigned((2**(adc_res-1)) - 1,adc_res) + sin_wave(to_integer(((2**phase_res)/2)-idx_phase) mod ((2**phase_res)/4)) when idx_phase(phase_res-1 downto phase_res-2)="01" else - -- to_unsigned((2**(adc_res-1)) - 1,adc_res) - sin_wave(to_integer(idx_phase-((2**phase_res)/2)) mod ((2**phase_res)/4)) when idx_phase(phase_res-1 downto phase_res-2)="10" else - -- to_unsigned((2**(adc_res-1)) - 1,adc_res) - sin_wave(to_integer(((2**phase_res)-1)-idx_phase) mod ((2**phase_res)/4)); - + --amp_sin <= sin_wave(to_integer(idx_phase)); + amp_sin <= to_unsigned((2**(adc_res-1)) - 1,adc_res) + sin_wave(to_integer(idx_phase(phase_res-3 downto 0))) when idx_phase(phase_res-1 downto phase_res-2)="00" else + to_unsigned((2**(adc_res-1)) - 1,adc_res) + sin_wave(to_integer(((2**(phase_res-2))-1) - idx_phase(phase_res-3 downto 0))) when idx_phase(phase_res-1 downto phase_res-2)="01" else + to_unsigned((2**(adc_res-1)) - 1,adc_res) - sin_wave(to_integer(idx_phase(phase_res-3 downto 0))) when idx_phase(phase_res-1 downto phase_res-2)="10" else + to_unsigned((2**(adc_res-1)) - 1,adc_res) - sin_wave(to_integer(((2**(phase_res-2))-1) - idx_phase(phase_res-3 downto 0))); + + with form select amp <= amp_rect when "00", amp_saw when "01", amp_tria when "10", amp_sin when others; - P1: process(clk) begin if(rising_edge(clk)) then From ecdaaccee550eebefc76d67ee1f772f11790e22e Mon Sep 17 00:00:00 2001 From: T-moe Date: Fri, 3 Jun 2016 15:20:32 +0200 Subject: [PATCH 13/13] Extended controller a bit so that the user can change the digit pos. --- controller.sym | 39 +++++++++--------- controller.vhd | 30 ++++++++++++-- io.ucf | 4 +- toplevel.sch | 106 +++++++++++++++++++++++++------------------------ yasg.gise | 74 +++++++++++++++++----------------- yasg.xise | 18 ++++----- 6 files changed, 152 insertions(+), 119 deletions(-) diff --git a/controller.sym b/controller.sym index edf28fc..f90185d 100644 --- a/controller.sym +++ b/controller.sym @@ -1,28 +1,31 @@ BLOCK - 2016-5-23T16:56:10 - - - - + 2016-6-3T12:59:50 + + - + + + + - - - + + + + - - - - - - - - - + + + + + + + + + + diff --git a/controller.vhd b/controller.vhd index 437f611..3f6bcfb 100644 --- a/controller.vhd +++ b/controller.vhd @@ -34,33 +34,57 @@ entity controller is rst: in STD_LOGIC; enc_updown : in STD_LOGIC; enc_ce : in STD_LOGIC; + enc_btn: in STD_LOGIC; enc_err : in STD_LOGIC; freq_out : out unsigned (16 downto 0)); end controller; architecture Behavioral of controller is signal freq_reg, freq_next : unsigned(16 downto 0) := to_unsigned(1000,17); + signal digpos_reg, digpos_next : unsigned(2 downto 0) := to_unsigned(0,3); + signal btn_old_reg, btn_old_next : std_logic := '0'; + + type storage is array (4 downto 0) of unsigned (16 downto 0); + constant bases : storage := (to_unsigned(1,17),to_unsigned(10,17), + to_unsigned(100,17),to_unsigned(1000,17), + to_unsigned(10000,17)); + + signal digpos_base : unsigned(16 downto 0); begin proc1: process(clk,rst) begin if(rst='1') then freq_reg <= to_unsigned(1000,17); + digpos_reg <= to_unsigned(0,3); + btn_old_reg <= '0'; elsif(rising_edge(clk)) then freq_reg <= freq_next; + digpos_reg <= digpos_next; + btn_old_reg <= btn_old_next; end if; end process proc1; freq_out <= freq_reg; + digpos_base <= bases(to_integer(digpos_reg)); - proc2: process(freq_reg,enc_updown,enc_ce,enc_err) + proc2: process(freq_reg,enc_updown,enc_ce,enc_err,enc_btn,digpos_reg,digpos_base,btn_old_reg) begin freq_next <= freq_reg; + digpos_next <= digpos_reg; + btn_old_next <= enc_btn; + if(enc_ce='1' and enc_err='0') then if(enc_updown='1') then - freq_next <= freq_reg + 1; + freq_next <= freq_reg + digpos_base; else - freq_next <= freq_reg - 1; + freq_next <= freq_reg - digpos_base; + end if; + elsif(enc_btn ='1' and btn_old_reg='0') then + if(digpos_reg = to_unsigned(4,3)) then + digpos_next <= to_unsigned(0,3); + else + digpos_next <= digpos_reg + 1; end if; end if; diff --git a/io.ucf b/io.ucf index 24d0206..e441457 100644 --- a/io.ucf +++ b/io.ucf @@ -19,4 +19,6 @@ NET "SW0" LOC = "V8" | IOSTANDARD = LVCMOS33 ; NET "SW1" LOC = "U10"| IOSTANDARD = LVCMOS33 ; NET "ROT_A" LOC = "T13" | IOSTANDARD = LVCMOS33 | PULLUP; -NET "ROT_B" LOC = "R14" | IOSTANDARD = LVCMOS33 | PULLUP; \ No newline at end of file +NET "ROT_B" LOC = "R14" | IOSTANDARD = LVCMOS33 | PULLUP; +NET "ROT_CENTER" LOC = "R13" | IOSTANDARD = LVCMOS33 | PULLDOWN; + \ No newline at end of file diff --git a/toplevel.sch b/toplevel.sch index c2f21e0..7c324d3 100644 --- a/toplevel.sch +++ b/toplevel.sch @@ -6,7 +6,6 @@ - @@ -29,9 +28,10 @@ - + + @@ -46,6 +46,7 @@ + 2016-5-20T8:33:2 @@ -92,15 +93,16 @@ - 2016-5-23T16:56:10 - + 2016-6-3T12:59:50 + - - - - - + + + + + + 2016-5-23T16:56:27 @@ -166,11 +168,12 @@ - - - + + + + @@ -181,7 +184,7 @@ - + @@ -242,12 +245,10 @@ - - - - - - + + + + @@ -294,39 +295,14 @@ - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - + @@ -341,9 +317,37 @@ - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/yasg.gise b/yasg.gise index 51e396f..8efff80 100644 --- a/yasg.gise +++ b/yasg.gise @@ -63,7 +63,9 @@ + + @@ -92,9 +94,7 @@ - - @@ -135,6 +135,7 @@ + @@ -149,38 +150,37 @@ - + - + + - + - + - - + - - + @@ -188,71 +188,72 @@ + + - + - + + - - - + - + - - + - + - + - + - + - + - + - + + @@ -272,11 +273,11 @@ - + - + @@ -285,12 +286,9 @@ - + - - - @@ -301,9 +299,8 @@ - + - @@ -316,7 +313,7 @@ - + @@ -328,12 +325,15 @@ - + - + + + + - + diff --git a/yasg.xise b/yasg.xise index b50633d..3067366 100644 --- a/yasg.xise +++ b/yasg.xise @@ -20,42 +20,42 @@ - + - + - + - + - + - + - + - + @@ -82,7 +82,7 @@ - +