From 974f0707def69428579ee4b9d21bf3a920de8938 Mon Sep 17 00:00:00 2001 From: oharboe Date: Mon, 8 Sep 2008 15:05:26 +0000 Subject: 2008-09-08 Salvador Eduardo Tropea * zpu/hdl/zealot: a complete ZPU implementation cleaned up and with a UART. --- zpu/hdl/zealot/devices/br_gen.vhdl | 91 ++++++ zpu/hdl/zealot/devices/phi_io.vhdl | 209 ++++++++++++++ zpu/hdl/zealot/devices/rx_unit.vhdl | 108 +++++++ zpu/hdl/zealot/devices/timer.vhdl | 91 ++++++ zpu/hdl/zealot/devices/trace.vhdl | 258 +++++++++++++++++ zpu/hdl/zealot/devices/tx_unit.vhdl | 109 +++++++ zpu/hdl/zealot/devices/txt_util.vhdl | 541 +++++++++++++++++++++++++++++++++++ 7 files changed, 1407 insertions(+) create mode 100644 zpu/hdl/zealot/devices/br_gen.vhdl create mode 100644 zpu/hdl/zealot/devices/phi_io.vhdl create mode 100644 zpu/hdl/zealot/devices/rx_unit.vhdl create mode 100644 zpu/hdl/zealot/devices/timer.vhdl create mode 100644 zpu/hdl/zealot/devices/trace.vhdl create mode 100644 zpu/hdl/zealot/devices/tx_unit.vhdl create mode 100644 zpu/hdl/zealot/devices/txt_util.vhdl (limited to 'zpu/hdl/zealot/devices') diff --git a/zpu/hdl/zealot/devices/br_gen.vhdl b/zpu/hdl/zealot/devices/br_gen.vhdl new file mode 100644 index 0000000..d14440e --- /dev/null +++ b/zpu/hdl/zealot/devices/br_gen.vhdl @@ -0,0 +1,91 @@ +------------------------------------------------------------------------------ +---- ---- +---- RS-232 baudrate generator ---- +---- ---- +---- http://www.opencores.org/ ---- +---- ---- +---- Description: ---- +---- This counter is a parametrizable clock divider. The count value is ---- +---- the generic parameter COUNT. It has a chip enable ce_i input. ---- +---- (will count only if CE is high). ---- +---- When it overflows, will emit a pulse on o_o. ---- +---- ---- +---- To Do: ---- +---- - ---- +---- ---- +---- Author: ---- +---- - Philippe Carton, philippe.carton2 libertysurf.fr ---- +---- - Juan Pablo Daniel Borgna, jpdborgna gmail.com ---- +---- - Salvador E. Tropea, salvador inti.gob.ar ---- +---- ---- +------------------------------------------------------------------------------ +---- ---- +---- Copyright (c) 2001-2003 Philippe Carton ---- +---- Copyright (c) 2005 Juan Pablo Daniel Borgna ---- +---- Copyright (c) 2005-2008 Salvador E. Tropea ---- +---- Copyright (c) 2005-2008 Instituto Nacional de Tecnología Industrial ---- +---- ---- +---- Distributed under the GPL license ---- +---- ---- +------------------------------------------------------------------------------ +---- ---- +---- Design unit: BRGen(Behaviour) (Entity and architecture) ---- +---- File name: br_gen.vhdl ---- +---- Note: None ---- +---- Limitations: None known ---- +---- Errors: None known ---- +---- Library: zpu ---- +---- Dependencies: IEEE.std_logic_1164 ---- +---- Target FPGA: Spartan ---- +---- Language: VHDL ---- +---- Wishbone: No ---- +---- Synthesis tools: Xilinx Release 9.2.03i - xst J.39 ---- +---- Simulation tools: GHDL [Sokcho edition] (0.2x) ---- +---- Text editor: SETEdit 0.5.x ---- +---- ---- +------------------------------------------------------------------------------ + +library IEEE; +use IEEE.std_logic_1164.all; + +entity BRGen is + generic( + COUNT : integer range 0 to 65535);-- Count revolution + port ( + clk_i : in std_logic; -- Clock + reset_i : in std_logic; -- Reset input + ce_i : in std_logic; -- Chip Enable + o_o : out std_logic); -- Output +end entity BRGen; + +architecture Behaviour of BRGen is + +begin + CountGen: + if COUNT/=1 generate + Counter: + process (clk_i) + variable cnt : integer range 0 to COUNT-1; + begin + if rising_edge(clk_i) then + o_o <= '0'; + if reset_i='1' then + cnt:=COUNT-1; + elsif ce_i='1' then + if cnt=0 then + o_o <= '1'; + cnt:=COUNT-1; + else + cnt:=cnt-1; + end if; -- cnt/=0 + end if; -- ce_i='1' + end if; -- rising_edge(clk_i) + end process Counter; + end generate CountGen; + + CountWire: + if COUNT=1 generate + o_o <= '0' when reset_i='1' else ce_i; + end generate CountWire; +end architecture Behaviour; -- Entity: BRGen + diff --git a/zpu/hdl/zealot/devices/phi_io.vhdl b/zpu/hdl/zealot/devices/phi_io.vhdl new file mode 100644 index 0000000..267ff54 --- /dev/null +++ b/zpu/hdl/zealot/devices/phi_io.vhdl @@ -0,0 +1,209 @@ +------------------------------------------------------------------------------ +---- ---- +---- ZPU Phi I/O ---- +---- ---- +---- http://www.opencores.org/ ---- +---- ---- +---- Description: ---- +---- ZPU is a 32 bits small stack cpu. This is the minimum I/O devices ---- +---- assumed by the libc. They are a timer and an UART.@p ---- +---- Important! this is currently a simulation only model, no UART ---- +---- provided and it unconditionally generates a log. ---- +---- Important! not all peripherals implemented! ---- +---- Important! The enable signals assumes this is mapped @ 0x80A00xx. ---- +---- ---- +---- To Do: ---- +---- - ---- +---- ---- +---- Author: ---- +---- - Øyvind Harboe, oyvind.harboe zylin.com ---- +---- - Salvador E. Tropea, salvador inti.gob.ar ---- +---- ---- +------------------------------------------------------------------------------ +---- ---- +---- Copyright (c) 2008 Øyvind Harboe ---- +---- Copyright (c) 2008 Salvador E. Tropea ---- +---- Copyright (c) 2008 Instituto Nacional de Tecnología Industrial ---- +---- ---- +---- Distributed under the BSD license ---- +---- ---- +------------------------------------------------------------------------------ +---- ---- +---- Design unit: ZPUPhiIO(Behave) (Entity and architecture) ---- +---- File name: phi_io.vhdl ---- +---- Note: None ---- +---- Limitations: Only for simulation. ---- +---- Errors: None known ---- +---- Library: zpu ---- +---- Dependencies: IEEE.std_logic_1164 ---- +---- IEEE.numeric_std ---- +---- std.textio ---- +---- zpu.zpupkg ---- +---- zpu.txt_util ---- +---- Target FPGA: Spartan 3 (XC3S1500-4-FG456) ---- +---- Language: VHDL ---- +---- Wishbone: No ---- +---- Synthesis tools: N/A ---- +---- Simulation tools: GHDL [Sokcho edition] (0.2x) ---- +---- Text editor: SETEdit 0.5.x ---- +---- ---- +------------------------------------------------------------------------------ + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use std.textio.all; + +library zpu; +use zpu.zpupkg.all; +use zpu.UART.all; +use zpu.txt_util.all; + +entity ZPUPhiIO is + generic( + BRDIVISOR : positive:=1; -- Baud rate divisor i.e. br_clk/9600/4 + ENA_LOG : boolean:=true; -- Enable log + LOG_FILE : string:="log.txt"); -- Name for the log file + port( + clk_i : in std_logic; -- System Clock + reset_i : in std_logic; -- Synchronous Reset + busy_o : out std_logic; -- I/O is busy + we_i : in std_logic; -- Write Enable + re_i : in std_logic; -- Read Enable + data_i : in unsigned(31 downto 0); + data_o : out unsigned(31 downto 0); + addr_i : in unsigned(2 downto 0); -- Address bits 4-2 + rs232_rx_i : in std_logic; -- UART Rx input + rs232_tx_o : out std_logic; -- UART Tx output + br_clk_i : in std_logic); -- UART base clock (enable) +end entity ZPUPhiIO; + + +architecture Behave of ZPUPhiIO is + constant LOW_BITS : unsigned(1 downto 0):=(others=>'0'); + constant TX_FULL : std_logic:='0'; + constant RX_EMPTY : std_logic:='1'; + + -- "000" 0x00 is CPU enable ... useful? + -- "001" 0x04 Unused + -- "010" 0x08 Unused + constant UART_TX : unsigned(2 downto 0):="011"; -- 0x0C + constant UART_RX : unsigned(2 downto 0):="100"; -- 0x10 + constant CNT_1 : unsigned(2 downto 0):="101"; -- 0x14 + constant CNT_2 : unsigned(2 downto 0):="110"; -- 0x18 + -- "111" 0x1C Unused + -- Unimplemented: Interrupt control and timer (not counter ...?) + + signal timer_read : unsigned(31 downto 0); + signal timer_we : std_logic; + signal is_timer : std_logic; + + -- UART + -- Rx + signal rx_br : std_logic; -- Rx timing + signal uart_read : std_logic; -- ZPU read the value + signal rx_avail : std_logic; -- Rx data available + signal rx_data : std_logic_vector(7 downto 0); -- Rx data + -- Tx + signal tx_br : std_logic; -- Tx timing + signal uart_write : std_logic; -- ZPU is writing + signal tx_busy : std_logic; -- Tx can't get a new value + + file l_file : text open write_mode is LOG_FILE; +begin + ----------- + -- Timer -- + ----------- + timerinst: Timer + port map( + clk_i => clk_i, reset_i => reset_i, we_i => timer_we, + data_i => data_i, addr_i => addr_i(1 downto 1), + data_o => timer_read); + + busy_o <= we_i or re_i; + is_timer <= '1' when addr_i=CNT_1 or addr_i=CNT_2 else '0'; -- 0x80A0014/8 + timer_we <= we_i and is_timer; + + ---------- + -- UART -- + ---------- + -- Rx section + rx_core : RxUnit + port map( + clk_i => clk_i, reset_i => reset_i, enable_i => rx_br, + read_i => uart_read, rxd_i => rs232_rx_i, rxav_o => rx_avail, + datao_o => rx_data); + uart_read <= '1' when re_i='1' and addr_i=UART_RX else '0'; + + -- Tx section + tx_core : TxUnit + port map( + clk_i => clk_i, reset_i => reset_i, enable_i => tx_br, + load_i => uart_write, txd_o => rs232_tx_o, busy_o => tx_busy, + datai_i => std_logic_vector(data_i(7 downto 0))); + uart_write <= '1' when we_i='1' and addr_i=UART_TX else '0'; + + -- Rx timing + rx_timer : BRGen + generic map(COUNT => BRDIVISOR) + port map( + clk_i => clk_i, reset_i => reset_i, ce_i => br_clk_i, o_o => rx_br); + + -- Tx timing + tx_timer : BRGen -- 4 Divider for Tx + generic map(COUNT => 4) + port map( + clk_i => clk_i, reset_i => reset_i, ce_i => rx_br, o_o => tx_br); + + do_io: + process(clk_i) + begin + if rising_edge(clk_i) then + if reset_i/='1' then + --synopsys translate off + if we_i='1' then + if addr_i=UART_TX and ENA_LOG then -- 0x80a000c + -- Write to UART + print("- Write to UART Tx: 0x" &hstr(data_i)&" ("& + character'val(to_integer(data_i) mod 256)&")"); + if to_integer(data_i)<256 then + print(l_file,character'val(to_integer(data_i))); + end if; + elsif is_timer='1' and ENA_LOG then + print("- Write to TIMER: 0x"&hstr(data_i)); + else + --print(l_file,character'val(to_integer(data_i))); + report "Illegal IO data_i=0x"&hstr(data_i)&" @0x"& + hstr(x"80a00"&"000"&addr_i&"00") severity warning; + end if; + end if; + --synopsys translate on + data_o <= (others => '0'); + if re_i='1' then + if addr_i=UART_TX then + if ENA_LOG then + print("- Read UART Tx"); + end if; + data_o(8) <= not(tx_busy); -- output fifo not full + elsif addr_i=UART_RX then + if ENA_LOG then + print("- Read UART Rx"); + end if; + data_o(8) <= rx_avail; -- receiver not empty + data_o(7 downto 0) <= unsigned(rx_data); + elsif is_timer='1' then + if ENA_LOG then + print("- Read TIMER: 0x"&hstr(timer_read)); + end if; + data_o <= timer_read; + else + report "Illegal IO data_o @0x"& + hstr(x"80a00"&"000"&addr_i&"00") severity warning; + end if; + end if; -- re_i='1' + end if; -- reset_i/='1' + end if; -- rising_edge(clk_i) + end process do_io; +end Behave; + diff --git a/zpu/hdl/zealot/devices/rx_unit.vhdl b/zpu/hdl/zealot/devices/rx_unit.vhdl new file mode 100644 index 0000000..e9b3251 --- /dev/null +++ b/zpu/hdl/zealot/devices/rx_unit.vhdl @@ -0,0 +1,108 @@ +------------------------------------------------------------------------------ +---- ---- +---- RS-232 simple Rx module ---- +---- ---- +---- http://www.opencores.org/ ---- +---- ---- +---- Description: ---- +---- Implements a simple 8N1 rx module for RS-232. ---- +---- ---- +---- To Do: ---- +---- - ---- +---- ---- +---- Author: ---- +---- - Philippe Carton, philippe.carton2 libertysurf.fr ---- +---- - Juan Pablo Daniel Borgna, jpdborgna gmail.com ---- +---- - Salvador E. Tropea, salvador inti.gob.ar ---- +---- ---- +------------------------------------------------------------------------------ +---- ---- +---- Copyright (c) 2001-2003 Philippe Carton ---- +---- Copyright (c) 2005 Juan Pablo Daniel Borgna ---- +---- Copyright (c) 2005-2008 Salvador E. Tropea ---- +---- Copyright (c) 2005-2008 Instituto Nacional de Tecnología Industrial ---- +---- ---- +---- Distributed under the GPL license ---- +---- ---- +------------------------------------------------------------------------------ +---- ---- +---- Design unit: RxUnit(Behaviour) (Entity and architecture) ---- +---- File name: rx_unit.vhdl ---- +---- Note: None ---- +---- Limitations: None known ---- +---- Errors: None known ---- +---- Library: zpu ---- +---- Dependencies: IEEE.std_logic_1164 ---- +---- Target FPGA: Spartan ---- +---- Language: VHDL ---- +---- Wishbone: No ---- +---- Synthesis tools: Xilinx Release 9.2.03i - xst J.39 ---- +---- Simulation tools: GHDL [Sokcho edition] (0.2x) ---- +---- Text editor: SETEdit 0.5.x ---- +---- ---- +------------------------------------------------------------------------------ + +library IEEE; +use IEEE.std_logic_1164.all; + +entity RxUnit is + port( + clk_i : in std_logic; -- System clock signal + reset_i : in std_logic; -- Reset input (sync) + enable_i : in std_logic; -- Enable input (rate*4) + read_i : in std_logic; -- Received Byte Read + rxd_i : in std_logic; -- RS-232 data input + rxav_o : out std_logic; -- Byte available + datao_o : out std_logic_vector(7 downto 0)); -- Byte received +end entity RxUnit; + +architecture Behaviour of RxUnit is + signal r_r : std_logic_vector(7 downto 0); -- Receive register + signal bavail_r : std_logic:='0'; -- Byte received +begin + rxav_o <= bavail_r; + -- Rx Process + RxProc: + process (clk_i) + variable bitpos : integer range 0 to 10; -- Position of the bit in the frame + variable samplecnt : integer range 0 to 3; -- Count from 0 to 3 in each bit + begin + if rising_edge(clk_i) then + if reset_i='1' then + bavail_r <= '0'; + bitpos:=0; + else -- reset_i='0' + if read_i='1' then + bavail_r <= '0'; + end if; + if enable_i='1' then + case bitpos is + when 0 => -- idle + bavail_r <= '0'; + if rxd_i='0' then -- Start Bit + samplecnt:=0; + bitpos:=1; + end if; + when 10 => -- Stop Bit + bitpos:=0; -- next is idle + bavail_r <= '1'; -- Indicate byte received + datao_o <= r_r; -- Store received byte + when others => + if samplecnt=1 and bitpos>=2 then -- Sample RxD on 1 + r_r(bitpos-2) <= rxd_i; -- Deserialisation + end if; + if samplecnt=3 then -- Increment BitPos on 3 + bitpos:=bitpos+1; + end if; + end case; + if samplecnt=3 then + samplecnt:=0; + else + samplecnt:=samplecnt+1; + end if; + end if; -- enable_i='1' + end if; -- reset_i='0' + end if; -- rising_edge(clk_i) + end process RxProc; +end architecture Behaviour; + diff --git a/zpu/hdl/zealot/devices/timer.vhdl b/zpu/hdl/zealot/devices/timer.vhdl new file mode 100644 index 0000000..f485e4d --- /dev/null +++ b/zpu/hdl/zealot/devices/timer.vhdl @@ -0,0 +1,91 @@ +------------------------------------------------------------------------------ +---- ---- +---- 64 bits clock counter ---- +---- ---- +---- http://www.opencores.org/ ---- +---- ---- +---- Description: ---- +---- This is a peripheral used by the PHI I/O layout. It just counts the ---- +---- elapsed number of clocks. ---- +---- ---- +---- To Do: ---- +---- - ---- +---- ---- +---- Author: ---- +---- - Øyvind Harboe, oyvind.harboe zylin.com ---- +---- - Salvador E. Tropea, salvador inti.gob.ar ---- +---- ---- +------------------------------------------------------------------------------ +---- ---- +---- Copyright (c) 2008 Øyvind Harboe ---- +---- Copyright (c) 2008 Salvador E. Tropea ---- +---- Copyright (c) 2008 Instituto Nacional de Tecnología Industrial ---- +---- ---- +---- Distributed under the BSD license ---- +---- ---- +------------------------------------------------------------------------------ +---- ---- +---- Design unit: Timer(Behave) (Entity and architecture) ---- +---- File name: timer.vhdl ---- +---- Note: None ---- +---- Limitations: None known ---- +---- Errors: None known ---- +---- Library: zpu ---- +---- Dependencies: IEEE.std_logic_1164 ---- +---- IEEE.numeric_std ---- +---- zpu.zpupkg ---- +---- Target FPGA: Spartan 3 (XC3S1500-4-FG456) ---- +---- Language: VHDL ---- +---- Wishbone: No ---- +---- Synthesis tools: Xilinx Release 9.2.03i - xst J.39 ---- +---- Simulation tools: GHDL [Sokcho edition] (0.2x) ---- +---- Text editor: SETEdit 0.5.x ---- +---- ---- +------------------------------------------------------------------------------ + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity Timer is + port( + clk_i : in std_logic; + reset_i : in std_logic; + we_i : in std_logic; + data_i : in unsigned(31 downto 0); + addr_i : in unsigned(0 downto 0); + data_o : out unsigned(31 downto 0)); +end entity Timer; + +architecture Behave of Timer is + signal sample : std_logic; + signal reset : std_logic; + + signal cnt : unsigned(63 downto 0); + signal cnt_smp : unsigned(63 downto 0); +begin + reset <= '1' when (we_i='1' and data_i(0)='1') else '0'; + sample <= '1' when (we_i='1' and data_i(1)='1') else '0'; + + -- Carry generation + do_timer: + process (clk_i) + begin + if rising_edge(clk_i) then + if reset_i='1' or reset='1' then + cnt <= (others => '0'); + cnt_smp <= (others => '0'); + else + cnt <= cnt+1; + if sample='1' then + -- report "sampling" severity failure; + cnt_smp <= cnt; + end if; + end if; -- else reset_i='1' + end if; -- rising_edge(clk_i) + end process do_timer; + + data_o <= cnt_smp(31 downto 0) when addr_i="0" else + cnt_smp(63 downto 32); +end architecture Behave; -- Entity: Timer + diff --git a/zpu/hdl/zealot/devices/trace.vhdl b/zpu/hdl/zealot/devices/trace.vhdl new file mode 100644 index 0000000..83d3782 --- /dev/null +++ b/zpu/hdl/zealot/devices/trace.vhdl @@ -0,0 +1,258 @@ +------------------------------------------------------------------------------ +---- ---- +---- ZPU Trace Module ---- +---- ---- +---- http://www.opencores.org/ ---- +---- ---- +---- Description: ---- +---- ZPU is a 32 bits small stack cpu. This is a module to log an ---- +---- execution trace. ---- +---- ---- +---- To Do: ---- +---- - ---- +---- ---- +---- Author: ---- +---- - Øyvind Harboe, oyvind.harboe zylin.com ---- +---- - Salvador E. Tropea, salvador inti.gob.ar ---- +---- ---- +------------------------------------------------------------------------------ +---- ---- +---- Copyright (c) 2008 Øyvind Harboe ---- +---- Copyright (c) 2008 Salvador E. Tropea ---- +---- Copyright (c) 2008 Instituto Nacional de Tecnología Industrial ---- +---- ---- +---- Distributed under the BSD license ---- +---- ---- +------------------------------------------------------------------------------ +---- ---- +---- Design unit: Trace(Behave) (Entity and architecture) ---- +---- File name: trace.vhdl ---- +---- Note: None ---- +---- Limitations: None known ---- +---- Errors: None known ---- +---- Library: zpu ---- +---- Dependencies: IEEE.std_logic_1164 ---- +---- IEEE.numeric_std ---- +---- std.textio ---- +---- zpu.zpupkg ---- +---- zpu.txt_util ---- +---- Target FPGA: N/A ---- +---- Language: VHDL ---- +---- Wishbone: No ---- +---- Synthesis tools: N/A ---- +---- Simulation tools: GHDL [Sokcho edition] (0.2x) ---- +---- Text editor: SETEdit 0.5.x ---- +---- ---- +------------------------------------------------------------------------------ + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use std.textio.all; + +library zpu; +use zpu.zpupkg.all; +use zpu.txt_util.all; + +entity Trace is + generic( + LOG_FILE : string:="trace.txt"; -- Name of the trace file + ADDR_W : integer:=16; -- Address width + WORD_SIZE : integer:=32); -- 16/32 + port( + clk_i : in std_logic; + dbg_i : in zpu_dbgo_t; + stop_i : in std_logic; + busy_i : in std_logic + ); +end entity Trace; + +architecture Behave of Trace is + file l_file : text open write_mode is LOG_FILE; + signal counter : unsigned(63 downto 0); +begin + -- write data and control information to a file + receive_data: + process + variable l : line; + variable stk_min : unsigned(31 downto 0):=(others => '1'); + variable stk_ini : unsigned(31 downto 0); + variable first : boolean:=true; + variable sp_off : unsigned(4 downto 0); + variable idim : boolean:=false; + variable im_val : unsigned(31 downto 0):=(others => '0'); + begin + counter <= to_unsigned(1,64); + -- print header for the logfile + print(l_file,"#PC Opcode SP A=[SP] B=[SP+1] Clk Counter Assembler"); + print(l_file,"#---------------------------------------------------------------------------"); + print(l_file," "); + + wait until clk_i='1'; + wait until clk_i='0'; + + while true loop + counter <= counter+1; + if dbg_i.b_inst='1' then + write(l, "0x"&hstr(dbg_i.pc(ADDR_W-1 downto 0))& + " 0x"&hstr(dbg_i.opcode)& + " 0x"&hstr(dbg_i.sp)& + " 0x"&hstr(dbg_i.stk_a)& + " 0x"&hstr(dbg_i.stk_b)& + " 0x"&hstr(counter)&" "); + -------------------------- + -- Instruction Decoder -- + -------------------------- + sp_off(4):=not dbg_i.opcode(4); + sp_off(3 downto 0):=dbg_i.opcode(3 downto 0); + if dbg_i.opcode(7 downto 7)=OPCODE_IM then + if idim then + im_val(31 downto 7):=im_val(24 downto 0); + im_val(6 downto 0):=dbg_i.opcode(6 downto 0); + else + im_val:=unsigned(resize(signed(dbg_i.opcode(6 downto 0)),32)); + end if; + idim:=true; + write(l,"im 0x"&hstr(dbg_i.opcode(6 downto 0))&" ; 0x"&hstr(im_val)); + elsif dbg_i.opcode(7 downto 5)=OPCODE_STORESP then + if sp_off=0 then + write(l,string'("storesp 0 ; pop")); + elsif sp_off=1 then + write(l,string'("storesp 4 ; 1*4 = popdown")); + else + write(l,"storesp "&integer'image(to_integer(sp_off)*4)&" ; "& + integer'image(to_integer(sp_off))&"*4"); + end if; + elsif dbg_i.opcode(7 downto 5)=OPCODE_LOADSP then + if sp_off=0 then + write(l,string'("loadsp 0 ; dup")); + elsif sp_off=1 then + write(l,string'("loadsp 4 ; 1*4 = dupstkb")); + else + write(l,"loadsp "&integer'image(to_integer(sp_off)*4)&" ; "& + integer'image(to_integer(sp_off))&"*4"); + end if; + elsif dbg_i.opcode(7 downto 5)=OPCODE_EMULATE then + if dbg_i.opcode(5 downto 0)=OPCODE_EQ then + write(l,string'("eq")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_LOADB then + write(l,string'("loadb")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_NEQBRANCH then + write(l,string'("neqbranch")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_PUSHSPADD then + write(l,string'("pushspadd")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_LESSTHAN then + write(l,string'("lessthan")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_ULESSTHAN then + write(l,string'("ulessthan")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_MULT then + write(l,string'("mult")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_STOREB then + write(l,string'("storeb")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_CALLPCREL then + write(l,string'("callpcrel")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_SUB then + write(l,string'("sub")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_LESSTHANOREQUAL then + write(l,string'("lessthanorequal")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_ULESSTHANOREQUAL then + write(l,string'("ulessthanorequal")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_CALL then + write(l,string'("call")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_POPPCREL then + write(l,string'("poppcrel")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_LSHIFTRIGHT then + write(l,string'("lshiftright")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_LOADH then + write(l,string'("loadh")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_STOREH then + write(l,string'("storeh")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_ASHIFTLEFT then + write(l,string'("ashiftleft")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_ASHIFTRIGHT then + write(l,string'("ashiftright")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_NEQ then + write(l,string'("neq")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_NEG then + write(l,string'("neg")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_XOR then + write(l,string'("xor")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_DIV then + write(l,string'("div")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_MOD then + write(l,string'("mod")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_EQBRANCH then + write(l,string'("eqbranch")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_CONFIG then + write(l,string'("config")); + elsif dbg_i.opcode(5 downto 0)=OPCODE_PUSHPC then + write(l,string'("pushpc")); + else + write(l,integer'image(to_integer(dbg_i.opcode(5 downto 0)))& + " ; invalid emulated instruction"); + end if; + elsif dbg_i.opcode(7 downto 4)=OPCODE_ADDSP then + if sp_off=0 then + write(l,string'("addsp 0 ; shift")); + elsif sp_off=1 then + write(l,string'("addsp 4 ; 1*4 = addtop")); + else + write(l,"addsp "&integer'image(to_integer(sp_off)*4)&" ; "& + integer'image(to_integer(sp_off))&"*4"); + end if; + else -- OPCODE_SHORT + case dbg_i.opcode(3 downto 0) is + when OPCODE_BREAK => + write(l,string'("break")); + when OPCODE_PUSHSP => + write(l,string'("pushsp")); + when OPCODE_POPPC => + write(l,string'("poppc")); + when OPCODE_ADD => + write(l,string'("add")); + when OPCODE_OR => + write(l,string'("or")); + when OPCODE_AND => + write(l,string'("and")); + when OPCODE_LOAD => + write(l,string'("load")); + when OPCODE_NOT => + write(l,string'("not")); + when OPCODE_FLIP => + write(l,string'("flip")); + when OPCODE_STORE => + write(l,string'("store")); + when OPCODE_POPSP => + write(l,string'("popsp")); + when OPCODE_NOP => + write(l,string'("nop")); + when others => + write(l,integer'image(to_integer(dbg_i.opcode))& + " ; invalid instruction"); + end case; + end if; + if dbg_i.opcode(7 downto 7)/=OPCODE_IM then + idim:=false; + end if; + ----------------------------- + -- End Instruction Decoder -- + ----------------------------- + writeline(l_file,l); + if dbg_i.sp -- idle or stop bit + txd_r <= '1'; + if loaded_r='1' then -- start transmit. next is start bit + t_r <= tbuff_r; + loaded_r <= '0'; + bitpos:=1; + end if; + when 1 => -- Start bit + txd_r <= '0'; + bitpos:=2; + when others => + txd_r <= t_r(bitpos-2); -- Serialisation of t_r + bitpos:=bitpos+1; + end case; + if bitpos=10 then -- bit8. next is stop bit + bitpos:=0; + end if; + end if; -- enable_i='1' + end if; -- reset_i='0' + end if; -- rising_edge(clk_i) + end process TxProc; +end architecture Behaviour; diff --git a/zpu/hdl/zealot/devices/txt_util.vhdl b/zpu/hdl/zealot/devices/txt_util.vhdl new file mode 100644 index 0000000..862611c --- /dev/null +++ b/zpu/hdl/zealot/devices/txt_util.vhdl @@ -0,0 +1,541 @@ +------------------------------------------------------------------------------ +---- ---- +---- Text Utils ---- +---- ---- +---- http://www.opencores.org/ ---- +---- ---- +---- Description: ---- +---- Utils to handle text. Used for the testbenches. ---- +---- ---- +---- To Do: ---- +---- - ---- +---- ---- +---- Author: ---- +---- - Øyvind Harboe, oyvind.harboe zylin.com ---- +---- ---- +------------------------------------------------------------------------------ +---- ---- +---- Copyright (c) 2008 Øyvind Harboe ---- +---- ---- +---- Distributed under the BSD license ---- +---- ---- +------------------------------------------------------------------------------ +---- ---- +---- Design unit: txt_util (Package) ---- +---- File name: txt_util.vhdl ---- +---- Note: None ---- +---- Limitations: None known ---- +---- Errors: None known ---- +---- Library: zpu ---- +---- Dependencies: IEEE.std_logic_1164 ---- +---- IEEE.numeric_std ---- +---- std.textio ---- +---- Target FPGA: N/A ---- +---- Language: VHDL ---- +---- Wishbone: No ---- +---- Synthesis tools: Xilinx Release 9.2.03i - xst J.39 ---- +---- Simulation tools: GHDL [Sokcho edition] (0.2x) ---- +---- Text editor: SETEdit 0.5.x ---- +---- ---- +------------------------------------------------------------------------------ + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use std.textio.all; + +library zpu; + +package txt_util is + -- prints a message to the screen + procedure print(text: string); + + -- prints the message when active + -- useful for debug switches + procedure print(active: boolean; text: string); + + -- converts std_logic into a character + function chr(sl: std_logic) return character; + + -- converts std_logic into a string (1 to 1) + function str(sl: std_logic) return string; + + -- converts std_logic_vector into a string (binary base) + function str(slv: std_logic_vector) return string; + + -- converts boolean into a string + function str(b: boolean) return string; + + -- converts an integer into a single character + -- (can also be used for hex conversion and other bases) + function chr(int: integer) return character; + + -- converts integer into string using specified base + function str(int: integer; base: integer) return string; + + -- converts integer to string, using base 10 + function str(int: integer) return string; + + -- convert std_logic_vector into a string in hex format + function hstr(slv: std_logic_vector) return string; + function hstr(slv: unsigned) return string; + + + -- functions to manipulate strings + ----------------------------------- + + -- convert a character to upper case + function to_upper(c: character) return character; + + -- convert a character to lower case + function to_lower(c: character) return character; + + -- convert a string to upper case + function to_upper(s: string) return string; + + -- convert a string to lower case + function to_lower(s: string) return string; + + + + -- functions to convert strings into other formats + -------------------------------------------------- + + -- converts a character into std_logic + function to_std_logic(c: character) return std_logic; + + -- converts a string into std_logic_vector + function to_std_logic_vector(s: string) return std_logic_vector; + + + + -- file I/O + ----------- + + -- read variable length string from input file + procedure str_read(file in_file: TEXT; + res_string: out string); + + procedure str_write(file out_file: TEXT; + new_string: in string); + + -- print string to a file and start new line + procedure print(file out_file: TEXT; + new_string: in string); + + -- print character to a file and start new line + procedure print(file out_file: TEXT; + char: in character); +end package txt_util; + + + + +package body txt_util is + -- prints text to the screen + procedure print(text: string) is + variable msg_line: line; + begin + --synopsys translate off + write(msg_line, text); + writeline(output, msg_line); + --synopsys translate on + end procedure print; + + -- prints text to the screen when active + procedure print(active: boolean; text: string) is + begin + if active then + print(text); + end if; + end procedure print; + + -- converts std_logic into a character + function chr(sl: std_logic) return character is + variable c: character; + begin + case sl is + when 'U' => c:= 'U'; + when 'X' => c:= 'X'; + when '0' => c:= '0'; + when '1' => c:= '1'; + when 'Z' => c:= 'Z'; + when 'W' => c:= 'W'; + when 'L' => c:= 'L'; + when 'H' => c:= 'H'; + when '-' => c:= '-'; + end case; + return c; + end function chr; + + -- converts std_logic into a string (1 to 1) + function str(sl: std_logic) return string is + variable s: string(1 to 1); + begin + s(1):=chr(sl); + return s; + end function str; + + -- converts std_logic_vector into a string (binary base) + -- (this also takes care of the fact that the range of + -- a string is natural while a std_logic_vector may + -- have an integer range) + function str(slv: std_logic_vector) return string is + variable result : string (1 to slv'length); + variable r : integer; + begin + r:=1; + for i in slv'range loop + result(r) := chr(slv(i)); + r:=r+1; + end loop; + return result; + end function str; + + + function str(b: boolean) return string is + begin + if b then + return "true"; + else + return "false"; + end if; + end function str; + + -- converts an integer into a character + -- for 0 to 9 the obvious mapping is used, higher + -- values are mapped to the characters A-Z + -- (this is usefull for systems with base > 10) + -- (adapted from Steve Vogwell's posting in comp.lang.vhdl) + function chr(int: integer) return character is + variable c: character; + begin + case int is + when 0 => c := '0'; + when 1 => c := '1'; + when 2 => c := '2'; + when 3 => c := '3'; + when 4 => c := '4'; + when 5 => c := '5'; + when 6 => c := '6'; + when 7 => c := '7'; + when 8 => c := '8'; + when 9 => c := '9'; + when 10 => c := 'A'; + when 11 => c := 'B'; + when 12 => c := 'C'; + when 13 => c := 'D'; + when 14 => c := 'E'; + when 15 => c := 'F'; + when 16 => c := 'G'; + when 17 => c := 'H'; + when 18 => c := 'I'; + when 19 => c := 'J'; + when 20 => c := 'K'; + when 21 => c := 'L'; + when 22 => c := 'M'; + when 23 => c := 'N'; + when 24 => c := 'O'; + when 25 => c := 'P'; + when 26 => c := 'Q'; + when 27 => c := 'R'; + when 28 => c := 'S'; + when 29 => c := 'T'; + when 30 => c := 'U'; + when 31 => c := 'V'; + when 32 => c := 'W'; + when 33 => c := 'X'; + when 34 => c := 'Y'; + when 35 => c := 'Z'; + when others => c := '?'; + end case; + return c; + end function chr; + + -- convert integer to string using specified base + -- (adapted from Steve Vogwell's posting in comp.lang.vhdl) + function str(int: integer; base: integer) return string is + variable temp : string(1 to 10); + variable num : integer; + variable abs_int : integer; + variable len : integer:=1; + variable power : integer:=1; + begin + -- bug fix for negative numbers + abs_int:=abs(int); + + num :=abs_int; + + while num>=base loop -- Determine how many + len:=len+1; -- characters required + num:=num/base; -- to represent the + end loop; -- number. + + for i in len downto 1 loop -- Convert the number to + temp(i):=chr(abs_int/power mod base); -- a string starting + power:=power*base; -- with the right hand + end loop ; -- side. + + -- return result and add sign if required + if int<0 then + return '-'& temp(1 to len); + else + return temp(1 to len); + end if; + end function str; + + -- convert integer to string, using base 10 + function str(int: integer) return string is + begin + return str(int, 10) ; + end function str; + + -- converts a std_logic_vector into a hex string. + function hstr(slv: std_logic_vector) return string is + variable hexlen: integer; + variable longslv : std_logic_vector(67 downto 0):=(others => '0'); + variable hex : string(1 to 16); + variable fourbit : std_logic_vector(3 downto 0); + begin + hexlen:=(slv'left+1)/4; + if (slv'left+1) mod 4/=0 then + hexlen := hexlen + 1; + end if; + longslv(slv'left downto 0) := slv; + for i in (hexlen-1) downto 0 loop + fourbit:=longslv(((i*4)+3) downto (i*4)); + case fourbit is + when "0000" => hex(hexlen-I):='0'; + when "0001" => hex(hexlen-I):='1'; + when "0010" => hex(hexlen-I):='2'; + when "0011" => hex(hexlen-I):='3'; + when "0100" => hex(hexlen-I):='4'; + when "0101" => hex(hexlen-I):='5'; + when "0110" => hex(hexlen-I):='6'; + when "0111" => hex(hexlen-I):='7'; + when "1000" => hex(hexlen-I):='8'; + when "1001" => hex(hexlen-I):='9'; + when "1010" => hex(hexlen-I):='A'; + when "1011" => hex(hexlen-I):='B'; + when "1100" => hex(hexlen-I):='C'; + when "1101" => hex(hexlen-I):='D'; + when "1110" => hex(hexlen-I):='E'; + when "1111" => hex(hexlen-I):='F'; + when "ZZZZ" => hex(hexlen-I):='z'; + when "UUUU" => hex(hexlen-I):='u'; + when "XXXX" => hex(hexlen-I):='x'; + when others => hex(hexlen-I):='?'; + end case; + end loop; + return hex(1 to hexlen); + end function hstr; + + function hstr(slv: unsigned) return string is + begin + return hstr(std_logic_vector(slv)); + end function hstr; + + -- functions to manipulate strings + ----------------------------------- + + + -- convert a character to upper case + function to_upper(c: character) return character is + variable u: character; + begin + case c is + when 'a' => u:='A'; + when 'b' => u:='B'; + when 'c' => u:='C'; + when 'd' => u:='D'; + when 'e' => u:='E'; + when 'f' => u:='F'; + when 'g' => u:='G'; + when 'h' => u:='H'; + when 'i' => u:='I'; + when 'j' => u:='J'; + when 'k' => u:='K'; + when 'l' => u:='L'; + when 'm' => u:='M'; + when 'n' => u:='N'; + when 'o' => u:='O'; + when 'p' => u:='P'; + when 'q' => u:='Q'; + when 'r' => u:='R'; + when 's' => u:='S'; + when 't' => u:='T'; + when 'u' => u:='U'; + when 'v' => u:='V'; + when 'w' => u:='W'; + when 'x' => u:='X'; + when 'y' => u:='Y'; + when 'z' => u:='Z'; + when others => u:=c; + end case; + return u; + end function to_upper; + + + -- convert a character to lower case + function to_lower(c: character) return character is + variable l: character; + begin + case c is + when 'A' => l:='a'; + when 'B' => l:='b'; + when 'C' => l:='c'; + when 'D' => l:='d'; + when 'E' => l:='e'; + when 'F' => l:='f'; + when 'G' => l:='g'; + when 'H' => l:='h'; + when 'I' => l:='i'; + when 'J' => l:='j'; + when 'K' => l:='k'; + when 'L' => l:='l'; + when 'M' => l:='m'; + when 'N' => l:='n'; + when 'O' => l:='o'; + when 'P' => l:='p'; + when 'Q' => l:='q'; + when 'R' => l:='r'; + when 'S' => l:='s'; + when 'T' => l:='t'; + when 'U' => l:='u'; + when 'V' => l:='v'; + when 'W' => l:='w'; + when 'X' => l:='x'; + when 'Y' => l:='y'; + when 'Z' => l:='z'; + when others => l:=c; + end case; + return l; + end function to_lower; + + -- convert a string to upper case + function to_upper(s: string) return string is + variable uppercase: string (s'range); + begin + for i in s'range loop + uppercase(i):=to_upper(s(i)); + end loop; + return uppercase; + end to_upper; + + -- convert a string to lower case + function to_lower(s: string) return string is + variable lowercase: string (s'range); + begin + for i in s'range loop + lowercase(i):=to_lower(s(i)); + end loop; + return lowercase; + end to_lower; + + -- functions to convert strings into other types + + -- converts a character into a std_logic + + function to_std_logic(c: character) return std_logic is + variable sl : std_logic; + begin + case c is + when 'U' => + sl:='U'; + when 'X' => + sl:='X'; + when '0' => + sl:='0'; + when '1' => + sl:='1'; + when 'Z' => + sl:='Z'; + when 'W' => + sl:='W'; + when 'L' => + sl:='L'; + when 'H' => + sl:='H'; + when '-' => + sl:='-'; + when others => + sl:='X'; + end case; + return sl; + end function to_std_logic; + + + -- converts a string into std_logic_vector + function to_std_logic_vector(s: string) return std_logic_vector is + variable slv : std_logic_vector(s'high-s'low downto 0); + variable k : integer; + begin + k:=s'high-s'low; + for i in s'range loop + slv(k):=to_std_logic(s(i)); + k :=k-1; + end loop; + return slv; + end function to_std_logic_vector; + + + ---------------- + -- file I/O -- + ---------------- + + -- read variable length string from input file + procedure str_read(file in_file: TEXT; + res_string: out string) is + variable l : line; + variable c : character; + variable is_string : boolean; + begin + readline(in_file, l); + -- clear the contents of the result string + for i in res_string'range loop + res_string(i):=' '; + end loop; + -- read all characters of the line, up to the length + -- of the results string + for i in res_string'range loop + read(l,c,is_string); + res_string(i):=c; + if not is_string then -- found end of line + exit; + end if; + end loop; + end procedure str_read; + + -- print string to a file + procedure print(file out_file: TEXT; + new_string: in string) is + variable l: line; + begin + write(l,new_string); + writeline(out_file,l); + end procedure print; + + -- print character to a file and start new line + procedure print(file out_file: TEXT; + char: in character) is + variable l: line; + begin + write(l,char); + writeline(out_file,l); + end procedure print; + + -- appends contents of a string to a file until line feed occurs + -- (LF is considered to be the end of the string) + procedure str_write(file out_file: TEXT; + new_string: in string) is + begin + for i in new_string'range loop + print(out_file,new_string(i)); + if new_string(i)=LF then -- end of string + exit; + end if; + end loop; + end str_write; +end package body txt_util; + -- cgit v1.1 From bf4405c61a9c010a8e888da678436a282b9551a3 Mon Sep 17 00:00:00 2001 From: Bert Lange Date: Thu, 13 Oct 2011 12:35:10 +0200 Subject: change: prettier logifle output (for zealot) --- zpu/hdl/zealot/devices/phi_io.vhdl | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'zpu/hdl/zealot/devices') diff --git a/zpu/hdl/zealot/devices/phi_io.vhdl b/zpu/hdl/zealot/devices/phi_io.vhdl index 267ff54..b70ccd7 100644 --- a/zpu/hdl/zealot/devices/phi_io.vhdl +++ b/zpu/hdl/zealot/devices/phi_io.vhdl @@ -158,6 +158,8 @@ begin do_io: process(clk_i) + variable line_out : line := new string'(""); + variable char : character; begin if rising_edge(clk_i) then if reset_i/='1' then @@ -167,9 +169,12 @@ begin -- Write to UART print("- Write to UART Tx: 0x" &hstr(data_i)&" ("& character'val(to_integer(data_i) mod 256)&")"); - if to_integer(data_i)<256 then - print(l_file,character'val(to_integer(data_i))); - end if; + char := character'val(to_integer(data_i)); + if char = lf then + std.textio.writeline(l_file, line_out); + else + std.textio.write(line_out, char); + end if; elsif is_timer='1' and ENA_LOG then print("- Write to TIMER: 0x"&hstr(data_i)); else -- cgit v1.1 From 66a60bf34fd1960bb3c8f87a784dd2e6d27e2213 Mon Sep 17 00:00:00 2001 From: Bert Lange Date: Sat, 15 Oct 2011 08:50:18 +0200 Subject: minor fix: to satisfy some synthesis tools --- zpu/hdl/zealot/devices/phi_io.vhdl | 2 ++ 1 file changed, 2 insertions(+) (limited to 'zpu/hdl/zealot/devices') diff --git a/zpu/hdl/zealot/devices/phi_io.vhdl b/zpu/hdl/zealot/devices/phi_io.vhdl index b70ccd7..99e0f8f 100644 --- a/zpu/hdl/zealot/devices/phi_io.vhdl +++ b/zpu/hdl/zealot/devices/phi_io.vhdl @@ -158,8 +158,10 @@ begin do_io: process(clk_i) + --synopsys translate off variable line_out : line := new string'(""); variable char : character; + --synopsys translate on begin if rising_edge(clk_i) then if reset_i/='1' then -- cgit v1.1 From c883cd4a4e4fa1974e5d7d72a79240de88bd26da Mon Sep 17 00:00:00 2001 From: Bert Lange Date: Tue, 25 Oct 2011 23:26:36 +0200 Subject: add: GPIO module to zealot SoC --- zpu/hdl/zealot/devices/gpio.vhdl | 107 +++++++++++++++++++++++++++++++++++++ zpu/hdl/zealot/devices/phi_io.vhdl | 71 ++++++++++++++++++------ 2 files changed, 163 insertions(+), 15 deletions(-) create mode 100644 zpu/hdl/zealot/devices/gpio.vhdl (limited to 'zpu/hdl/zealot/devices') diff --git a/zpu/hdl/zealot/devices/gpio.vhdl b/zpu/hdl/zealot/devices/gpio.vhdl new file mode 100644 index 0000000..fc66bde --- /dev/null +++ b/zpu/hdl/zealot/devices/gpio.vhdl @@ -0,0 +1,107 @@ +-- +-- this module desribes a simple GPIO interface +-- +-- data on port_in is synhronized to clk_i and can be read at +-- address 0 +-- +-- any write to address 0 is mapped to port_out +-- +-- at address 1 is a direction register (port_dir) +-- initialized with '1's, what mean direction = in +-- this register is useful for bidirectional pins, e.g. headers +-- +-- +-- some examples: +-- +-- to connect 4 buttons: +-- port_in( 3 downto 0) <= gpio_button; +-- +-- +-- to connect 8 LEDs: +-- gpio_led <= port_out(7 downto 0); +-- +-- +-- to connect 2 bidirectional header pins: +-- port_in(8) <= gpio_pin(0); +-- gpio_pin(0) <= port_out(8) when port_dir(8) = '0' else 'Z'; +-- +-- port_in(9) <= gpio_pin(1); +-- gpio_pin(1) <= port_out(9) when port_dir(9) = '0' else 'Z'; +-- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + + +entity gpio is + port( + clk_i : in std_logic; + reset_i : in std_logic; + -- + we_i : in std_logic; + data_i : in unsigned(31 downto 0); + addr_i : in unsigned( 0 downto 0); + data_o : out unsigned(31 downto 0); + -- + port_in : in std_logic_vector(31 downto 0); + port_out : out std_logic_vector(31 downto 0); + port_dir : out std_logic_vector(31 downto 0) + ); +end entity gpio; + + +architecture rtl of gpio is + + signal port_in_reg : std_logic_vector(31 downto 0); + signal port_in_sync : std_logic_vector(31 downto 0); + -- + signal direction : std_logic_vector(31 downto 0) := (others => '1'); + +begin + + process + begin + wait until rising_edge( clk_i); + + -- synchronize all inputs with two registers + -- to avoid metastability + port_in_reg <= port_in; + port_in_sync <= port_in_reg; + + -- write access to gpio + if we_i = '1' then + -- data + if addr_i = "0" then + port_out <= std_logic_vector( data_i); + end if; + -- direction + if addr_i = "1" then + direction <= std_logic_vector( data_i); + end if; + end if; + + -- read access to gpio + -- data + if addr_i = "0" then + data_o <= unsigned( port_in_sync); + end if; + -- direction + if addr_i = "1" then + data_o <= unsigned( direction); + end if; + + -- outputs + port_dir <= direction; + + -- sync reset + if reset_i = '1' then + direction <= (others => '1'); + port_in_reg <= (others => '0'); + port_in_sync <= (others => '0'); + end if; + + end process; + + +end architecture rtl; diff --git a/zpu/hdl/zealot/devices/phi_io.vhdl b/zpu/hdl/zealot/devices/phi_io.vhdl index 99e0f8f..71e881c 100644 --- a/zpu/hdl/zealot/devices/phi_io.vhdl +++ b/zpu/hdl/zealot/devices/phi_io.vhdl @@ -56,7 +56,8 @@ use IEEE.numeric_std.all; use std.textio.all; library zpu; -use zpu.zpupkg.all; +use zpu.zpupkg.timer; +use zpu.zpupkg.gpio; use zpu.UART.all; use zpu.txt_util.all; @@ -73,25 +74,31 @@ entity ZPUPhiIO is re_i : in std_logic; -- Read Enable data_i : in unsigned(31 downto 0); data_o : out unsigned(31 downto 0); - addr_i : in unsigned(2 downto 0); -- Address bits 4-2 + addr_i : in unsigned(2 downto 0); -- Address bits 4-2 + -- rs232_rx_i : in std_logic; -- UART Rx input rs232_tx_o : out std_logic; -- UART Tx output - br_clk_i : in std_logic); -- UART base clock (enable) + br_clk_i : in std_logic; -- UART base clock (enable) + -- + gpio_in : in std_logic_vector(31 downto 0); + gpio_out : out std_logic_vector(31 downto 0); + gpio_dir : out std_logic_vector(31 downto 0) -- 1 = in, 0 = out + ); end entity ZPUPhiIO; architecture Behave of ZPUPhiIO is - constant LOW_BITS : unsigned(1 downto 0):=(others=>'0'); - constant TX_FULL : std_logic:='0'; - constant RX_EMPTY : std_logic:='1'; + constant LOW_BITS : unsigned(1 downto 0):=(others=>'0'); + constant TX_FULL : std_logic:='0'; + constant RX_EMPTY : std_logic:='1'; -- "000" 0x00 is CPU enable ... useful? - -- "001" 0x04 Unused - -- "010" 0x08 Unused - constant UART_TX : unsigned(2 downto 0):="011"; -- 0x0C - constant UART_RX : unsigned(2 downto 0):="100"; -- 0x10 - constant CNT_1 : unsigned(2 downto 0):="101"; -- 0x14 - constant CNT_2 : unsigned(2 downto 0):="110"; -- 0x18 + constant IO_DATA : unsigned(2 downto 0):="001"; -- 0x04 + constant IO_DIR : unsigned(2 downto 0):="010"; -- 0x08 + constant UART_TX : unsigned(2 downto 0):="011"; -- 0x0C + constant UART_RX : unsigned(2 downto 0):="100"; -- 0x10 + constant CNT_1 : unsigned(2 downto 0):="101"; -- 0x14 + constant CNT_2 : unsigned(2 downto 0):="110"; -- 0x18 -- "111" 0x1C Unused -- Unimplemented: Interrupt control and timer (not counter ...?) @@ -110,7 +117,13 @@ architecture Behave of ZPUPhiIO is signal uart_write : std_logic; -- ZPU is writing signal tx_busy : std_logic; -- Tx can't get a new value + -- GPIO + signal gpio_we : std_logic; + signal is_gpio : std_logic; + signal gpio_read : unsigned(31 downto 0); + file l_file : text open write_mode is LOG_FILE; + begin ----------- -- Timer -- @@ -155,6 +168,27 @@ begin generic map(COUNT => 4) port map( clk_i => clk_i, reset_i => reset_i, ce_i => rx_br, o_o => tx_br); + + ---------- + -- GPIO -- + ---------- + gpio_i0: gpio + port map( + clk_i => clk_i, -- : in std_logic; + reset_i => reset_i, -- : in std_logic; + -- + we_i => gpio_we, -- : in std_logic; + data_i => data_i, -- : in unsigned(31 downto 0); + addr_i => addr_i(1 downto 1), -- : in unsigned( 0 downto 0); + data_o => gpio_read, -- : out unsigned(31 downto 0); + -- + port_in => gpio_in, -- : std_logic_vector(31 downto 0); + port_out => gpio_out, -- : std_logic_vector(31 downto 0); + port_dir => gpio_dir -- : std_logic_vector(31 downto 0); + ); + is_gpio <= '1' when addr_i = IO_DATA or addr_i = IO_DIR else '0'; -- 0x80A0004/8 + gpio_we <= we_i and is_gpio; + do_io: process(clk_i) @@ -177,8 +211,10 @@ begin else std.textio.write(line_out, char); end if; + elsif is_gpio = '1' and ENA_LOG then + print("- Write GPIO: 0x" & hstr(data_i)); elsif is_timer='1' and ENA_LOG then - print("- Write to TIMER: 0x"&hstr(data_i)); + print("- Write to TIMER: 0x" & hstr(data_i)); else --print(l_file,character'val(to_integer(data_i))); report "Illegal IO data_i=0x"&hstr(data_i)&" @0x"& @@ -188,7 +224,12 @@ begin --synopsys translate on data_o <= (others => '0'); if re_i='1' then - if addr_i=UART_TX then + if is_gpio = '1' then + if ENA_LOG then + print("- Read GPIO: 0x" & hstr(gpio_read)); + end if; + data_o <= gpio_read; + elsif addr_i=UART_TX then if ENA_LOG then print("- Read UART Tx"); end if; @@ -201,7 +242,7 @@ begin data_o(7 downto 0) <= unsigned(rx_data); elsif is_timer='1' then if ENA_LOG then - print("- Read TIMER: 0x"&hstr(timer_read)); + print("- Read TIMER: 0x" & hstr(timer_read)); end if; data_o <= timer_read; else -- cgit v1.1 From 221eb9f6525789d20f2895b2de775bf345cf97cb Mon Sep 17 00:00:00 2001 From: Bert Lange Date: Fri, 28 Oct 2011 11:25:31 +0200 Subject: minor fix: reduce simulation warnings at 0 ps --- zpu/hdl/zealot/devices/phi_io.vhdl | 4 ++-- zpu/hdl/zealot/devices/timer.vhdl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'zpu/hdl/zealot/devices') diff --git a/zpu/hdl/zealot/devices/phi_io.vhdl b/zpu/hdl/zealot/devices/phi_io.vhdl index 71e881c..6e40d1d 100644 --- a/zpu/hdl/zealot/devices/phi_io.vhdl +++ b/zpu/hdl/zealot/devices/phi_io.vhdl @@ -135,7 +135,7 @@ begin data_o => timer_read); busy_o <= we_i or re_i; - is_timer <= '1' when addr_i=CNT_1 or addr_i=CNT_2 else '0'; -- 0x80A0014/8 + is_timer <= '1' when to_01(addr_i)=CNT_1 or to_01(addr_i)=CNT_2 else '0'; -- 0x80A0014/8 timer_we <= we_i and is_timer; ---------- @@ -186,7 +186,7 @@ begin port_out => gpio_out, -- : std_logic_vector(31 downto 0); port_dir => gpio_dir -- : std_logic_vector(31 downto 0); ); - is_gpio <= '1' when addr_i = IO_DATA or addr_i = IO_DIR else '0'; -- 0x80A0004/8 + is_gpio <= '1' when to_01(addr_i) = IO_DATA or to_01(addr_i) = IO_DIR else '0'; -- 0x80A0004/8 gpio_we <= we_i and is_gpio; diff --git a/zpu/hdl/zealot/devices/timer.vhdl b/zpu/hdl/zealot/devices/timer.vhdl index f485e4d..389868c 100644 --- a/zpu/hdl/zealot/devices/timer.vhdl +++ b/zpu/hdl/zealot/devices/timer.vhdl @@ -85,7 +85,7 @@ begin end if; -- rising_edge(clk_i) end process do_timer; - data_o <= cnt_smp(31 downto 0) when addr_i="0" else + data_o <= cnt_smp(31 downto 0) when to_01(addr_i)="0" else cnt_smp(63 downto 32); end architecture Behave; -- Entity: Timer -- cgit v1.1