URL
https://opencores.org/ocsvn/manchesterwireless/manchesterwireless/trunk
Subversion Repositories manchesterwireless
Compare Revisions
- This comparison shows the changes necessary to convert path
/manchesterwireless/branches
- from Rev 1 to Rev 6
- ↔ Reverse comparison
Rev 1 → Rev 6
/singledouble/decode/simTest.vhd
0,0 → 1,257
library IEEE; |
use IEEE.STD_LOGIC_1164.ALL; |
use IEEE.STD_LOGIC_ARITH.ALL; |
use IEEE.STD_LOGIC_UNSIGNED.ALL; |
|
use work.globals.all; |
|
entity sim_test is |
end sim_test; |
|
architecture Behavioral of sim_test is |
|
COMPONENT decode |
PORT( |
clk_i : in std_logic; |
rst_i : in std_logic; |
encoded_i : in std_logic_vector(3 downto 0); |
nd_i : in std_logic; |
decoded_o : out std_logic_vector(WORD_LENGTH-1 downto 0); |
nd_o : out std_logic |
); |
END COMPONENT; |
|
-- For encoded_i: |
-- |
-- 0000 = null |
-- 0001 = single one |
-- 0010 = single zero |
-- 0100 = double one |
-- 1000 = double zero |
|
signal clk_i : std_logic; |
signal rst_i : std_logic; |
signal encoded_i : std_logic_vector(3 downto 0) := "0000"; |
signal nd_i : std_logic := '0'; |
signal decoded_o : std_logic_vector(WORD_LENGTH-1 downto 0); |
signal nd_o : std_logic; |
constant half_period : time := 10 ns; |
constant period : time := 2*half_period; |
constant mid_single : time := (INTERVAL_MIN_SINGLE+INTERVAL_MAX_SINGLE)/2*period; |
|
begin |
|
Inst_decode: decode PORT MAP( |
clk_i => clk_i, |
rst_i => rst_i, |
encoded_i => encoded_i, |
nd_i => nd_i, |
decoded_o => decoded_o, |
nd_o => nd_o |
); |
|
process |
begin |
-- below never changes |
rst_i <= '1'; |
wait for MID_SINGLE; |
|
rst_i <= '0'; |
encoded_i <= "0000"; |
wait for MID_SINGLE; |
|
|
nd_i <= '1'; |
wait for period; |
nd_i <= '0'; |
|
wait for MID_SINGLE; |
|
encoded_i <= "1000"; -- 00 |
|
nd_i <= '1'; |
wait for period; |
nd_i <= '0'; |
|
wait for MID_SINGLE; |
|
-- above never changes |
|
encoded_i <= "0010"; --11 |
|
nd_i <= '1'; |
wait for period; |
nd_i <= '0'; |
|
wait for MID_SINGLE; |
|
encoded_i <= "0100"; --0 |
|
nd_i <= '1'; |
wait for period; |
nd_i <= '0'; |
|
wait for MID_SINGLE; |
|
encoded_i <= "0001"; --1 |
|
nd_i <= '1'; |
wait for period; |
nd_i <= '0'; |
|
wait for MID_SINGLE; |
|
encoded_i <= "1000"; --00 |
|
nd_i <= '1'; |
wait for period; |
nd_i <= '0'; |
|
wait for MID_SINGLE; |
|
|
encoded_i <= "0001"; --1 |
|
nd_i <= '1'; |
wait for period; |
nd_i <= '0'; |
|
wait for MID_SINGLE; |
|
encoded_i <= "0100"; --0 |
|
nd_i <= '1'; |
wait for period; |
nd_i <= '0'; |
|
wait for MID_SINGLE; |
|
encoded_i <= "0001"; --1 |
|
nd_i <= '1'; |
wait for period; |
nd_i <= '0'; |
|
wait for MID_SINGLE; |
|
encoded_i <= "0100"; --0 |
|
nd_i <= '1'; |
wait for period; |
nd_i <= '0'; |
|
wait for MID_SINGLE; |
|
encoded_i <= "0001"; --1 |
|
nd_i <= '1'; |
wait for period; |
nd_i <= '0'; |
|
wait for MID_SINGLE; |
|
encoded_i <= "0100"; --0 |
|
nd_i <= '1'; |
wait for period; |
nd_i <= '0'; |
|
wait for MID_SINGLE; |
|
encoded_i <= "0001"; --1 |
|
nd_i <= '1'; |
wait for period; |
nd_i <= '0'; |
|
wait for MID_SINGLE; |
|
encoded_i <= "0100"; --0 |
|
nd_i <= '1'; |
wait for period; |
nd_i <= '0'; |
|
wait for MID_SINGLE; |
|
encoded_i <= "0001"; --1 |
|
nd_i <= '1'; |
wait for period; |
nd_i <= '0'; |
|
wait for MID_SINGLE; |
|
encoded_i <= "0100"; --0 |
|
nd_i <= '1'; |
wait for period; |
nd_i <= '0'; |
|
wait for MID_SINGLE; |
|
encoded_i <= "0001"; --1 |
|
nd_i <= '1'; |
wait for period; |
nd_i <= '0'; |
|
wait for MID_SINGLE; |
|
encoded_i <= "0100"; --0 |
|
nd_i <= '1'; |
wait for period; |
nd_i <= '0'; |
|
wait for MID_SINGLE; |
|
|
|
|
|
encoded_i <= "0001"; --1 |
|
nd_i <= '1'; |
wait for period; |
nd_i <= '0'; |
|
wait for MID_SINGLE; |
|
encoded_i <= "0100"; --0 |
|
nd_i <= '1'; |
wait for period; |
nd_i <= '0'; |
|
wait for MID_SINGLE; |
|
encoded_i <= "0001"; --1 |
|
nd_i <= '1'; |
wait for period; |
nd_i <= '0'; |
|
wait for MID_SINGLE; |
|
encoded_i <= "0100"; --0 |
|
nd_i <= '1'; |
wait for period; |
nd_i <= '0'; |
|
wait for MID_SINGLE; |
|
end process; |
|
clock : process |
begin |
clk_i <= '1'; |
loop |
wait for half_period; |
clk_i <= not clk_i; |
end loop; |
end process; |
|
end Behavioral; |
|
singledouble/decode/simTest.vhd
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: singledouble/decode/decode.vhd
===================================================================
--- singledouble/decode/decode.vhd (nonexistent)
+++ singledouble/decode/decode.vhd (revision 6)
@@ -0,0 +1,225 @@
+-----------------------------------------------------------------------------
+-- Copyright (C) 2009 Sam Green
+--
+-- This code is free software; you can redistribute it and/or
+-- modify it under the terms of the GNU Lesser General Public
+-- License as published by the Free Software Foundation; either
+-- version 2.1 of the License, or (at your option) any later version.
+--
+-- This code is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+-- Lesser General Public License for more details.
+--
+-- Decodes manchester encoded data
+--
+-----------------------------------------------------------------------------
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+
+use work.globals.all;
+
+entity decode is
+
+ port (
+ clk_i : in std_logic;
+ rst_i : in std_logic;
+ nd_i : in std_logic;
+ encoded_i : in std_logic_vector(3 downto 0);
+ decoded_o : out std_logic_vector(WORD_LENGTH-1 downto 0);
+ nd_o : out std_logic
+ );
+
+end;
+
+architecture behavioral of decode is
+
+ type state_type is (reset, pause, one_0, one_1, two_0, two_1);
+ signal state, next_state : state_type;
+
+ -- *2 comes from each bit in the word is manchester encoded.
+ -- +2 comes from protocol transmitting -------_ to initiate
+ -- a transmission; +1 from the ------- and +1 from the _
+ constant STRING_LENGTH : integer := WORD_LENGTH*2+2;
+ -- the range -1 comes from the state machine which will
+ -- update index_n while the protocol finishes transmission
+ signal index, index_n : integer range -1 to STRING_LENGTH-1;
+ signal str_buffer : std_logic_vector(STRING_LENGTH-3 downto 0);
+ signal insert : std_logic_vector(1 downto 0);
+ signal nd_o_buff : std_logic;
+begin
+
+ controller : process(nd_i, rst_i)
+ begin
+ if rst_i = '1' then
+
+ index <= STRING_LENGTH-1;
+ state <= reset;
+ str_buffer <= (others => '0');
+ nd_o_buff <= '0';
+
+ elsif rising_edge(nd_i) then
+ -- index is initalized at STRING_LENGTH-1
+ -- the protocol initializes with two bits
+ -- which are trashed, hence we wait until the first
+ -- trashed bits have been passed
+ --
+ -- processing stops when the WORD_LENGTH bits have arrived (nd_o_buff = '1')
+ if STRING_LENGTH - index >= 3 and nd_o_buff = '0' then
+ -- Adding a single/double zero/one?
+ if index - index_n = 2 then -- update 2
+ str_buffer(index downto index-1) <= insert; -- insert double
+ else -- update 1
+ str_buffer(index) <= insert(1); -- insert single
+ end if;
+ end if;
+
+ -- finished?
+ if index = 0 then
+ nd_o_buff <= '1';
+ state <= reset;
+ else
+ index <= index_n;
+ state <= next_state;
+ end if;
+ end if;
+ end process;
+
+ output_decode: process(state, index, nd_i)
+ begin
+ case state is
+
+ when one_1 =>
+ insert <= "10";
+ if (index > -1) then
+ index_n <= index - 1;
+ else
+ index_n <= 0; -- error
+ end if;
+
+ when one_0 =>
+ insert <= "00";
+ if (index > -1) then
+ index_n <= index - 1;
+ else
+ index_n <= 0; -- error
+ end if;
+
+ when two_1 =>
+ insert <= "11";
+
+ if (index > 0) then
+ index_n <= index - 2;
+ else
+ index_n <= 0; -- error
+ end if;
+
+ when two_0 =>
+ insert <= "00";
+
+ if (index > 0) then
+ index_n <= index - 2;
+ else
+ index_n <= 0; -- error
+ end if;
+
+ when others =>
+ insert <= "00";
+ index_n <= index;
+
+ end case;
+ end process;
+
+ -- For encoded_i:
+ --
+ -- 0000 = null
+ -- 0001 = single one
+ -- 0010 = double one
+ -- 0100 = single zero
+ -- 1000 = double zero
+
+ next_state_decode: process(state, encoded_i)
+ begin
+ next_state <= state;
+ case(state) is
+ when reset =>
+
+ next_state <= pause;
+
+ when pause =>
+
+ next_state <= one_1; -- only if we came from reset. The long
+ -- initialization string of ones --------- is considered a
+ -- single one.
+
+ when one_0 =>
+
+ case(encoded_i) is
+ when "0100" => next_state <= one_0; -- remain here until change
+ when "0001" => next_state <= one_1; -- because of the protocol, a
+ -- single 0 can only be followed by a single one.
+ when others => next_state <= reset; -- only on error
+ end case;
+
+ when one_1 =>
+
+ case(encoded_i) is
+ when "0001" => next_state <= one_1; -- remain here until change
+ when "0100" => next_state <= one_0;
+ when "1000" => next_state <= two_0;
+ when others => next_state <= reset; -- only on error
+ end case;
+
+ when two_0 =>
+
+ case(encoded_i) is
+ when "1000" => next_state <= two_0; -- remain here until change
+ when "0001" => next_state <= one_1;
+ when "0010" => next_state <= two_1;
+ when others => next_state <= reset; -- only on error
+ end case;
+
+ when two_1 =>
+
+ case(encoded_i) is
+ when "0010" => next_state <= two_1; -- remain here until change
+ when "0100" => next_state <= one_0;
+ when "1000" => next_state <= two_0;
+ when others => next_state <= reset; -- only on error
+ end case;
+
+ when others =>
+ next_state <= reset; -- only on error
+
+ end case;
+ end process;
+
+ -- decoded!
+ rearrange : process(clk_i, rst_i)
+ begin
+ if rst_i = '1' then
+ decoded_o <= (others => '0');
+ nd_o <= '0';
+ elsif rising_edge(clk_i) then
+ if nd_o_buff = '1' then
+ for i in 0 to WORD_LENGTH-1 loop
+ -- the bits are ror when transmitted, thus the left-most
+ -- bit in decoded_buffer (excluding the xmitter protocol bits)
+ -- describe the right-most bit in the original data word.
+ -- The following line of code turns 01 to 1 and 10 to 0 and it converts
+ -- the big endian decoded_buffer to little endian decoded_o.
+ if str_buffer(str_buffer'left-2*i downto str_buffer'left-1-2*i) = "01" then
+ decoded_o(i) <= '1';
+ else
+ decoded_o(i) <= '0';
+ end if;
+ end loop;
+
+ nd_o <= '1';
+ end if;
+ end if;
+ end process;
+
+end;
+
singledouble/decode/decode.vhd
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: singledouble/singleDouble/simTest.vhd
===================================================================
--- singledouble/singleDouble/simTest.vhd (nonexistent)
+++ singledouble/singleDouble/simTest.vhd (revision 6)
@@ -0,0 +1,88 @@
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.STD_LOGIC_ARITH.ALL;
+use IEEE.STD_LOGIC_UNSIGNED.ALL;
+
+
+entity test_sim is
+end test_sim;
+
+architecture Behavioral of test_sim is
+
+ COMPONENT singleDouble
+ PORT(
+ clk_i : in std_logic;
+ ce_i : in std_logic;
+ rst_i : in std_logic;
+ data_i : in std_logic;
+ q_o : out std_logic_vector(3 downto 0);
+ ready_o : out std_logic
+ );
+ END COMPONENT;
+
+ signal clk : std_logic := '0';
+ signal ce_i : std_logic := '0';
+ signal mdi : std_logic := '0';
+ signal q : std_logic_vector(3 downto 0);
+ signal nd : std_logic;
+
+ constant period : time := 10 ns;
+ constant md_period : time := period*16;
+ signal reset : std_logic := '1';
+begin
+
+ Inst_singleDouble: singleDouble PORT MAP(
+ clk_i => clk,
+ ce_i => ce_i,
+ rst_i => reset,
+ data_i => mdi,
+ q_o => q,
+ ready_o => nd
+ );
+
+ process
+ begin
+ loop
+ reset <= '1';
+ ce_i <= '0';
+
+ wait for 2*md_period;
+
+ reset <= '0';
+ ce_i <= '1';
+
+ wait for 2*md_period;
+
+ mdi <= not mdi;
+ wait for 2*md_period;
+
+ mdi <= not mdi;
+ wait for md_period;
+
+ mdi <= not mdi;
+ wait for md_period;
+
+ mdi <= not mdi;
+ wait for md_period;
+
+ mdi <= not mdi;
+ wait for 2*md_period;
+
+ mdi <= not mdi;
+ wait for md_period;
+
+ mdi <= not mdi;
+ wait for 5*md_period;
+ end loop;
+ end process;
+
+ process
+ begin
+ loop
+ clk <= not clk;
+ wait for period/2;
+ end loop;
+ end process;
+
+end Behavioral;
+
singledouble/singleDouble/simTest.vhd
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: singledouble/singleDouble/singleDouble.vhd
===================================================================
--- singledouble/singleDouble/singleDouble.vhd (nonexistent)
+++ singledouble/singleDouble/singleDouble.vhd (revision 6)
@@ -0,0 +1,175 @@
+-----------------------------------------------------------------------------
+-- Copyright (C) 2009 José Rodríguez-Navarro
+--
+-- This code is free software; you can redistribute it and/or
+-- modify it under the terms of the GNU Lesser General Public
+-- License as published by the Free Software Foundation; either
+-- version 2.1 of the License, or (at your option) any later version.
+--
+-- This code is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+-- Lesser General Public License for more details.
+--
+-- Identify single/double ones/zeros based on length
+-- of time data_i is high/low
+--
+-- Revision Date Author Comment
+-- -------- ---------- -------------------- ----------------
+-- 1.0 20/02/09 J. Rodriguez-Navarro Initial revision
+-- Future revisions tracked in Subversion at OpenCores.org
+-- under the manchesterwireless project
+-----------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use work.globals.all;
+
+--------------------------------------------------------------------------------
+
+entity singleDouble is
+ port (
+ clk_i : in std_logic;
+ ce_i : in std_logic;
+ rst_i : in std_logic;
+ data_i : in std_logic;
+ q_o : out std_logic_vector(3 downto 0);
+ ready_o : out std_logic
+ );
+end;
+
+--------------------------------------------------------------------------------
+--------------------------------------------------------------------------------
+
+architecture behavioral of singleDouble is
+
+ signal transition_n: std_logic;
+ signal transition_i: std_logic;
+
+ signal count_ones : integer range 0 to INTERVAL_MAX_DOUBLE;
+ signal count_ones_n : integer range 0 to INTERVAL_MAX_DOUBLE;
+ signal count_zeros : integer range 0 to INTERVAL_MAX_DOUBLE;
+ signal count_zeros_n : integer range 0 to INTERVAL_MAX_DOUBLE;
+
+ signal single_one: std_logic;
+ signal double_one: std_logic;
+ signal single_zero: std_logic;
+ signal double_zero: std_logic;
+
+ signal data_i_d : std_logic;
+ signal data_i_d2 : std_logic;
+ signal data_i_d3 : std_logic;
+ signal data_i_d3b: std_logic;
+
+ begin
+
+ --------------------------------------------------------------------------------
+ -- SEQUENTIAL ------------------------------------------------------------------
+ --------------------------------------------------------------------------------
+
+ -- Domain Clock (clk_i)
+ process (rst_i, clk_i)
+ begin
+
+ if rst_i = '1' then
+ data_i_d <= '1';
+ data_i_d2 <= '1';
+ data_i_d3 <= '1';
+ transition_i <= '0';
+ count_ones <= 0;
+ count_zeros <= 0;
+ elsif (rising_edge(clk_i) and ce_i = '1') then -- posedge
+ data_i_d3 <= data_i_d2;
+ data_i_d2 <= data_i_d;
+ data_i_d <= data_i;
+ transition_i <= transition_n;
+ count_ones <= count_ones_n;
+ count_zeros <= count_zeros_n;
+ end if;
+
+ end process;
+
+
+ --------------------------------------------------------------------------------
+ -- COMBINATIONAL ---------------------------------------------------------------
+ --------------------------------------------------------------------------------
+
+ -- Mark transition when an edge on data_i is detected
+ transition_n <= data_i_d xor data_i_d2;
+ ready_o <= transition_i; -- buffered transition_n
+
+ -- Invert and count zeroes
+ data_i_d3b <= not data_i_d3;
+
+ --
+ -- Increment counters between transitions every posedge clk_i
+ --
+ process (transition_i, data_i_d3, data_i_d3b, count_ones, count_zeros)
+ begin
+
+ if transition_i = '1' then
+ count_ones_n <= 0;
+ count_zeros_n <= 0;
+ else
+ count_ones_n <= count_ones + conv_integer(data_i_d3);
+ count_zeros_n <= count_zeros + conv_integer(data_i_d3b);
+ end if;
+
+ end process;
+
+ --
+ -- map single/double one/zero to output
+ --
+ transition : process (transition_i, rst_i)
+ begin
+
+ if (rst_i = '1') then
+ q_o <= "0000"; -- protocol dictates an inital one. used in connecting entity
+ elsif rising_edge(transition_i) then
+ q_o(0) <= single_one;
+ q_o(1) <= double_one;
+ q_o(2) <= single_zero;
+ q_o(3) <= double_zero;
+ end if;
+
+ end process;
+
+ --
+ -- unsigned comparators
+ --
+ process(count_ones)
+ begin
+
+ if (count_ones >= INTERVAL_MIN_DOUBLE) and (count_ones <= INTERVAL_MAX_DOUBLE) then
+ double_one <= '1';
+ else
+ double_one <= '0';
+ end if;
+ if (count_ones >= INTERVAL_MIN_SINGLE) and (count_ones <= INTERVAL_MAX_SINGLE) then
+ single_one <= '1';
+ else
+ single_one <= '0';
+ end if;
+
+ end process;
+
+ process(count_zeros)
+ begin
+
+ if (count_zeros >= INTERVAL_MIN_DOUBLE) and (count_zeros <= INTERVAL_MAX_DOUBLE) then
+ double_zero <= '1';
+ else
+ double_zero <= '0';
+ end if;
+ if (count_zeros >= INTERVAL_MIN_SINGLE) and (count_zeros <= INTERVAL_MAX_SINGLE) then
+ single_zero <= '1';
+ else
+ single_zero <= '0';
+ end if;
+
+ end process;
+
+end;
+
+
singledouble/singleDouble/singleDouble.vhd
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: singledouble/globals.vhd
===================================================================
--- singledouble/globals.vhd (nonexistent)
+++ singledouble/globals.vhd (revision 6)
@@ -0,0 +1,20 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+package globals is
+ -- number of data bits
+ constant WORD_LENGTH : integer := 4;
+
+ -- when each transmitter bit is 3.24 ms and the FPGA clock is 50 MHz
+ -- then:
+
+ -- single is nominally 23200
+ constant INTERVAL_MIN_SINGLE: integer := 10000;
+ constant INTERVAL_MAX_SINGLE: integer := 65000;
+
+ -- double is nominally 43000-50000
+ constant INTERVAL_MIN_DOUBLE: integer := 90000;--80000
+ constant INTERVAL_MAX_DOUBLE: integer := 120000;
+
+ constant INTERVAL_QUADRUPLE: integer := 650000;--350000
+end globals;
\ No newline at end of file
singledouble/globals.vhd
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: singledouble/synthTest.vhd
===================================================================
--- singledouble/synthTest.vhd (nonexistent)
+++ singledouble/synthTest.vhd (revision 6)
@@ -0,0 +1,90 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.globals.all;
+
+entity synthTest is
+ port (
+ clk_i : in std_logic;
+ rst_i : in std_logic;
+ data_i : in std_logic;
+ ready_o : out std_logic;
+ character_o : out std_logic_vector(0 to 7);
+ anode_ctrl : out std_logic_vector(3 downto 0);
+ recieved_debug : out std_logic_vector(3 downto 0);
+ waitforstart_rdy : out std_logic;
+ testpin : out std_logic
+ );
+end synthTest;
+
+architecture Behavioral of synthTest is
+
+ component manchesterWireless
+ port (
+ clk_i : in std_logic;
+ rst_i : in std_logic;
+ data_i : in std_logic;
+ q_o : out std_logic_vector(WORD_LENGTH-1 downto 0);
+ ready_o : out std_logic;
+ recieved_debug : out std_logic_vector(3 downto 0);
+ waitforstart_rdy : out std_logic
+ );
+ end component;
+
+ signal decode_output : std_logic_vector(WORD_LENGTH-1 downto 0);
+ signal ud_buff1, ud_buff1_reg : std_logic_vector(6 downto 0);
+ signal reset_manchester, soft_reset, ready_o_buff : std_logic;
+begin
+ character_o(7) <= '1'; -- turn off decimal point
+ testpin <= '1';
+
+ reset_manchester <= rst_i or soft_reset;
+ ready_o <= ready_o_buff;
+
+ inst_manchesterWireless : manchesterWireless
+ port map(
+ clk_i => clk_i,
+ rst_i => reset_manchester,
+ data_i => data_i,
+ q_o => decode_output,
+ ready_o => ready_o_buff,
+ recieved_debug => recieved_debug,
+ waitforstart_rdy => waitforstart_rdy
+ );
+
+ -- decode digit
+ with decode_output(3 downto 0) select
+ ud_buff1 <= "0000001" when x"0", -- off
+ "1001111" when x"1", -- 1
+ "0010010" when x"2", -- 2
+ "0000110" when x"3", -- 3
+ "1001100" when x"4", -- 4
+ "0100100" when x"5", -- 5
+ "0100000" when x"6", -- 6
+ "0001111" when x"7", -- 7
+ "0000000" when x"8", -- 8
+ "0000100" when x"9", -- 9
+ "0110000" when others; -- Error
+
+ process (clk_i,rst_i)
+ begin
+ if rst_i = '1' then
+ soft_reset <= '0';
+ ud_buff1_reg <= "1111111";
+ elsif (clk_i'event and clk_i = '1') then
+ -- register the output
+ if (ready_o_buff = '1') then
+ ud_buff1_reg <= ud_buff1;
+ soft_reset <= '1';
+ else
+ soft_reset <= '0';
+ end if;
+
+ end if;
+ end process;
+
+ character_o(0 to 6) <= ud_buff1_reg;
+ anode_ctrl <= "0111";
+
+end Behavioral;
+
singledouble/synthTest.vhd
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: singledouble/manchesterWireless.vhd
===================================================================
--- singledouble/manchesterWireless.vhd (nonexistent)
+++ singledouble/manchesterWireless.vhd (revision 6)
@@ -0,0 +1,109 @@
+-----------------------------------------------------------------------------
+-- Copyright (C) 2009 Sam Green
+--
+-- This code is free software; you can redistribute it and/or
+-- modify it under the terms of the GNU Lesser General Public
+-- License as published by the Free Software Foundation; either
+-- version 2.1 of the License, or (at your option) any later version.
+--
+-- This code is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+-- Lesser General Public License for more details.
+--
+--
+-- Revision Date Author Comment
+-- -------- ---------- -------------------- ----------------
+-- 1.0 09/06/09 S. Green Initial version
+-----------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.globals.all;
+
+entity manchesterWireless is
+ port (
+ clk_i : in std_logic;
+ rst_i : in std_logic;
+ data_i : in std_logic;
+ q_o : out std_logic_vector(WORD_LENGTH-1 downto 0);
+ ready_o : out std_logic;
+ recieved_debug : out std_logic_vector(3 downto 0);
+ waitforstart_rdy : out std_logic
+ );
+end;
+
+architecture behavioral of manchesterWireless is
+
+ component waitForStart
+ port (
+ data_i : in std_logic;
+ clk_i : in std_logic;
+ rst_i : in std_logic;
+ ready_o : out std_logic
+ );
+ end component;
+
+ component singleDouble
+ port (
+ clk_i : in std_logic;
+ ce_i : in std_logic;
+ rst_i : in std_logic;
+ data_i : in std_logic;
+ q_o : out std_logic_vector(3 downto 0);
+ ready_o : out std_logic
+ );
+ end component;
+
+ component decode
+ port (
+ clk_i : in std_logic;
+ rst_i : in std_logic;
+ nd_i : in std_logic;
+ encoded_i : in std_logic_vector(3 downto 0);
+ decoded_o : out std_logic_vector(WORD_LENGTH-1 downto 0);
+ nd_o : out std_logic
+ );
+ end component;
+
+ signal wait_rdy : std_logic;
+ signal md16_nd : std_logic;
+ signal md16_q_o : std_logic_vector(3 downto 0);
+
+begin
+
+ inst_waitForStart: waitForStart
+ port map(
+ data_i => data_i,
+ clk_i => clk_i,
+ rst_i => rst_i,
+ ready_o => wait_rdy
+ );
+
+ waitforstart_rdy <= wait_rdy;
+
+ inst_singleDouble : singleDouble
+ port map(
+ clk_i => clk_i,
+ ce_i => wait_rdy,
+ rst_i => rst_i,
+ data_i => data_i,
+ q_o => md16_q_o,
+ ready_o => md16_nd
+ );
+
+ recieved_debug <= md16_q_o;
+
+ inst_decode: decode
+ port map(
+ clk_i => clk_i,
+ rst_i => rst_i,
+ nd_i => md16_nd,
+ encoded_i => md16_q_o,
+ decoded_o => q_o,
+ nd_o => ready_o
+ );
+
+end;
+
singledouble/manchesterWireless.vhd
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: singledouble/waitForStart/waitForStart.vhd
===================================================================
--- singledouble/waitForStart/waitForStart.vhd (nonexistent)
+++ singledouble/waitForStart/waitForStart.vhd (revision 6)
@@ -0,0 +1,60 @@
+-----------------------------------------------------------------------------
+-- Copyright (C) 2009 Sam Green
+--
+-- This code is free software; you can redistribute it and/or
+-- modify it under the terms of the GNU Lesser General Public
+-- License as published by the Free Software Foundation; either
+-- version 2.1 of the License, or (at your option) any later version.
+--
+-- This code is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+-- Lesser General Public License for more details.
+--
+-- Waits for data_i to high for INTERVAL_QUADRUPLE FPGA clocks then
+-- sends ready_o high
+--
+-----------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use work.globals.all;
+
+entity waitForStart is
+ port (
+ data_i : in std_logic;
+ clk_i : in std_logic;
+ rst_i : in std_logic;
+ ready_o : out std_logic
+ );
+end;
+
+architecture behavioral of waitForStart is
+begin
+ process (clk_i, rst_i)
+ variable counter : integer;
+ variable lock : std_logic;
+ begin
+ if (rst_i = '1') then
+ ready_o <= '0';
+ counter := 0;
+ lock := '0';
+ elsif rising_edge(clk_i) then
+ if data_i = '1' then
+ counter := counter + 1;
+ else
+ counter := 0;
+ end if;
+
+ if counter > INTERVAL_QUADRUPLE or lock = '1' then
+ ready_o <= '1';
+ lock := '1';
+ else
+ ready_o <= '0';
+ end if;
+ end if;
+ end process;
+
+ end;
+
singledouble/waitForStart/waitForStart.vhd
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: singledouble/waitForStart/simTest.vhd
===================================================================
--- singledouble/waitForStart/simTest.vhd (nonexistent)
+++ singledouble/waitForStart/simTest.vhd (revision 6)
@@ -0,0 +1,62 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity testSim is
+end testSim;
+
+architecture Behavioral of testSim is
+ constant start_length : integer := 20;
+
+ component waitForStart
+ generic (start_length : integer);
+ port (
+ data_i : in std_logic;
+ clk_i : in std_logic;
+ rst_i : in std_logic;
+ ready_o : out std_logic
+ );
+ end component;
+
+ constant half_period : time := 10 ns;
+
+ signal data_i : std_logic;
+ signal clk_i : std_logic;
+ signal rst_i : std_logic := '1';
+ signal ready_o : std_logic;
+begin
+
+ process
+ begin
+ rst_i <= '1';
+ wait for 5 ns;
+ rst_i <= '0';
+ data_i <= '1';
+
+ wait for 400 ns;
+ data_i <= '0';
+
+ wait for 100 ns;
+ data_i <= '1';
+
+ wait for 2000 ns;
+ end process;
+
+ waitForStart1 : waitForStart
+ generic map(start_length => start_length)
+ port map(
+ data_i => data_i,
+ clk_i => clk_i,
+ rst_i => rst_i,
+ ready_o => ready_o
+ );
+
+ clock : process
+ begin
+ clk_i <= '1';
+ loop
+ wait for half_period;
+ clk_i <= not clk_i;
+ end loop;
+ end process;
+end Behavioral;
+
singledouble/waitForStart/simTest.vhd
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: singledouble/documentation/design.txt
===================================================================
--- singledouble/documentation/design.txt (nonexistent)
+++ singledouble/documentation/design.txt (revision 6)
@@ -0,0 +1,117 @@
+Manchester Wireless Core
+
+================================= Overview ====================================
+
+This core was created to serve as a decoder for incoming Manchester encoded
+data. This project was developed using an ASK A315 transmitter/receiver pair
+obtained from Sparkfun.com. The transmitter was driven by an Atmel AVR
+microcontroller. The receiver's output was was plugged into a Xilinx Spartan-3
+starter board obtained from Digilent.
+
+The ASK equipment is convenient in that when the input of the transmitter is
+driven high, the output will also go high, and when the input goes low, the
+output goes low. There is a caveat, however. The receiver's input must make
+high/low transitions at a certain minimum frequency to prevent the receiver
+from outputting random garbage. Furthermore, there is a maximum frequency at
+which these transmitter/receiver pair will operate.
+
+In brief, the Manchester encoding is trivial: 0 is converted to 10 and 1 is
+converted to 01, where 0 and 1 refer to sending the data line of the ASK
+transmitter low (0) or high (1) for one bit length. When programming the
+microcontroller it was easiest to shift the bits of the message off to the
+right and encode/transmit one bit at a time. Take the binary string 1000, for
+example. The first zero is shifted off, and 10 is sent. Likewise, the other two
+zeros are shifted off and sent. Finally the 1 is sent as 01. This gives a
+transmission of 10101001. Note the encoded bits are are in reverse order of the
+original; when the Manchester Wireless Core decodes the bits, it will present
+them in the correct order as 1000.
+
+Because of the asynchronous nature of the input, the challenge is in the
+receiving side. To send a message, then, this core defines a protocol that must
+be adhered to. First, the transmitter sends four high bits. Then the
+transmitter sends one low bit. Then the data stream begins. Finally a few "end
+transmission" bits are sent. Continuing the example above, the total message
+would be :
+
+11110 10101001 0101
+start signal begin data stream begin end transmission
+
+Note that the spaces between the 0's and 1's are added for readability.
+
+
+
+================================= User's Guide ====================================
+
+The file globals.vhd has the constants which must be configured by the user.
+
+Those constants are
+
+WORD_LENGTH : The number of data bits before encoding. In the overview, above,
+the WORD_LENGTH was four bits.
+
+INTERVAL_MIN/MAX_SINGLE, INTERVAL_MIN/MAX_DOUBLE : The number of FGPA clock
+cycles that must pass before the algorithm classifies a single/double/quadruple
+one/zero. For example if the transmitter bit length is 1 ms and the FPGA clock
+is 50 MHz, then the nominal number of FPGA cycles required to classify a bit as
+being a single is 1 ms / (1/50E6 cycles/second) = .001/2E-8 cycles = 50000
+cycles. The transmission, for whatever reasons, will not be exactly 1 ms, which
+is the reason for having a MIN and MAX interval for the single/double and
+quadruple constants. Some experimentation may be necessary to get the best
+performance from this core. It is recommended that you synthesize the
+singleDouble.vhd module, which classifies single/double zeros/ones and see
+which windows will provide the best performance.
+
+INTERVAL_QUADRUPLE : The series of ones at the beginning of the transmission
+must be at least INTERVAL_QUADRUPLE cycles. To get this constant, multiply the
+nominal single bit length by four and add some padding.
+
+Out of the box, the manchesterWireless core will decode one message, then set
+the ready_o flag, then stop. The core must be reset to start waiting for the
+next message. See synthTest.vhd for an example of how to use this core.
+synthTest.vhd is used to create a simple counter which waits for and displays
+the digits 0 to 9 on the LEDs of the Spartan-3 board.
+
+
+
+================================= Design ====================================
+
+manchesterWireless is composed of three modules which flow from the top down:
+
+1)waitForStart : Waits for the data_i to go high for INTERVAL_QUADRUPLE
+cycles then sets ready_o to 1. One process is in wait for start. When data_i
+goes high, a counter will measure how long it stays high. If data_i stays high
+for longer than INTERVAL_QUADRUPLE clocks then the ready_o flag is set and
+remains set until the core is reset; the 'lock' variable keeps the flag set
+after the window is reached. If data_i drops to zero before the ready_o flag is
+set, then the counter will be set to zero.
+
+2)singleDouble : Once waitForStart is finished, singleDouble classifies
+single/double zeros/ones which it outputs on q_o. q_o is a four bit vector
+with the following mapping
+
+q_o(0) <= single_one;
+q_o(1) <= double_one;
+q_o(2) <= single_zero;
+q_o(3) <= double_zero;
+
+
+The constants set in globals.vhd are such that there is never an overlap
+between what is classified as a single or a double.
+
+TODO: The transition process infers a clock from transition_i. This should
+probably be eliminated by polling transition_i on a clock edge.
+
+3)decode : Takes serial input from singleDouble and provides a decoded parallel
+output. The controller process counts how many bits have been decoded and
+stops when all of the message has been encoded. The next_state_decode and
+output_decode processes keep track of the bits coming from singleDouble and
+decodes them. The challenge is that we receive a single_one followed by a
+double_zero, that is 100, we will decode a 0 from the 10 and place the last
+zero in 100 in the left most place of the insert buffer "0_". At this point,
+as can be seen by inspecting the next_state_decode process, only a single
+or double one is possible.
+
+TODO: The next_state_decode process will reset when an unexpected next_state
+is provided. For example, from the state one_0, the only possible valid
+next state is one_1. Any other next_state will send the FSM to reset. It
+would be good to reset the entire circuit at this point.
Index: singledouble/documentation
===================================================================
--- singledouble/documentation (nonexistent)
+++ singledouble/documentation (revision 6)
singledouble/documentation
Property changes :
Added: svn:ignore
## -0,0 +1 ##
+design.odt
Index: singledouble/simTest.vhd
===================================================================
--- singledouble/simTest.vhd (nonexistent)
+++ singledouble/simTest.vhd (revision 6)
@@ -0,0 +1,224 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.globals.all;
+
+entity testSim is
+end testSim;
+
+architecture Behavioral of testSim is
+
+ component decodeManchester
+ port (
+ clk_i : in std_logic;
+ rst_i : in std_logic;
+ data_i : in std_logic;
+ q_o : out std_logic_vector(WORD_LENGTH-1 downto 0);
+ ready_o : out std_logic;
+ recieved_debug : out std_logic_vector(3 downto 0);
+ waitforstart_rdy : out std_logic
+ );
+ end component;
+
+ signal decode_output : std_logic_vector(WORD_LENGTH-1 downto 0);
+ -- up/down and left/right buffers
+ signal parity_o_buff, parity_o_reg : std_logic;
+ signal button_o_buff, button_o_reg : std_logic_vector(1 downto 0);
+ signal ud_buff1, ud_buff2, lr_buff1, lr_buff2 : std_logic_vector(6 downto 0);
+ signal ud_buff1_reg, ud_buff2_reg, lr_buff1_reg, lr_buff2_reg : std_logic_vector(6 downto 0);
+ signal char_select : integer range 0 to 3;
+ signal reset_manchester, soft_reset, ready_o_buff : std_logic;
+
+
+ signal clk_i : std_logic;
+ signal rst_i : std_logic := '1';
+ signal data_i : std_logic;
+ signal ready_o : std_logic;
+ signal character_o : std_logic_vector(0 to 7);
+ signal anode_ctrl : std_logic_vector(3 downto 0);
+ signal button_o : std_logic_vector(1 downto 0);
+ signal parity_o : std_logic;
+ signal recieved_debug : std_logic_vector(3 downto 0);
+ signal waitforstart_rdy : std_logic;
+
+ signal coded_rdy: std_logic;
+ signal coded : std_logic_vector(WORD_LENGTH-1 downto 0);
+ constant half_period : time := 10 ns;
+ constant period : time := 2*half_period;
+ constant mid_single : time := (INTERVAL_MIN_SINGLE+INTERVAL_MAX_SINGLE)/2*period;
+ constant WORD : std_logic_vector(28 downto 0) := "01100101100101010101010101010";
+
+begin
+ character_o(7) <= '1'; -- turn off decimal point
+
+ reset_manchester <= rst_i or soft_reset;
+ ready_o <= ready_o_buff;
+
+ inst_decodeManchester: decodeManchester
+ port map(
+ clk_i => clk_i,
+ rst_i => reset_manchester,
+ data_i => data_i,
+ q_o => decode_output,
+ ready_o => ready_o_buff,
+ recieved_debug => recieved_debug,
+ waitforstart_rdy => waitforstart_rdy
+ );
+
+ -- the transmitter is sending the following UP/DOWN (4 bits)
+ -- then left/right (3 bits), and finally the parity (1 bit)
+ -- each command was ror onto the transmitter -- one at a time.
+ -- the decoder was written to assume that all the data was in
+ -- being shifted to the transmitter from the right
+ -- thus, while we are transmitting:
+ -- initialize|up/down|left/right|buttons|parity|stop
+ -- the decoder will return results to us as
+ -- parity|buttons|left/right|up/down
+ -- bits 9| 8-7 | 6-4 | 3-0
+
+ -- decode up/down first digit (ones place)
+ with decode_output(3 downto 0) select
+ ud_buff1 <= "0000001" when x"D", -- off
+ "1001111" when x"F", -- 1
+ "0010010" when x"7", -- 2
+ "0000110" when x"5", -- 3
+ "1001100" when x"1", -- 4
+ "0100100" when x"3", -- 5
+ "0100000" when x"2", -- 6
+ "0001111" when x"6", -- 7
+ "0000000" when x"e", -- 8
+ "0000100" when x"c", -- 9
+ "0000001" when x"a", -- 10
+ "1001111" when x"b", -- 11
+ "0010010" when x"9", -- 12
+ "0000110" when x"8", -- 13
+ "1111111" when others; -- 'E'rror
+
+ -- decode up/down second digit (tens place)
+ with decode_output(3 downto 0) select
+ ud_buff2 <= "1001111" when x"a", -- 10
+ "1001111" when x"b", -- 11
+ "1001111" when x"9", -- 12
+ "1001111" when x"8", -- 13
+ "1111111" when others;
+
+ -- decode left/right first digit
+ with decode_output(6 downto 4) select
+ lr_buff1 <= "1001111" when "010", -- -1
+ "0010010" when "011", -- -2
+ "0000110" when "001", -- -3
+ "0000001" when "110", -- 0
+ "1001111" when "100", -- 1
+ "0010010" when "101", -- 2
+ "0000110" when "111", -- 3
+ "1111111" when others;
+
+ -- decode left/right sign digit
+ with decode_output(6 downto 4) select
+ lr_buff2 <= "1111110" when "010", -- -1
+ "1111110" when "011", -- -2
+ "1111110" when "001", -- -3
+ "1111111" when others;
+
+ -- decode buttons
+ with decode_output(8 downto 7) select
+ button_o_buff <= "11" when "10", -- 00
+ "01" when "11", -- 10
+ "10" when "01", -- 01
+ "00" when "00", -- 11
+ "11" when others;
+
+ parity_o_buff <= decode_output(9);
+ parity_o <= parity_o_reg;
+
+ process (clk_i,rst_i)
+ variable counter : integer range 0 to 1023;
+ begin
+ if rst_i = '1' then
+ char_select <= 0;
+ counter := 0;
+ div_clk := '0';
+ soft_reset <= '0';
+ elsif (clk_i'event and clk_i = '1') then
+ -- register the output
+ if (ready_o_buff = '1') then
+ ud_buff1_reg <= ud_buff1;
+ ud_buff2_reg <= ud_buff2;
+ lr_buff1_reg <= lr_buff1;
+ lr_buff2_reg <= lr_buff2;
+ button_o_reg <= button_o_buff;
+ parity_o_reg <= parity_o_buff;
+ soft_reset <= '1';
+ else
+ soft_reset <= '0';
+ end if;
+
+ counter := counter + 1;
+ if (counter = 1023) then
+
+ -- this is for simulation
+ -- ModelSim does not want to roll over
+ if char_select < 3 then
+ char_select <= char_select + 1;
+ else
+ char_select <= 0;
+ end if;
+
+ counter := 0;
+ end if;
+
+ end if;
+ end process;
+
+ -- set output
+ with char_select select
+ character_o(0 to 6) <= ud_buff2_reg when 0,
+ ud_buff1_reg when 1,
+ lr_buff2_reg when 2,
+ lr_buff1_reg when 3;
+
+ with char_select select
+ anode_ctrl <= "0111" when 0,
+ "1011" when 1,
+ "1101" when 2,
+ "1110" when 3;
+
+ process
+ begin
+ wait for 5*period;
+ rst_i <= '0';
+
+ -- begin transmission header
+ data_i <= '1';
+ wait for 5*MID_SINGLE;
+
+ data_i <= '0';
+ wait for MID_SINGLE;
+ -- end transmission header
+
+ for i in WORD'left downto 0 loop
+ data_i <= WORD(i);
+ wait for MID_SINGLE;
+ end loop;
+
+ data_i <= '1';
+ wait for MID_SINGLE;
+
+ rst_i <= '1';
+ wait for 5*period;
+
+ end process;
+
+ clock : process
+ begin
+ clk_i <= '1';
+ loop
+ wait for half_period;
+ clk_i <= not clk_i;
+ end loop;
+ end process;
+
+end Behavioral;
+
+
+
singledouble/simTest.vhd
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property