Commit 2366b356 authored by Adrian Weber's avatar Adrian Weber
Browse files

entity for parsing of Cbm RICH sensor informations from uC AddOn, including...

entity for parsing of Cbm RICH sensor informations from uC AddOn, including simulation tb and DP ram for storage of values.
parent 39a41ef9
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
USE ieee.std_logic_UNSIGNED.ALL;
library work;
use work.trb_net_std.all;
--library machxo2;
--use machxo2.all;
entity uart_uC_SensorReadout is
generic(
BAUD : integer := 115200;
MAX_DS18B20 : integer range 0 to 112 := 112; -- 16 sensors on 7 lines -- !! MAX_DS18B20*3+MAX_DS28E17*6 < 1022 !!
MAX_DS28E17 : integer range 0 to 112 := 112 -- 16 sensors on 7 lines
);
port(
CLK : in std_logic;
RESET : in std_logic; -- reset all values
UART_RX : in std_logic; -- incoming data which needs to be processed
UART_TX : out std_logic; -- send data to board
BUS_RX : in CTRLBUS_RX; -- what user is sending to FPGA
BUS_TX : out CTRLBUS_TX -- what FPGA is sending to user
);
end entity;
architecture uart_uC_SensorReadout_arch of uart_uC_SensorReadout is
--UART general
signal clk_div : integer := 100000000/BAUD;
-- UART RX
signal rx_data : std_logic_vector(7 downto 0);
signal rx_ready : std_logic;
signal rx_debug : std_logic_vector(3 downto 0);
signal rx_ready_in : std_logic;
signal rx_ascii_data : std_logic_vector(7 downto 0);
signal rx_hex_data : std_logic_vector(3 downto 0);
signal rx_hex_inval : std_logic;
-- UART TX
signal tx_send : std_logic;
signal tx_ready : std_logic;
signal tx_debug : std_logic_vector(3 downto 0);
signal tx_fifo_out : std_logic_vector(8 downto 0);
signal tx_fifo_empty : std_logic;
signal tx_fifo_full : std_logic;
signal tx_fifo_read : std_logic;
signal tx_fifo_write : std_logic;
-- RX FSM
type rec_states_t is (IDLE,FamId_0,FamId_1,RegId_0,RegId_1,ROM_rec,I2C_Add_rec_0,I2C_Add_rec_1,ValType_rec,Val_rec,Finish_Rec);
signal rec_state : rec_states_t;
signal rec_data_ready : std_logic := '0';
signal rec_data_mode : std_logic_vector(1 downto 0);
signal rec_regAdd : integer;
signal rec_fam_id : std_logic_vector(7 downto 0);
signal rec_val_type : std_logic_vector(1 downto 0);
-- RX FSM
type ram_cntrl_state_t is (IDLE,CALC_ADDR,WRITE_ADDR_0,WRITE_ADDR_1,CALC_VAL_ADDR,WRITE_Val);
signal ram_cntrl_state : ram_cntrl_state_t;
signal ram_wr_addr : std_logic_vector( 9 downto 0);
signal ram_rd_addr : std_logic_vector( 9 downto 0);
signal ram_data_in : std_logic_vector(31 downto 0);
signal ram_write : std_logic;
signal ram_data_out : std_logic_vector(31 downto 0);
signal ram_regAddr_tmp : integer := 0;
signal Monitor_RAM_RE : std_logic;
signal Monitor_RAM_ready_r : std_logic;
signal Monitor_RAM_ready : std_logic;
-- Registers for Values. This will be expensive...
type data_array is array (0 to 2) of std_logic_vector(31 downto 0);
signal Data_reg : data_array;-- := (others => (others => '0'));
component RAM_pseudo_DP_wReg_32x1k is
port (
WrAddress : in std_logic_vector( 9 downto 0);
RdAddress : in std_logic_vector( 9 downto 0);
Data : in std_logic_vector(31 downto 0);
WE : in std_logic;
RdClock : in std_logic;
RdClockEn : in std_logic;
Reset : in std_logic;
WrClock : in std_logic;
WrClockEn : in std_logic;
Q : out std_logic_vector(31 downto 0)
);
end component RAM_pseudo_DP_wReg_32x1k;
begin
-- THE_TX_FIFO : entity work.fifo_9x2k_oreg
-- port map(
-- Clock => CLK,
-- Data => BUS_RX.data(8 downto 0),
-- WrEn => tx_fifo_write,
-- RdEn => tx_fifo_read,
-- Reset => RESET,
-- Q => tx_fifo_out,
-- Empty => tx_fifo_empty,
-- Full => tx_fifo_full
-- );
--
-- THE_TX : entity work.uart_trans
-- port map(
-- CLK_DIV => clk_div,
-- CLK => CLK,
-- RST => RESET,
-- DATA_IN => tx_fifo_out(7 downto 0),
-- SEND => tx_send,
-- READY => tx_ready,
-- TX => UART_TX,
-- DEBUG => tx_debug
-- );
-----------------------------------------
-- UART Receiver
-----------------------------------------
THE_RX : entity work.uart_rec
port map(
CLK_DIV => clk_div,
CLK => CLK,
RST => RESET,
RX => UART_RX, -- pass signale to sub entity (blackbox)
DATA_OUT => rx_data, -- return value
DATA_WAITING => rx_ready_in, -- return value
DEBUG => rx_debug -- return value
);
-----------------------------------------
-- ASCII to Hex (and Raw) Translater
-----------------------------------------
PROC_AsciiToHEX : process
begin
wait until rising_edge(CLK);
if rx_ready_in = '1' then
rx_hex_inval <= '0';
if (rx_data >= x"30" and rx_data <= x"39") then -- number
rx_hex_data <= rx_data(3 downto 0);
elsif (rx_data >= x"41" and rx_data <= x"46") or -- A to F
(rx_data >= x"61" and rx_data <= x"66") then -- a to f
rx_hex_data <= std_logic_vector( unsigned(rx_data(3 downto 0)) + 9);
else
rx_hex_inval <= '1';
end if;
end if;
rx_ascii_data <= rx_data;
rx_ready <= rx_ready_in;
end process;
-----------------------------------------
-- UART Receiver Parser
-----------------------------------------
PROC_RX_FSM : process
variable mode : std_logic_vector( 1 downto 0) := b"00"; -- 00: IDLE; 01: Address; 10: Value; 11:T.B.D.
variable famId : std_logic_vector( 7 downto 0) := x"00";
variable I2C_Addr : std_logic_vector( 7 downto 0) := x"00";
variable RegAddr : std_logic_vector( 7 downto 0) := x"00";
variable ROM : std_logic_vector(47 downto 0) := x"000000000000";
variable ValType : std_logic_vector( 1 downto 0) := b"00";
variable MeasValue : std_logic_vector(15 downto 0) := x"0000";
variable errorFlag : std_logic := '0';
variable cnt : integer range 0 to 12 := 0;
begin
wait until rising_edge(CLK);
rec_data_ready <= '0';
if (RESET = '1') then
rec_state <= IDLE;
mode := "00";
errorFlag := '0';
cnt := 0;
famId := x"00";
I2C_Addr := x"00";
RegAddr := x"00";
ROM := x"000000000000";
ValType := b"00";
MeasValue := x"0000";
else
case (rec_state) is
when IDLE =>
mode := "00";
errorFlag := '0';
cnt := 0;
famId := x"00";
I2C_Addr := x"00";
RegAddr := x"00";
ROM := x"000000000000";
ValType := b"00";
MeasValue := x"0000";
if (rx_ready = '1') then
if ((rx_ascii_data = x"41") or (rx_ascii_data = x"61")) then -- 'A' or 'a'
mode := "01"; -- Address receiving mode
rec_state <= FamId_0;
elsif ((rx_ascii_data = x"56") or (rx_ascii_data = x"76")) then -- 'V' or 'v'
mode := "10"; -- Value receiving mode
rec_state <= FamId_0;
else
rec_state <= IDLE;
end if;
else
rec_state <= IDLE;
end if;
when FamId_0 =>
if (rx_ready = '1') then
if (rx_ascii_data = x"0D") then
rec_state <= IDLE;
errorFlag := '1';
else
famId(7 downto 4) := rx_hex_data;
rec_state <= FamId_1;
if rx_hex_inval = '1' then -- check if hex data is correct
rec_state <= Finish_Rec;
errorFlag := '1';
end if;
end if;
end if;
when FamId_1 =>
if (rx_ready = '1') then
if (rx_ascii_data = x"0D") then
rec_state <= IDLE;
errorFlag := '1';
else
famId(3 downto 0) := rx_hex_data;
rec_state <= RegId_0;
if rx_hex_inval = '1' then -- check if hex data is correct
rec_state <= Finish_Rec;
errorFlag := '1';
end if;
end if;
end if;
when RegId_0 =>
if (rx_ready = '1') then
if (rx_ascii_data = x"0D") then
rec_state <= IDLE;
errorFlag := '1';
else
RegAddr(7 downto 4) := rx_hex_data;
rec_state <= RegId_1;
if rx_hex_inval = '1' then -- check if hex data is correct
rec_state <= Finish_Rec;
errorFlag := '1';
end if;
end if;
end if;
when RegId_1 =>
if (rx_ready = '1') then
if (rx_ascii_data = x"0D") then
rec_state <= IDLE;
errorFlag := '1';
else
RegAddr(3 downto 0) := rx_hex_data;
if (mode = "01") then -- Address receiver
cnt := 12;
rec_state <= ROM_rec;
elsif (mode = "10") then -- Value receiver
rec_state <= ValType_rec;
else -- not allowed in this state
errorFlag := '1';
end if;
if rx_hex_inval = '1' then -- check if hex data is correct
rec_state <= Finish_Rec;
errorFlag := '1';
end if;
end if;
end if;
when ROM_rec =>
if (rx_ready = '1') then
if (rx_ascii_data = x"0D") then
rec_state <= IDLE;
errorFlag := '1';
else
cnt := cnt - 1;
ROM((cnt*4+3) downto cnt*4) := rx_hex_data;
if (cnt = 0) then
rec_state <= I2C_Add_rec_0;
end if;
if rx_hex_inval = '1' then -- check if hex data is correct
rec_state <= Finish_Rec;
errorFlag := '1';
end if;
end if;
end if;
when I2C_Add_rec_0 =>
if (rx_ready = '1') then
if (rx_ascii_data = x"0D") then
rec_state <= IDLE;
errorFlag := '1';
else
I2C_Addr(7 downto 4) := rx_hex_data;
rec_state <= I2C_Add_rec_1;
if rx_hex_inval = '1' then -- check if hex data is correct
rec_state <= Finish_Rec;
errorFlag := '1';
end if;
end if;
end if;
when I2C_Add_rec_1 =>
if (rx_ready = '1') then
if (rx_ascii_data = x"0D") then
rec_state <= IDLE;
errorFlag := '1';
else
I2C_Addr(3 downto 0) := rx_hex_data;
rec_state <= Finish_Rec;
if rx_hex_inval = '1' then -- check if hex data is correct
rec_state <= Finish_Rec;
errorFlag := '1';
end if;
end if;
end if;
when ValType_rec =>
if (rx_ready = '1') then
if (rx_ascii_data = x"0D") then
rec_state <= IDLE;
errorFlag := '1';
elsif ((rx_ascii_data = x"54") or (rx_ascii_data = x"74")) then -- T or t
ValType := b"00";
cnt := 4;
rec_state <= Val_rec;
elsif ((rx_ascii_data = x"58") or (rx_ascii_data = x"78")) then -- X or x
ValType := b"01";
cnt := 4;
rec_state <= Val_rec;
elsif ((rx_ascii_data = x"59") or (rx_ascii_data = x"79")) then -- Y or y
ValType := b"10";
cnt := 4;
rec_state <= Val_rec;
elsif ((rx_ascii_data = x"5A") or (rx_ascii_data = x"7A")) then -- Z or z
ValType := b"11";
cnt := 4;
rec_state <= Val_rec;
else
rec_state <= Finish_Rec;
errorFlag := '1';
end if;
end if;
when Val_rec =>
if (rx_ready = '1') then
if (rx_ascii_data = x"0D") then
rec_state <= IDLE;
errorFlag := '1';
else
cnt := cnt - 1;
MeasValue(cnt*4+3 downto cnt*4) := rx_hex_data;
if (cnt = 0) then
rec_state <= Finish_Rec;
end if;
if rx_hex_inval = '1' then -- check if hex data is correct
rec_state <= Finish_Rec;
errorFlag := '1';
end if;
end if;
end if;
when Finish_Rec =>
if (rx_ready = '1') then
if (rx_ascii_data = x"0D") then
if errorFlag = '0' then
rec_data_ready <= '1';
rec_data_mode <= mode;
rec_regAdd <= to_integer(unsigned(RegAddr));
rec_fam_id <= famId;
rec_val_type <= ValType;
if ((famId = x"28") and (to_integer(unsigned(RegAddr)) < MAX_DS18B20)) then -- DS18B20
if (mode = "01") then
Data_reg(0) <= ROM(31 downto 0);
Data_reg(1) <= RegAddr & I2C_Addr & ROM(47 downto 32);
elsif (mode = "10") then
Data_reg(2) <= x"0000" & MeasValue;
end if;
elsif ((famId = x"19") and (to_integer(unsigned(RegAddr)) < MAX_DS28E17)) then --MLX90393 @ DS28E17
if (mode = "01") then
Data_reg(0) <= ROM(31 downto 0);
Data_reg(1) <= RegAddr & I2C_Addr & ROM(47 downto 32);
elsif (mode = "10") then
Data_reg(2) <= x"0000" & MeasValue; -- T,X,Y or Z
end if;
end if;
end if;
rec_state <= IDLE;
end if;
end if;
when others => null;
end case;
end if;
end process;
-----------------------------------------
-- RAM write Handler FSM
-----------------------------------------
PROC_RAM_CONTROL_FSM : process
begin
wait until rising_edge(CLK);
ram_write <= '0';
if (RESET = '1') then
ram_cntrl_state <= IDLE;
else
case (ram_cntrl_state) is
when IDLE =>
if rec_data_ready = '1' then
if rec_data_mode = "01" then
ram_cntrl_state <= CALC_ADDR;
elsif rec_data_mode = "10" then
ram_cntrl_state <= CALC_VAL_ADDR;
end if;
end if;
when CALC_ADDR =>
ram_cntrl_state <= WRITE_ADDR_0;
if (rec_fam_id = x"28") and (rec_regAdd < MAX_DS18B20) then
ram_regAddr_tmp <= rec_regAdd*3;
elsif (rec_fam_id = x"19") and (rec_regAdd < MAX_DS28E17) then
ram_regAddr_tmp <= rec_regAdd*6 + MAX_DS18B20*3;
else
ram_cntrl_state <= IDLE;
end if;
when WRITE_ADDR_0 =>
ram_write <= '1';
ram_cntrl_state <= WRITE_ADDR_1;
ram_wr_addr <= std_logic_vector(to_unsigned(ram_regAddr_tmp,10));
ram_data_in <= Data_reg(0);
ram_regAddr_tmp <= ram_regAddr_tmp + 1;
when WRITE_ADDR_1 =>
ram_write <= '1';
ram_cntrl_state <= IDLE;
ram_wr_addr <= std_logic_vector(to_unsigned(ram_regAddr_tmp,10));
ram_data_in <= Data_reg(1);
when CALC_VAL_ADDR =>
ram_cntrl_state <= WRITE_Val;
if rec_fam_id = x"28" and (rec_regAdd < MAX_DS18B20) then
ram_regAddr_tmp <= rec_regAdd*3+2;
elsif rec_fam_id = x"19" and (rec_regAdd < MAX_DS28E17) then
if rec_val_type = "00" then --T
ram_regAddr_tmp <= rec_regAdd*6+2 + MAX_DS18B20*3;
elsif rec_val_type = "01" then --X
ram_regAddr_tmp <= rec_regAdd*6+3 + MAX_DS18B20*3;
elsif rec_val_type = "10" then --Y
ram_regAddr_tmp <= rec_regAdd*6+4 + MAX_DS18B20*3;
elsif rec_val_type = "11" then --Z
ram_regAddr_tmp <= rec_regAdd*6+5 + MAX_DS18B20*3;
end if;
else
ram_cntrl_state <= IDLE;
end if;
when WRITE_Val =>
ram_write <= '1';
ram_wr_addr <= std_logic_vector(to_unsigned(ram_regAddr_tmp,10));
ram_data_in <= Data_reg(2);
ram_cntrl_state <= IDLE;
when others => null;
end case;
end if;
end process;
THE_DATA_RAM : RAM_pseudo_DP_wReg_32x1k
port map (
WrAddress => ram_wr_addr,
RdAddress => ram_rd_addr,
Data => ram_data_in,
WE => ram_write,
RdClock => CLK,
RdClockEn => '1',
Reset => RESET,
WrClock => CLK,
WrClockEn => '1',
Q => ram_data_out
);
Monitor_RAM_ready_r <= Monitor_RAM_RE when rising_edge(CLK);
Monitor_RAM_ready <= Monitor_RAM_ready_r when rising_edge(CLK);
-----------------------------------------
-- BUS Handler
-----------------------------------------
PROC_REGS : process
variable addr : integer := 0;
constant MAX_SIZE : integer := (MAX_DS18B20*3+MAX_DS28E17*6);
begin
wait until rising_edge(CLK);
BUS_TX.unknown <= '0';
BUS_TX.ack <= '0';
BUS_TX.nack <= '0';
BUS_TX.data <= (others => '0');
Monitor_RAM_RE <= '0';
if BUS_RX.write = '1' then
BUS_TX.unknown <= '1';
elsif BUS_RX.read = '1' then
addr := to_integer(unsigned(BUS_RX.addr(9 downto 0)));
if addr = 0 then
BUS_TX.data <= std_logic_vector(to_unsigned(MAX_DS28E17,16)) & std_logic_vector(to_unsigned(MAX_DS18B20,16));
BUS_TX.ack <= '1';
elsif (addr <= MAX_SIZE) then
--BUS_TX.data <= ram_data_out;
--BUS_TX.ack <= Monitor_RAM_ready;
ram_rd_addr <= std_logic_vector(to_unsigned(addr-1,10)); -- ram starts at address 0, bus at 1
Monitor_RAM_RE <= '1';
BUS_TX.ack <= '0';
else
BUS_TX.ack <= '0';
BUS_TX.unknown <= '1';
end if;
elsif (Monitor_RAM_ready = '1') then
BUS_TX.data <= ram_data_out;
BUS_TX.ack <= '1';
end if;
end process;
end architecture;
<?xml version="1.0" encoding="UTF-8"?>
<DiamondModule name="RAM_pseudo_DP_wReg_32x1k" module="RAM_DP" VendorName="Lattice Semiconductor Corporation" generator="IPexpress" date="2021 02 23 16:18:22.926" version="6.5" type="Module" synthesis="synplify" source_format="VHDL">
<Package>
<File name="" type="mem" modified="2021 02 23 16:18:22.000"/>
<File name="RAM_pseudo_DP_wReg_32x1k.lpc" type="lpc" modified="2021 02 23 16:18:20.000"/>
<File name="RAM_pseudo_DP_wReg_32x1k.vhd" type="top_level_vhdl" modified="2021 02 23 16:18:20.000"/>
<File name="RAM_pseudo_DP_wReg_32x1k_tmpl.vhd" type="template_vhdl" modified="2021 02 23 16:18:20.000"/>
<File name="tb_RAM_pseudo_DP_wReg_32x1k_tmpl.vhd" type="testbench_vhdl" modified="2021 02 23 16:18:20.000"/>
</Package>
</DiamondModule>
[Device]
Family=ecp5um
PartType=LFE5UM-85F
PartName=LFE5UM-85F-8BG756C
SpeedGrade=8
Package=CABGA756
OperatingCondition=COM
Status=P
[IP]
VendorName=Lattice Semiconductor Corporation
CoreType=LPM
CoreStatus=Demo
CoreName=RAM_DP
CoreRevision=6.5
ModuleName=RAM_pseudo_DP_wReg_32x1k
SourceFormat=VHDL
ParameterFileVersion=1.0
Date=02/23/2021
Time=16:18:20
[Parameters]
Verilog=0
VHDL=1
EDIF=1
Destination=Synplicity
Expression=BusA(0 to 7)
Order=Big Endian [MSB:LSB]
IO=0
RAddress=1024
RData=32
WAddress=1024