OpenCores
URL https://opencores.org/ocsvn/manchesterwireless/manchesterwireless/trunk

Subversion Repositories manchesterwireless

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /manchesterwireless/tags
    from Rev 1 to Rev 5
    Reverse comparison

Rev 1 → Rev 5

/release-1.0/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;
 
release-1.0/decode/simTest.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: release-1.0/decode/decode.vhd =================================================================== --- release-1.0/decode/decode.vhd (nonexistent) +++ release-1.0/decode/decode.vhd (revision 5) @@ -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; +
release-1.0/decode/decode.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: release-1.0/singleDouble/simTest.vhd =================================================================== --- release-1.0/singleDouble/simTest.vhd (nonexistent) +++ release-1.0/singleDouble/simTest.vhd (revision 5) @@ -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; +
release-1.0/singleDouble/simTest.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: release-1.0/singleDouble/singleDouble.vhd =================================================================== --- release-1.0/singleDouble/singleDouble.vhd (nonexistent) +++ release-1.0/singleDouble/singleDouble.vhd (revision 5) @@ -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; + +
release-1.0/singleDouble/singleDouble.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: release-1.0/globals.vhd =================================================================== --- release-1.0/globals.vhd (nonexistent) +++ release-1.0/globals.vhd (revision 5) @@ -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
release-1.0/globals.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: release-1.0/synthTest.vhd =================================================================== --- release-1.0/synthTest.vhd (nonexistent) +++ release-1.0/synthTest.vhd (revision 5) @@ -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; +
release-1.0/synthTest.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: release-1.0/manchesterWireless.vhd =================================================================== --- release-1.0/manchesterWireless.vhd (nonexistent) +++ release-1.0/manchesterWireless.vhd (revision 5) @@ -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; +
release-1.0/manchesterWireless.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: release-1.0/waitForStart/waitForStart.vhd =================================================================== --- release-1.0/waitForStart/waitForStart.vhd (nonexistent) +++ release-1.0/waitForStart/waitForStart.vhd (revision 5) @@ -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; +
release-1.0/waitForStart/waitForStart.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: release-1.0/waitForStart/simTest.vhd =================================================================== --- release-1.0/waitForStart/simTest.vhd (nonexistent) +++ release-1.0/waitForStart/simTest.vhd (revision 5) @@ -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; +
release-1.0/waitForStart/simTest.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: release-1.0/documentation/design.txt =================================================================== --- release-1.0/documentation/design.txt (nonexistent) +++ release-1.0/documentation/design.txt (revision 5) @@ -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: release-1.0/documentation =================================================================== --- release-1.0/documentation (nonexistent) +++ release-1.0/documentation (revision 5)
release-1.0/documentation Property changes : Added: svn:ignore ## -0,0 +1 ## +design.odt Index: release-1.0/simTest.vhd =================================================================== --- release-1.0/simTest.vhd (nonexistent) +++ release-1.0/simTest.vhd (revision 5) @@ -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; + + +
release-1.0/simTest.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.