LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; USE IEEE.STD_LOGIC_ARITH.all; USE IEEE.STD_LOGIC_UNSIGNED.all; -- assumed in all the examples! ----------------------------------------------- --dcsboard srg design full version 5 --based on a central state machine -- -->supports 9 ports write, 9 ports read (multiplexed) -->software switchable hamming -->security timeout from 0 to 104 sec -- (can be disabled for debugging) --10,31,2006 Jens Steckert --hamming is activated by default --ch 0..8 at address 0..8 --extended status display ----------------------------------------------- --Entity ----------------------------------------------- entity scomm5 is --connections to the outside world port ( --input writedata : in std_logic_vector(31 downto 0); clk : in std_logic; rst_n : in std_logic; write_n : in std_logic; --write control, takes data only when negative... --controlled by avalon bus... read_n : in std_logic; --read control signal from the avalon bus address : in std_logic_vector(3 downto 0);--receives adress for mux SERIAL_IN : in std_logic_vector(8 downto 0); readdata : out std_logic_vector(31 downto 0); --received data state_display : out std_logic_vector(3 downto 0); --output SERIAL_OUT : out std_logic_vector(8 downto 0); --9 output channels status_error : out std_logic_vector(8 downto 0); status_active : out std_logic_vector(8 downto 0); timeout_display: out std_logic; STROBE : out std_logic ; --common strobe clkout : out std_logic --common serial clock ); end scomm5; -------------------------------------------------------------- --Architecture -------------------------------------------------------------- architecture a of scomm5 is --shiftregister parin serial out component shreg_parin is generic(N : Integer := 24); port( rst_n : in std_logic; PARIN : in std_logic_vector(N downto 1); CLK : in std_logic; --VALID : in std_logic; EN : in std_logic; SDOUT : out std_logic; SSTR : out std_logic; sclk : out std_logic ); end component; --shift register with serial in / parallel out component shreg2 is generic(N : Integer := 24); port( rst_n : in std_logic; SCLK : in std_logic; SDIN : in std_logic; EN : in std_logic; SSTR : in std_logic; SDOUT : out std_logic; PAROUT : out std_logic_vector(N downto 1) ); end component; --generates the active/error status bits for every channel component status is port( hamming : out std_logic_vector(1 downto 0); pdcv2 : in std_logic; data_ch1 : in std_logic_vector(38 downto 0); data_ch2 : in std_logic_vector(38 downto 0); data_ch3 : in std_logic_vector(38 downto 0); data_ch4 : in std_logic_vector(38 downto 0); data_ch5 : in std_logic_vector(38 downto 0); data_ch6 : in std_logic_vector(38 downto 0); data_ch7 : in std_logic_vector(38 downto 0); data_ch8 : in std_logic_vector(38 downto 0); data_ch9 : in std_logic_vector(38 downto 0); reset_n : in std_logic; clk : in std_logic; str : in std_logic; EN : in std_logic; serial_in : in std_logic_vector(8 downto 0); blink : out std_logic; s_error : out std_logic_vector(8 downto 0); s_active : out std_logic_vector(8 downto 0); s_connected : out std_logic_vector(8 downto 0); d_active : out std_logic_vector(8 downto 0); d_error : out std_logic_vector(8 downto 0) --status_debug :out std_logic_vector(31 downto 0) ); end component; --timeout component timeout is port( --clock input clk_in : in std_logic; refresh : in std_logic; timeval : in std_logic_vector(15 downto 0); EN : in std_logic; --clock output expired : out std_logic ); end component; --hamming encoder component hamming_enc_dmem is port ( din : in std_logic_vector (31 downto 0); -- data from the device dout : out std_logic_vector (38 downto 0) -- data to instr. memory ); end component; --hamming decoder component hamming_dec_dmem is port ( din : in std_logic_vector (38 downto 0); -- data from data memory dout : out std_logic_vector (31 downto 0); -- data to CPU state : out std_logic_vector ( 1 downto 0) ); end component; --clock divider component fdiv is port( rst_n : in std_logic; clk_in : in std_logic; clk_out : out std_logic; en_out : out std_logic; pulse_out : out std_logic ); end component; --global clock buffer for the 10kHz main clock signal component global is port(a_in : in std_logic; a_out : out std_logic ); end component; ----------------------- --signal definitions... ----------------------- signal serout : std_logic_vector(8 downto 0);--serial data for 1 ch ----------------------------------------------------------------------------- --clocks signal clk20 : std_logic:= '0'; --internal clock, after global buffer signal clk_i2hz : std_logic; signal strobe_i : std_logic_vector(8 downto 0); --common strobe signal strobe_del : std_logic; signal en10k : std_logic; --10kHz enable for all entities signal en10k_switch : std_logic; --muxed en10k for compatibility with pdcv2 --------------------------------------------------------------------------------- --Buffers for data signal readbuffer : std_logic_vector(38 downto 0); --buffers data from serial input register signal writeoutbuffer : std_logic_vector(38 downto 0); --contains hamming encoded data signal muxbuffer: std_logic_vector(38 downto 0); --contains the data to send signal decreadbuffer :std_logic_vector(31 downto 0); --buffers data from input hamming decoder signal debugbuffer : std_logic_vector(15 downto 0); signal readdatabuffer : std_logic_vector(31 downto 0); signal optionbuffer :std_logic_vector(31 downto 0); --buffers the option string signal timebuffer : std_logic_vector(15 downto 0); --the time value type data_array is array (0 to 8) of std_logic_vector(38 downto 0); signal wdata_array : data_array; -------------------------------------------------------------------------------------------- --status registers signal status_register : std_logic_vector(31 downto 0); --holds the status bits from the status entity signal status_active_i : std_logic_vector(8 downto 0); signal status_error_i : std_logic_vector( 8 downto 0); signal status_connected_i : std_logic_vector( 8 downto 0); signal d_active_i : std_logic_vector(8 downto 0); signal d_error_i : std_logic_vector(8 downto 0); --------------------------------------------------------------------------------------- --address logic signal validreadaddress : std_logic_vector(3 downto 0); signal reqreadaddress : std_logic_vector(3 downto 0); signal readaddress : std_logic_vector(3 downto 0); signal activechannel : std_logic_vector(3 downto 0); -------------------------------------------------------------------------------------------- --avalon io buffers signal addressbuffer : std_logic_vector(3 downto 0); --buffers the address signal addressbuffer2 : std_logic_vector(3 downto 0); --buffers the address signal sentdata, gotdata :std_logic; signal sentdata2, gotdata2 :std_logic; signal write_i,read_i : std_logic; signal write_i2,read_i2 : std_logic; signal inputbuffer :std_logic_vector(31 downto 0); signal inputbuffer2 :std_logic_vector(31 downto 0); ----------------------------------------------------------------------------------------------- --global flags signal reset_i : std_logic; --internal reset signal expired_i :std_logic; --interal timer expired, flushes registers signal refresh_i :std_logic; --refreshs the timer signal errorflag : std_logic; signal serial_in_i :std_logic; CONSTANT ch1 : std_logic_vector(3 DOWNTO 0) := "0000"; --0 CONSTANT ch2 : std_logic_vector(3 DOWNTO 0) := "0001"; --1 CONSTANT ch3 : std_logic_vector(3 DOWNTO 0) := "0010"; --2 CONSTANT ch4 : std_logic_vector(3 DOWNTO 0) := "0011"; --3 CONSTANT ch5 : std_logic_vector(3 DOWNTO 0) := "0100"; --4 CONSTANT ch6 : std_logic_vector(3 DOWNTO 0) := "0101"; --5 CONSTANT ch7 : std_logic_vector(3 DOWNTO 0) := "0110"; --6 CONSTANT ch8 : std_logic_vector(3 DOWNTO 0) := "0111"; --7 CONSTANT ch9 : std_logic_vector(3 DOWNTO 0) := "1000"; --8 CONSTANT version : std_logic_vector(3 DOWNTO 0) := "1001"; --9 CONSTANT status_adr : std_logic_vector(3 DOWNTO 0) := "1010"; --a CONSTANT debug : std_logic_vector(3 DOWNTO 0) := "1011"; --b CONSTANT vaddress : std_logic_vector(3 DOWNTO 0) := "1100"; --c CONSTANT cleartimeout : std_logic_vector(3 DOWNTO 0) := "1101"; --d CONSTANT option : std_logic_vector(3 DOWNTO 0) := "1110"; --e CONSTANT settime : std_logic_vector(3 DOWNTO 0) := "1111"; --f signal stat: std_logic_vector(3 downto 0); constant idle : std_logic_vector(3 downto 0) := "0000"; constant wdec : std_logic_vector(3 downto 0) := "0001"; constant rdec : std_logic_vector(3 downto 0) := "0010"; constant sendread : std_logic_vector(3 downto 0) := "0011"; constant reqread : std_logic_vector(3 downto 0) := "0100"; constant sop : std_logic_vector(3 downto 0) := "0101"; constant stime : std_logic_vector(3 downto 0) := "0110"; constant writemux : std_logic_vector(3 downto 0) := "0111"; constant writereg : std_logic_vector(3 downto 0) := "1000"; constant writehamm : std_logic_vector(3 downto 0) := "1001"; constant error : std_logic_vector(3 downto 0) := "1010"; constant refresh : std_logic_vector(3 downto 0) := "1011"; constant refoff : std_logic_vector(3 downto 0) := "1100"; ---------------------------------------------------- --portmapping and connecting the logical blocks ---------------------------------------------------- begin --gets the input signals and puts it into the buffer --registers inputproc: process(clk, reset_i) begin if reset_i = '0' then write_i <= '0'; read_i <= '0'; --stat <= idle; addressbuffer <= (others => '0'); -- VA - wird unten zugewiesen, wenn hier fehlt,dann wird mehr für die clock_enables verbraucht. inputbuffer <= (others => '0'); elsif clk'event and clk ='1' then --rising clock edge if write_n = '0' then addressbuffer <= address; inputbuffer <= writedata; write_i <= '1'; read_i <= '0'; elsif read_n = '0' then read_i <= '1'; write_i <= '0'; addressbuffer <= address; else if gotdata2 = '1' then write_i <= '0'; end if; if sentdata2 ='1'then read_i <= '0'; end if; end if; end if; end process; cdcross: process(clk20, reset_i) begin if reset_i = '0' then readdata <= (others => '0'); addressbuffer2 <= (others => '0'); inputbuffer2 <= (others => '0'); gotdata2 <= '0'; sentdata2 <= '0'; write_i2 <= '0'; read_i2 <= '0'; elsif clk20'event and clk20 ='1' then if en10k = '1' then write_i2 <= write_i; read_i2 <= read_i; readdata <= readdatabuffer; addressbuffer2 <= addressbuffer; inputbuffer2 <= inputbuffer; gotdata2 <= gotdata; sentdata2 <= sentdata; end if; end if; end process; fsm: process(clk20, reset_i) begin if reset_i = '0' then stat <= idle; gotdata <= '0'; sentdata <= '0'; for i in 0 to 8 loop wdata_array(i) <= (others => '0'); end loop; elsif clk20'event and clk20 ='1' then if en10k = '1' then case stat is when idle => if write_i2 = '1' then stat <= wdec; gotdata <= '1'; elsif read_i2 = '1' then stat <= rdec; sentdata <= '1'; else gotdata <= '0'; sentdata <= '0'; stat <= idle; end if; if expired_i = '1' then status_register(30) <= '1'; for i in 0 to 8 loop wdata_array(i) <= (others => '0'); end loop; end if; when wdec => case addressbuffer2 is when option => stat <= sop; when settime => stat <= stime; when ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8 | ch9 => -- VA: mehrere cases auf einem Schlag, besser lesbar activechannel <= addressbuffer2; stat <= writemux; when cleartimeout => status_register(30) <= '0'; stat <= refresh; when others => stat <= idle; end case; when writemux => if optionbuffer(3 downto 0) = "0000" then stat <= writehamm; elsif optionbuffer(3 downto 0) = "1111" then muxbuffer <= "0000000" & inputbuffer2(31 downto 0); stat <= writereg; else stat <= idle; end if; when writehamm => muxbuffer <= writeoutbuffer; stat <= writereg; when writereg => CASE addressbuffer2 IS WHEN ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8 | ch9=> -- VA wdata_array(CONV_INTEGER(addressbuffer2)) <= muxbuffer; stat <= refresh; --dummy command WHEN OTHERS => stat <= error; END CASE; when rdec => case addressbuffer2 is --address decoder, the addresses are defined as constants above.. WHEN ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8 | ch9=> -- VA If addressbuffer2 = validreadaddress then stat <= sendread; else reqreadaddress <= addressbuffer2; stat <= reqread; end if; when option => readdatabuffer <= optionbuffer(31 downto 0); stat <= refresh; --if timer is expired first bit of timebuffer is set WHEN settime => readdatabuffer <= x"0000" & timebuffer(15 downto 0); stat <= refresh; when debug => readdatabuffer <= x"0000" & debugbuffer; --b stat <= refresh; --when status_adr =>readdatabuffer <= status_register; --a when status_adr =>readdatabuffer <= status_register;--a stat <= refresh; when version => readdatabuffer <= x"00000037"; stat <= refresh; when vaddress => readdatabuffer <= x"0000000" & validreadaddress; stat <= refresh; when others => readdatabuffer <= writedata(31 downto 0); stat <= idle; end case; when reqread => readdatabuffer <= x"F000000F"; stat <= refresh; -- when sendread => if optionbuffer(3 downto 0) = "0000" then readdatabuffer <= decreadbuffer(31 downto 0); else readdatabuffer <= readbuffer(31 downto 0); --invreadbuffer end if; stat <= refresh; when sop => optionbuffer <= inputbuffer2; stat <= refresh; when stime => timebuffer <= inputbuffer2(15 downto 0); if timebuffer = x"0000" then status_register(30) <= '0'; else status_register(30) <= '1'; end if; stat <= refresh; when refresh => refresh_i <= '1'; stat <= refoff; when refoff => refresh_i <= '0'; stat <= idle; when error => errorflag <= '1'; stat <=idle; when others => stat <= idle; end case; end if; end if; end process; --put those signals out of process... reset_i <= rst_n; ----------------------------------------------------------- --not en10k is used as global output clock for the pdc's clkout <= en10k ; --inverting clock out to avoid glitches --invreadbuffer <= not readbuffer; serial_out <= serout; strobe <= strobe_i(1); status_error <= d_error_i; status_active <= d_active_i; state_display <= stat; --status_debug_i <= invreadbuffer(31 downto 0); status_register(31) <= expired_i; status_register(26 downto 18) <= status_error_i; status_register(17 downto 9) <= status_active_i; status_register(8 downto 0) <= status_connected_i; timeout_display <= expired_i and clk_i2hz ; --switches between normal and inverted enable according to option register --inverted enable is required if old pdb is used by default non invered --enable is used --clk_switch <= clk20 when optionbuffer(4)= '0' else clk20_n; en10k_switch <= en10k when optionbuffer(4) = '0' else not en10k; debugbuffer(4) <= optionbuffer(4); readenable: process(clk20, strobe_i(1)) begin if strobe_i(1)= '1' then if clk20'event and clk20 ='1' then if en10k = '1' then if readaddress = reqreadaddress then validreadaddress <= readaddress; else validreadaddress <= "1111"; readaddress <= reqreadaddress; end if; end if; end if; end if; end process; --strobedelay: process(clk20) --begin -- if clk20'event and clk20 = '1' then -- strobe_del <= strobe_i(1); -- end if; --end process; with readaddress(3 downto 0) select serial_in_i <= not SERIAL_IN(0) when ch1, not SERIAL_IN(1) when ch2, not SERIAL_IN(2) when ch3, not SERIAL_IN(3) when ch4, not SERIAL_IN(4) when ch5, not SERIAL_IN(5) when ch6, not SERIAL_IN(6) when ch7, not SERIAL_IN(7) when ch8, not SERIAL_IN(8) when ch9, '0' when others; -------------------------------port maps...<------------------- --------------------------------------------------------- --generates 9 shift registers of type shreg_parin --------------------------------------------------------- multishift: for i in 0 to 8 generate --sender mpsreg: shreg_parin generic map(N => 39) port map( rst_n => reset_i, parin => wdata_array(i), clk => clk20, EN => en10k, sstr => strobe_i(i), sdout => serout(i) ); end generate; --receiver sreg: shreg2 generic map(n => 39) port map( rst_n => reset_i, SCLK => clk20, EN => en10k_switch, -- SCLK => clk_switch, SDIN => SERIAL_IN_i, SSTR => strobe_i(1), --SSTR => strobe_del, Parout => readbuffer ); --status bit generator sstatus: status port map( hamming => debugbuffer(7 downto 6), data_ch1 => wdata_array(0), data_ch2 => wdata_array(1), data_ch3 => wdata_array(2), data_ch4 => wdata_array(3), data_ch5 => wdata_array(4), data_ch6 => wdata_array(5), data_ch7 => wdata_array(6), data_ch8 => wdata_array(7), data_ch9 => wdata_array(8), pdcv2 => optionbuffer(4), clk => clk20, ---changed this signal for v19 str => strobe_i(0), serial_in => serial_in(8 downto 0), blink => clk_i2hz, EN => en10k, reset_n => reset_i, s_error => status_error_i, s_active => status_active_i, s_connected => status_connected_i, d_error => d_error_i, d_active => d_active_i ); --clock divider fdiv40: fdiv port map( rst_n => reset_i, clk_in =>clk, --fast clock from avalon bus... clk_out => clk20, --slow clock for srg en_out => en10k ); --hamming encoder hammigenc: hamming_enc_dmem port map( din => inputbuffer2, dout => writeoutbuffer ); --hamming decoder hammingdec: hamming_dec_dmem port map( din => readbuffer, --invreadbuffer dout => decreadbuffer, state => debugbuffer(1 downto 0) ); --timeoutwatchdog watchdog: timeout port map( clk_in => clk20, refresh => refresh_i, timeval => timebuffer, EN => en10k, expired => expired_i ); end;