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 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/trunk/globals.vhd
0,0 → 1,17
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 |
constant MAX_COUNT: integer := 2**18-1; |
-- double is nominally 43000-50000 |
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; |
trunk/globals.vhd
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: trunk/synthTest.vhd
===================================================================
--- trunk/synthTest.vhd (nonexistent)
+++ trunk/synthTest.vhd (revision 2)
@@ -0,0 +1,91 @@
+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 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 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_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
+ );
+
+ -- decode up/down first digit (ones place)
+ 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;
+
trunk/synthTest.vhd
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: trunk/md16/md16.vhd
===================================================================
--- trunk/md16/md16.vhd (nonexistent)
+++ trunk/md16/md16.vhd (revision 2)
@@ -0,0 +1,176 @@
+-----------------------------------------------------------------------------
+-- 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 :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: trunk/md16/simTest.vhd
===================================================================
--- trunk/md16/simTest.vhd (nonexistent)
+++ trunk/md16/simTest.vhd (revision 2)
@@ -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/md16/simTest.vhd
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: trunk/simTest.vhd
===================================================================
--- trunk/simTest.vhd (nonexistent)
+++ trunk/simTest.vhd (revision 2)
@@ -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;
+
+
+
trunk/simTest.vhd
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: trunk/waitForStart/simTest.vhd
===================================================================
--- trunk/waitForStart/simTest.vhd (nonexistent)
+++ trunk/waitForStart/simTest.vhd (revision 2)
@@ -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;
+
trunk/waitForStart/simTest.vhd
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: trunk/waitForStart/waitForStart.vhd
===================================================================
--- trunk/waitForStart/waitForStart.vhd (nonexistent)
+++ trunk/waitForStart/waitForStart.vhd (revision 2)
@@ -0,0 +1,61 @@
+-----------------------------------------------------------------------------
+-- 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 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 waitForStart;
+
+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 behavioral;
+
trunk/waitForStart/waitForStart.vhd
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: trunk/readme.txt
===================================================================
--- trunk/readme.txt (nonexistent)
+++ trunk/readme.txt (revision 2)
@@ -0,0 +1,11 @@
+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 :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: trunk/decodeManchester.vhd
===================================================================
--- trunk/decodeManchester.vhd (nonexistent)
+++ trunk/decodeManchester.vhd (revision 2)
@@ -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 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 :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: trunk/twoToOne/simTest.vhd
===================================================================
--- trunk/twoToOne/simTest.vhd (nonexistent)
+++ trunk/twoToOne/simTest.vhd (revision 2)
@@ -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/twoToOne/simTest.vhd
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: trunk/twoToOne/twoToOne.vhd
===================================================================
--- trunk/twoToOne/twoToOne.vhd (nonexistent)
+++ trunk/twoToOne/twoToOne.vhd (revision 2)
@@ -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.
+--
+-- 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 :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property