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

Subversion Repositories manchesterwireless

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /manchesterwireless
    from Rev 2 to Rev 3
    Reverse comparison

Rev 2 → Rev 3

trunk/twoToOne/simTest.vhd Property changes : Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: trunk/twoToOne/twoToOne.vhd =================================================================== --- trunk/twoToOne/twoToOne.vhd (revision 2) +++ trunk/twoToOne/twoToOne.vhd (nonexistent) @@ -1,225 +0,0 @@ ------------------------------------------------------------------------------ --- 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. --- --- twoToOne.vhd --- --- 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; - --- For encoded_i: --- --- 0000 = null --- 0001 = single one --- 0010 = double one --- 0100 = single zero --- 1000 = double zero - -entity twoToOne 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 twoToOne; - -architecture Behavioral of twoToOne 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 - 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 - - 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 - -- update one or two? - if index - index_n = 2 then -- update 2 - str_buffer(index downto index-1) <= insert; - else -- update 1 - str_buffer(index) <= insert(1); - 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; - - 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 - - when one_0 => - - case(encoded_i) is - when "0100" => next_state <= one_0; -- remain here until change - when "0001" => next_state <= one_1; - 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! - 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 Behavioral; -
trunk/twoToOne/twoToOne.vhd Property changes : Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: trunk/readme.txt =================================================================== --- trunk/readme.txt (revision 2) +++ trunk/readme.txt (nonexistent) @@ -1,11 +0,0 @@ -Usage: - -Open globals.vhd. Change WORD_LENGTH to the number of bits to be received -- this is the number of bits _before_ Manchester encoding. - -The constants: INTERVAL_MAX_DOUBLE, INTERVAL_MIN_DOUBLE, INTERVAL_MAX_SINGLE, INTERVAL_MIN_SINGLE, INTERVAL_QUADRUPLE set the window of FPGA clocks needed to classify a single/double one/zero. For example, if transmission arrives at 1K BAUD, then each bit is 1ms long. If the FPGA clock is 50MHz, giving a period of 2E-8, then 50K FPGA clocks will occur each bit. Therefore set INTERVAL_MIN/MAX_SINGLE to be somewhere on either end of 50K, for example 10K and 75K. Do similar for INTERVAL_MIN/MAX_DOUBLE. Unfortunately, you will probably need to experiment to see how static your transmitter BAUD really is. - -Out of the box, the decodeManchester core will decode one transmission, then stop, waiting to be reset, until the next signal is decodable. See synthTest.vhd for a simple way to reset the circuit after each received bit. - -TODO: - -When testing this circuit with an ASK transmitter/receiver pair, random radio noise was a huge problem. There needs to be a way to strengthen the protocol. Also, I believe, it is from the quality of the ASK equipment, the twoToOne subcore misses some bits, causing frustrating noise to be permitted into the system. \ No newline at end of file
trunk/readme.txt Property changes : Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: trunk/md16/md16.vhd =================================================================== --- trunk/md16/md16.vhd (revision 2) +++ trunk/md16/md16.vhd (nonexistent) @@ -1,176 +0,0 @@ ------------------------------------------------------------------------------ --- 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. --- --- md16.vhd --- --- Manchester Decoding based on Oversampling & Counting Algorithm --- --- Revision Date Author Comment --- -------- ---------- -------------------- ---------------- --- 1.0 20/02/09 J. Rodriguez-Navarro Initial revision --- 2.0 15/05/09 S. Green Reduced scope ------------------------------------------------------------------------------ - -library ieee; -use ieee.std_logic_1164.all; -use ieee.std_logic_arith.all; -use work.globals.all; - --------------------------------------------------------------------------------- - -entity md16 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 md16; - --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- - -architecture inst_md16 of md16 is - -signal transition_n: std_logic; -signal transition_i: std_logic; - -signal count_ones : integer range 0 to MAX_COUNT; -signal count_ones_n : integer range 0 to MAX_COUNT; -signal count_zeros : integer range 0 to MAX_COUNT; -signal count_zeros_n : integer range 0 to MAX_COUNT; - -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 --- -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; - -
trunk/md16/md16.vhd Property changes : Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: trunk/md16/simTest.vhd =================================================================== --- trunk/md16/simTest.vhd (revision 2) +++ trunk/md16/simTest.vhd (nonexistent) @@ -1,88 +0,0 @@ -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 md16 - 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_md16: md16 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; -
trunk/md16/simTest.vhd Property changes : Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: trunk/decodeManchester.vhd =================================================================== --- trunk/decodeManchester.vhd (revision 2) +++ trunk/decodeManchester.vhd (nonexistent) @@ -1,109 +0,0 @@ ------------------------------------------------------------------------------ --- 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 decodeManchester 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 decodeManchester; - -architecture behavioral of decodeManchester 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 md16 - 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 twoToOne - 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_md16: md16 - 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_twoToOne: twoToOne - 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 behavioral; -
trunk/decodeManchester.vhd Property changes : Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: trunk/globals.vhd =================================================================== --- trunk/globals.vhd (revision 2) +++ trunk/globals.vhd (revision 3) @@ -6,12 +6,15 @@ constant WORD_LENGTH : integer := 4; -- when each transmitter bit is 3.24 ms and the FPGA clock is 50 MHz - constant MAX_COUNT: integer := 2**18-1; + -- 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_MIN_DOUBLE: integer := 90000;--80000 - -- single is nominally 23200 - constant INTERVAL_MAX_SINGLE: integer := 65000; - constant INTERVAL_MIN_SINGLE: integer := 10000; + constant INTERVAL_QUADRUPLE: integer := 650000;--350000 end globals; \ No newline at end of file
/trunk/decode/decode.vhd
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;
 
trunk/decode/decode.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/decode/simTest.vhd =================================================================== --- trunk/decode/simTest.vhd (nonexistent) +++ trunk/decode/simTest.vhd (revision 3) @@ -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 twoToOne + 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_twoToOne: twoToOne 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; +
trunk/decode/simTest.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/synthTest.vhd =================================================================== --- trunk/synthTest.vhd (revision 2) +++ trunk/synthTest.vhd (revision 3) @@ -19,7 +19,7 @@ architecture Behavioral of synthTest is - component decodeManchester + component manchesterWireless port ( clk_i : in std_logic; rst_i : in std_logic; @@ -32,7 +32,6 @@ end component; signal decode_output : std_logic_vector(WORD_LENGTH-1 downto 0); - -- up/down and left/right buffers signal ud_buff1, ud_buff1_reg : std_logic_vector(6 downto 0); signal reset_manchester, soft_reset, ready_o_buff : std_logic; begin @@ -42,7 +41,7 @@ reset_manchester <= rst_i or soft_reset; ready_o <= ready_o_buff; - inst_decodeManchester: decodeManchester + inst_manchesterWireless : manchesterWireless port map( clk_i => clk_i, rst_i => reset_manchester, @@ -53,7 +52,7 @@ waitforstart_rdy => waitforstart_rdy ); - -- decode up/down first digit (ones place) + -- decode digit with decode_output(3 downto 0) select ud_buff1 <= "0000001" when x"0", -- off "1001111" when x"1", -- 1 @@ -84,7 +83,7 @@ end if; end process; - character_o(0 to 6) <= ud_buff1_reg; + character_o(0 to 6) <= ud_buff1_reg; anode_ctrl <= "0111"; end Behavioral;
/trunk/manchesterWireless.vhd
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;
 
trunk/manchesterWireless.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/waitForStart/waitForStart.vhd =================================================================== --- trunk/waitForStart/waitForStart.vhd (revision 2) +++ trunk/waitForStart/waitForStart.vhd (revision 3) @@ -11,10 +11,9 @@ -- 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 -- --- Revision Date Author Comment --- -------- ---------- -------------------- ---------------- --- 1.0 09/06/09 S. Green Initial version ----------------------------------------------------------------------------- library ieee; @@ -29,7 +28,7 @@ rst_i : in std_logic; ready_o : out std_logic ); -end waitForStart; +end; architecture behavioral of waitForStart is begin @@ -57,5 +56,5 @@ end if; end process; - end behavioral; + end;
/trunk/documentation/design.txt
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.
trunk/documentation Property changes : Added: svn:ignore ## -0,0 +1 ## +design.odt Index: trunk/singleDouble/singleDouble.vhd =================================================================== --- trunk/singleDouble/singleDouble.vhd (nonexistent) +++ trunk/singleDouble/singleDouble.vhd (revision 3) @@ -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; + +
trunk/singleDouble/singleDouble.vhd Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/singleDouble/simTest.vhd =================================================================== --- trunk/singleDouble/simTest.vhd (nonexistent) +++ trunk/singleDouble/simTest.vhd (revision 3) @@ -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 md16 + 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_md16: md16 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; +
trunk/singleDouble/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.