mirror of
https://github.com/mist-devel/mist-board.git
synced 2026-04-25 03:55:26 +00:00
[TUTORIALS] New lesson 7c: Direct block IO
This commit is contained in:
47
tutorials/soc/lesson7c/Makefile
Normal file
47
tutorials/soc/lesson7c/Makefile
Normal file
@@ -0,0 +1,47 @@
|
||||
SDCC=sdcc
|
||||
CPU=z80
|
||||
CODE=boot_rom
|
||||
TTY=/dev/ttyUSB0
|
||||
OBJ=$(CODE).rel irqvec.rel font.rel pff.rel block_io.rel
|
||||
ROM=z80_soc.rom
|
||||
|
||||
all: $(ROM)
|
||||
|
||||
bin2c: bin2c.c
|
||||
|
||||
font.part: font.fnt
|
||||
dd if=$< of=$@ bs=1 count=768 skip=256
|
||||
|
||||
font.c: font.part bin2c
|
||||
./bin2c font.part font.c "unsigned char font[]"
|
||||
|
||||
irqvec.rel: irqvec.s
|
||||
sdasz80 -o $@ $<
|
||||
|
||||
%.rel: %.c
|
||||
$(SDCC) -m$(CPU) -c $<
|
||||
|
||||
$(CODE).ihx: $(OBJ)
|
||||
$(SDCC) -m$(CPU) $(OBJ)
|
||||
|
||||
%.hex: %.ihx
|
||||
cp $< $@
|
||||
|
||||
%.bin: %.hex
|
||||
srec_cat -multiple $< -intel -o $@ -binary
|
||||
|
||||
$(ROM): $(CODE).bin
|
||||
cp $< $@
|
||||
|
||||
disasm: $(CODE).bin
|
||||
z80dasm -a -t -g 0 $<
|
||||
|
||||
clean:
|
||||
rm -rf *~ *.asm *.ihx *.lk *.lst *.map *.noi *.rel *.sym *.bin bin2c *.part
|
||||
|
||||
run: $(ROM)
|
||||
stty -F $(TTY) speed 115200 raw -echo
|
||||
timeout 1s cp $(TTY) /dev/null || /bin/true
|
||||
echo "x $(ROM) `stat -c%s $<`" > $(TTY)
|
||||
sx $< <$(TTY) >$(TTY)
|
||||
echo "r" > $(TTY)
|
||||
1088
tutorials/soc/lesson7c/T80.vhd
Normal file
1088
tutorials/soc/lesson7c/T80.vhd
Normal file
File diff suppressed because it is too large
Load Diff
371
tutorials/soc/lesson7c/T80_ALU.vhd
Normal file
371
tutorials/soc/lesson7c/T80_ALU.vhd
Normal file
@@ -0,0 +1,371 @@
|
||||
-- ****
|
||||
-- T80(b) core. In an effort to merge and maintain bug fixes ....
|
||||
--
|
||||
--
|
||||
-- Ver 301 parity flag is just parity for 8080, also overflow for Z80, by Sean Riddle
|
||||
-- Ver 300 started tidyup
|
||||
-- MikeJ March 2005
|
||||
-- Latest version from www.fpgaarcade.com (original www.opencores.org)
|
||||
--
|
||||
-- ****
|
||||
--
|
||||
-- Z80 compatible microprocessor core
|
||||
--
|
||||
-- Version : 0247
|
||||
--
|
||||
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
|
||||
--
|
||||
-- All rights reserved
|
||||
--
|
||||
-- Redistribution and use in source and synthezised forms, with or without
|
||||
-- modification, are permitted provided that the following conditions are met:
|
||||
--
|
||||
-- Redistributions of source code must retain the above copyright notice,
|
||||
-- this list of conditions and the following disclaimer.
|
||||
--
|
||||
-- Redistributions in synthesized form must reproduce the above copyright
|
||||
-- notice, this list of conditions and the following disclaimer in the
|
||||
-- documentation and/or other materials provided with the distribution.
|
||||
--
|
||||
-- Neither the name of the author nor the names of other contributors may
|
||||
-- be used to endorse or promote products derived from this software without
|
||||
-- specific prior written permission.
|
||||
--
|
||||
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
|
||||
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
-- POSSIBILITY OF SUCH DAMAGE.
|
||||
--
|
||||
-- Please report bugs to the author, but before you do so, please
|
||||
-- make sure that this is not a derivative work and that
|
||||
-- you have the latest version of this file.
|
||||
--
|
||||
-- The latest version of this file can be found at:
|
||||
-- http://www.opencores.org/cvsweb.shtml/t80/
|
||||
--
|
||||
-- Limitations :
|
||||
--
|
||||
-- File history :
|
||||
--
|
||||
-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test
|
||||
--
|
||||
-- 0238 : Fixed zero flag for 16 bit SBC and ADC
|
||||
--
|
||||
-- 0240 : Added GB operations
|
||||
--
|
||||
-- 0242 : Cleanup
|
||||
--
|
||||
-- 0247 : Cleanup
|
||||
--
|
||||
|
||||
library IEEE;
|
||||
use IEEE.std_logic_1164.all;
|
||||
use IEEE.numeric_std.all;
|
||||
|
||||
entity T80_ALU is
|
||||
generic(
|
||||
Mode : integer := 0;
|
||||
Flag_C : integer := 0;
|
||||
Flag_N : integer := 1;
|
||||
Flag_P : integer := 2;
|
||||
Flag_X : integer := 3;
|
||||
Flag_H : integer := 4;
|
||||
Flag_Y : integer := 5;
|
||||
Flag_Z : integer := 6;
|
||||
Flag_S : integer := 7
|
||||
);
|
||||
port(
|
||||
Arith16 : in std_logic;
|
||||
Z16 : in std_logic;
|
||||
ALU_Op : in std_logic_vector(3 downto 0);
|
||||
IR : in std_logic_vector(5 downto 0);
|
||||
ISet : in std_logic_vector(1 downto 0);
|
||||
BusA : in std_logic_vector(7 downto 0);
|
||||
BusB : in std_logic_vector(7 downto 0);
|
||||
F_In : in std_logic_vector(7 downto 0);
|
||||
Q : out std_logic_vector(7 downto 0);
|
||||
F_Out : out std_logic_vector(7 downto 0)
|
||||
);
|
||||
end T80_ALU;
|
||||
|
||||
architecture rtl of T80_ALU is
|
||||
|
||||
procedure AddSub(A : std_logic_vector;
|
||||
B : std_logic_vector;
|
||||
Sub : std_logic;
|
||||
Carry_In : std_logic;
|
||||
signal Res : out std_logic_vector;
|
||||
signal Carry : out std_logic) is
|
||||
|
||||
variable B_i : unsigned(A'length - 1 downto 0);
|
||||
variable Res_i : unsigned(A'length + 1 downto 0);
|
||||
begin
|
||||
if Sub = '1' then
|
||||
B_i := not unsigned(B);
|
||||
else
|
||||
B_i := unsigned(B);
|
||||
end if;
|
||||
|
||||
Res_i := unsigned("0" & A & Carry_In) + unsigned("0" & B_i & "1");
|
||||
Carry <= Res_i(A'length + 1);
|
||||
Res <= std_logic_vector(Res_i(A'length downto 1));
|
||||
end;
|
||||
|
||||
-- AddSub variables (temporary signals)
|
||||
signal UseCarry : std_logic;
|
||||
signal Carry7_v : std_logic;
|
||||
signal Overflow_v : std_logic;
|
||||
signal HalfCarry_v : std_logic;
|
||||
signal Carry_v : std_logic;
|
||||
signal Q_v : std_logic_vector(7 downto 0);
|
||||
|
||||
signal BitMask : std_logic_vector(7 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
with IR(5 downto 3) select BitMask <= "00000001" when "000",
|
||||
"00000010" when "001",
|
||||
"00000100" when "010",
|
||||
"00001000" when "011",
|
||||
"00010000" when "100",
|
||||
"00100000" when "101",
|
||||
"01000000" when "110",
|
||||
"10000000" when others;
|
||||
|
||||
UseCarry <= not ALU_Op(2) and ALU_Op(0);
|
||||
AddSub(BusA(3 downto 0), BusB(3 downto 0), ALU_Op(1), ALU_Op(1) xor (UseCarry and F_In(Flag_C)), Q_v(3 downto 0), HalfCarry_v);
|
||||
AddSub(BusA(6 downto 4), BusB(6 downto 4), ALU_Op(1), HalfCarry_v, Q_v(6 downto 4), Carry7_v);
|
||||
AddSub(BusA(7 downto 7), BusB(7 downto 7), ALU_Op(1), Carry7_v, Q_v(7 downto 7), Carry_v);
|
||||
|
||||
-- bug fix - parity flag is just parity for 8080, also overflow for Z80
|
||||
process (Carry_v, Carry7_v, Q_v)
|
||||
begin
|
||||
if(Mode=2) then
|
||||
OverFlow_v <= not (Q_v(0) xor Q_v(1) xor Q_v(2) xor Q_v(3) xor
|
||||
Q_v(4) xor Q_v(5) xor Q_v(6) xor Q_v(7)); else
|
||||
OverFlow_v <= Carry_v xor Carry7_v;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16)
|
||||
variable Q_t : std_logic_vector(7 downto 0);
|
||||
variable DAA_Q : unsigned(8 downto 0);
|
||||
begin
|
||||
Q_t := "--------";
|
||||
F_Out <= F_In;
|
||||
DAA_Q := "---------";
|
||||
case ALU_Op is
|
||||
when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" | "0110" | "0111" =>
|
||||
F_Out(Flag_N) <= '0';
|
||||
F_Out(Flag_C) <= '0';
|
||||
case ALU_OP(2 downto 0) is
|
||||
when "000" | "001" => -- ADD, ADC
|
||||
Q_t := Q_v;
|
||||
F_Out(Flag_C) <= Carry_v;
|
||||
F_Out(Flag_H) <= HalfCarry_v;
|
||||
F_Out(Flag_P) <= OverFlow_v;
|
||||
when "010" | "011" | "111" => -- SUB, SBC, CP
|
||||
Q_t := Q_v;
|
||||
F_Out(Flag_N) <= '1';
|
||||
F_Out(Flag_C) <= not Carry_v;
|
||||
F_Out(Flag_H) <= not HalfCarry_v;
|
||||
F_Out(Flag_P) <= OverFlow_v;
|
||||
when "100" => -- AND
|
||||
Q_t(7 downto 0) := BusA and BusB;
|
||||
F_Out(Flag_H) <= '1';
|
||||
when "101" => -- XOR
|
||||
Q_t(7 downto 0) := BusA xor BusB;
|
||||
F_Out(Flag_H) <= '0';
|
||||
when others => -- OR "110"
|
||||
Q_t(7 downto 0) := BusA or BusB;
|
||||
F_Out(Flag_H) <= '0';
|
||||
end case;
|
||||
if ALU_Op(2 downto 0) = "111" then -- CP
|
||||
F_Out(Flag_X) <= BusB(3);
|
||||
F_Out(Flag_Y) <= BusB(5);
|
||||
else
|
||||
F_Out(Flag_X) <= Q_t(3);
|
||||
F_Out(Flag_Y) <= Q_t(5);
|
||||
end if;
|
||||
if Q_t(7 downto 0) = "00000000" then
|
||||
F_Out(Flag_Z) <= '1';
|
||||
if Z16 = '1' then
|
||||
F_Out(Flag_Z) <= F_In(Flag_Z); -- 16 bit ADC,SBC
|
||||
end if;
|
||||
else
|
||||
F_Out(Flag_Z) <= '0';
|
||||
end if;
|
||||
F_Out(Flag_S) <= Q_t(7);
|
||||
case ALU_Op(2 downto 0) is
|
||||
when "000" | "001" | "010" | "011" | "111" => -- ADD, ADC, SUB, SBC, CP
|
||||
when others =>
|
||||
F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor
|
||||
Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7));
|
||||
end case;
|
||||
if Arith16 = '1' then
|
||||
F_Out(Flag_S) <= F_In(Flag_S);
|
||||
F_Out(Flag_Z) <= F_In(Flag_Z);
|
||||
F_Out(Flag_P) <= F_In(Flag_P);
|
||||
end if;
|
||||
when "1100" =>
|
||||
-- DAA
|
||||
F_Out(Flag_H) <= F_In(Flag_H);
|
||||
F_Out(Flag_C) <= F_In(Flag_C);
|
||||
DAA_Q(7 downto 0) := unsigned(BusA);
|
||||
DAA_Q(8) := '0';
|
||||
if F_In(Flag_N) = '0' then
|
||||
-- After addition
|
||||
-- Alow > 9 or H = 1
|
||||
if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then
|
||||
if (DAA_Q(3 downto 0) > 9) then
|
||||
F_Out(Flag_H) <= '1';
|
||||
else
|
||||
F_Out(Flag_H) <= '0';
|
||||
end if;
|
||||
DAA_Q := DAA_Q + 6;
|
||||
end if;
|
||||
-- new Ahigh > 9 or C = 1
|
||||
if DAA_Q(8 downto 4) > 9 or F_In(Flag_C) = '1' then
|
||||
DAA_Q := DAA_Q + 96; -- 0x60
|
||||
end if;
|
||||
else
|
||||
-- After subtraction
|
||||
if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then
|
||||
if DAA_Q(3 downto 0) > 5 then
|
||||
F_Out(Flag_H) <= '0';
|
||||
end if;
|
||||
DAA_Q(7 downto 0) := DAA_Q(7 downto 0) - 6;
|
||||
end if;
|
||||
if unsigned(BusA) > 153 or F_In(Flag_C) = '1' then
|
||||
DAA_Q := DAA_Q - 352; -- 0x160
|
||||
end if;
|
||||
end if;
|
||||
F_Out(Flag_X) <= DAA_Q(3);
|
||||
F_Out(Flag_Y) <= DAA_Q(5);
|
||||
F_Out(Flag_C) <= F_In(Flag_C) or DAA_Q(8);
|
||||
Q_t := std_logic_vector(DAA_Q(7 downto 0));
|
||||
if DAA_Q(7 downto 0) = "00000000" then
|
||||
F_Out(Flag_Z) <= '1';
|
||||
else
|
||||
F_Out(Flag_Z) <= '0';
|
||||
end if;
|
||||
F_Out(Flag_S) <= DAA_Q(7);
|
||||
F_Out(Flag_P) <= not (DAA_Q(0) xor DAA_Q(1) xor DAA_Q(2) xor DAA_Q(3) xor
|
||||
DAA_Q(4) xor DAA_Q(5) xor DAA_Q(6) xor DAA_Q(7));
|
||||
when "1101" | "1110" =>
|
||||
-- RLD, RRD
|
||||
Q_t(7 downto 4) := BusA(7 downto 4);
|
||||
if ALU_Op(0) = '1' then
|
||||
Q_t(3 downto 0) := BusB(7 downto 4);
|
||||
else
|
||||
Q_t(3 downto 0) := BusB(3 downto 0);
|
||||
end if;
|
||||
F_Out(Flag_H) <= '0';
|
||||
F_Out(Flag_N) <= '0';
|
||||
F_Out(Flag_X) <= Q_t(3);
|
||||
F_Out(Flag_Y) <= Q_t(5);
|
||||
if Q_t(7 downto 0) = "00000000" then
|
||||
F_Out(Flag_Z) <= '1';
|
||||
else
|
||||
F_Out(Flag_Z) <= '0';
|
||||
end if;
|
||||
F_Out(Flag_S) <= Q_t(7);
|
||||
F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor
|
||||
Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7));
|
||||
when "1001" =>
|
||||
-- BIT
|
||||
Q_t(7 downto 0) := BusB and BitMask;
|
||||
F_Out(Flag_S) <= Q_t(7);
|
||||
if Q_t(7 downto 0) = "00000000" then
|
||||
F_Out(Flag_Z) <= '1';
|
||||
F_Out(Flag_P) <= '1';
|
||||
else
|
||||
F_Out(Flag_Z) <= '0';
|
||||
F_Out(Flag_P) <= '0';
|
||||
end if;
|
||||
F_Out(Flag_H) <= '1';
|
||||
F_Out(Flag_N) <= '0';
|
||||
F_Out(Flag_X) <= '0';
|
||||
F_Out(Flag_Y) <= '0';
|
||||
if IR(2 downto 0) /= "110" then
|
||||
F_Out(Flag_X) <= BusB(3);
|
||||
F_Out(Flag_Y) <= BusB(5);
|
||||
end if;
|
||||
when "1010" =>
|
||||
-- SET
|
||||
Q_t(7 downto 0) := BusB or BitMask;
|
||||
when "1011" =>
|
||||
-- RES
|
||||
Q_t(7 downto 0) := BusB and not BitMask;
|
||||
when "1000" =>
|
||||
-- ROT
|
||||
case IR(5 downto 3) is
|
||||
when "000" => -- RLC
|
||||
Q_t(7 downto 1) := BusA(6 downto 0);
|
||||
Q_t(0) := BusA(7);
|
||||
F_Out(Flag_C) <= BusA(7);
|
||||
when "010" => -- RL
|
||||
Q_t(7 downto 1) := BusA(6 downto 0);
|
||||
Q_t(0) := F_In(Flag_C);
|
||||
F_Out(Flag_C) <= BusA(7);
|
||||
when "001" => -- RRC
|
||||
Q_t(6 downto 0) := BusA(7 downto 1);
|
||||
Q_t(7) := BusA(0);
|
||||
F_Out(Flag_C) <= BusA(0);
|
||||
when "011" => -- RR
|
||||
Q_t(6 downto 0) := BusA(7 downto 1);
|
||||
Q_t(7) := F_In(Flag_C);
|
||||
F_Out(Flag_C) <= BusA(0);
|
||||
when "100" => -- SLA
|
||||
Q_t(7 downto 1) := BusA(6 downto 0);
|
||||
Q_t(0) := '0';
|
||||
F_Out(Flag_C) <= BusA(7);
|
||||
when "110" => -- SLL (Undocumented) / SWAP
|
||||
if Mode = 3 then
|
||||
Q_t(7 downto 4) := BusA(3 downto 0);
|
||||
Q_t(3 downto 0) := BusA(7 downto 4);
|
||||
F_Out(Flag_C) <= '0';
|
||||
else
|
||||
Q_t(7 downto 1) := BusA(6 downto 0);
|
||||
Q_t(0) := '1';
|
||||
F_Out(Flag_C) <= BusA(7);
|
||||
end if;
|
||||
when "101" => -- SRA
|
||||
Q_t(6 downto 0) := BusA(7 downto 1);
|
||||
Q_t(7) := BusA(7);
|
||||
F_Out(Flag_C) <= BusA(0);
|
||||
when others => -- SRL
|
||||
Q_t(6 downto 0) := BusA(7 downto 1);
|
||||
Q_t(7) := '0';
|
||||
F_Out(Flag_C) <= BusA(0);
|
||||
end case;
|
||||
F_Out(Flag_H) <= '0';
|
||||
F_Out(Flag_N) <= '0';
|
||||
F_Out(Flag_X) <= Q_t(3);
|
||||
F_Out(Flag_Y) <= Q_t(5);
|
||||
F_Out(Flag_S) <= Q_t(7);
|
||||
if Q_t(7 downto 0) = "00000000" then
|
||||
F_Out(Flag_Z) <= '1';
|
||||
else
|
||||
F_Out(Flag_Z) <= '0';
|
||||
end if;
|
||||
F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor
|
||||
Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7));
|
||||
if ISet = "00" then
|
||||
F_Out(Flag_P) <= F_In(Flag_P);
|
||||
F_Out(Flag_S) <= F_In(Flag_S);
|
||||
F_Out(Flag_Z) <= F_In(Flag_Z);
|
||||
end if;
|
||||
when others =>
|
||||
null;
|
||||
end case;
|
||||
Q <= Q_t;
|
||||
end process;
|
||||
end;
|
||||
2024
tutorials/soc/lesson7c/T80_MCode.vhd
Normal file
2024
tutorials/soc/lesson7c/T80_MCode.vhd
Normal file
File diff suppressed because it is too large
Load Diff
228
tutorials/soc/lesson7c/T80_Pack.vhd
Normal file
228
tutorials/soc/lesson7c/T80_Pack.vhd
Normal file
@@ -0,0 +1,228 @@
|
||||
-- ****
|
||||
-- T80(b) core. In an effort to merge and maintain bug fixes ....
|
||||
--
|
||||
--
|
||||
-- Ver 303 add undocumented DDCB and FDCB opcodes by TobiFlex 20.04.2010
|
||||
-- Ver 300 started tidyup
|
||||
-- MikeJ March 2005
|
||||
-- Latest version from www.fpgaarcade.com (original www.opencores.org)
|
||||
--
|
||||
-- ****
|
||||
--
|
||||
-- Z80 compatible microprocessor core
|
||||
--
|
||||
-- Version : 0242
|
||||
--
|
||||
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
|
||||
--
|
||||
-- All rights reserved
|
||||
--
|
||||
-- Redistribution and use in source and synthezised forms, with or without
|
||||
-- modification, are permitted provided that the following conditions are met:
|
||||
--
|
||||
-- Redistributions of source code must retain the above copyright notice,
|
||||
-- this list of conditions and the following disclaimer.
|
||||
--
|
||||
-- Redistributions in synthesized form must reproduce the above copyright
|
||||
-- notice, this list of conditions and the following disclaimer in the
|
||||
-- documentation and/or other materials provided with the distribution.
|
||||
--
|
||||
-- Neither the name of the author nor the names of other contributors may
|
||||
-- be used to endorse or promote products derived from this software without
|
||||
-- specific prior written permission.
|
||||
--
|
||||
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
|
||||
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
-- POSSIBILITY OF SUCH DAMAGE.
|
||||
--
|
||||
-- Please report bugs to the author, but before you do so, please
|
||||
-- make sure that this is not a derivative work and that
|
||||
-- you have the latest version of this file.
|
||||
--
|
||||
-- The latest version of this file can be found at:
|
||||
-- http://www.opencores.org/cvsweb.shtml/t80/
|
||||
--
|
||||
-- Limitations :
|
||||
--
|
||||
-- File history :
|
||||
--
|
||||
|
||||
library IEEE;
|
||||
use IEEE.std_logic_1164.all;
|
||||
|
||||
package T80_Pack is
|
||||
|
||||
constant aNone : std_logic_vector(2 downto 0) := "111";
|
||||
constant aBC : std_logic_vector(2 downto 0) := "000";
|
||||
constant aDE : std_logic_vector(2 downto 0) := "001";
|
||||
constant aXY : std_logic_vector(2 downto 0) := "010";
|
||||
constant aIOA : std_logic_vector(2 downto 0) := "100";
|
||||
constant aSP : std_logic_vector(2 downto 0) := "101";
|
||||
constant aZI : std_logic_vector(2 downto 0) := "110";
|
||||
|
||||
component T80
|
||||
generic(
|
||||
Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
|
||||
IOWait : integer := 0; -- 1 => Single cycle I/O, 1 => Std I/O cycle
|
||||
Flag_C : integer := 0;
|
||||
Flag_N : integer := 1;
|
||||
Flag_P : integer := 2;
|
||||
Flag_X : integer := 3;
|
||||
Flag_H : integer := 4;
|
||||
Flag_Y : integer := 5;
|
||||
Flag_Z : integer := 6;
|
||||
Flag_S : integer := 7
|
||||
);
|
||||
port(
|
||||
RESET_n : in std_logic;
|
||||
CLK_n : in std_logic;
|
||||
CEN : in std_logic;
|
||||
WAIT_n : in std_logic;
|
||||
INT_n : in std_logic;
|
||||
NMI_n : in std_logic;
|
||||
BUSRQ_n : in std_logic;
|
||||
M1_n : out std_logic;
|
||||
IORQ : out std_logic;
|
||||
NoRead : out std_logic;
|
||||
Write : out std_logic;
|
||||
RFSH_n : out std_logic;
|
||||
HALT_n : out std_logic;
|
||||
BUSAK_n : out std_logic;
|
||||
A : out std_logic_vector(15 downto 0);
|
||||
DInst : in std_logic_vector(7 downto 0);
|
||||
DI : in std_logic_vector(7 downto 0);
|
||||
DO : out std_logic_vector(7 downto 0);
|
||||
MC : out std_logic_vector(2 downto 0);
|
||||
TS : out std_logic_vector(2 downto 0);
|
||||
IntCycle_n : out std_logic;
|
||||
IntE : out std_logic;
|
||||
Stop : out std_logic
|
||||
);
|
||||
end component;
|
||||
|
||||
component T80_Reg
|
||||
port(
|
||||
Clk : in std_logic;
|
||||
CEN : in std_logic;
|
||||
WEH : in std_logic;
|
||||
WEL : in std_logic;
|
||||
AddrA : in std_logic_vector(2 downto 0);
|
||||
AddrB : in std_logic_vector(2 downto 0);
|
||||
AddrC : in std_logic_vector(2 downto 0);
|
||||
DIH : in std_logic_vector(7 downto 0);
|
||||
DIL : in std_logic_vector(7 downto 0);
|
||||
DOAH : out std_logic_vector(7 downto 0);
|
||||
DOAL : out std_logic_vector(7 downto 0);
|
||||
DOBH : out std_logic_vector(7 downto 0);
|
||||
DOBL : out std_logic_vector(7 downto 0);
|
||||
DOCH : out std_logic_vector(7 downto 0);
|
||||
DOCL : out std_logic_vector(7 downto 0)
|
||||
);
|
||||
end component;
|
||||
|
||||
component T80_MCode
|
||||
generic(
|
||||
Mode : integer := 0;
|
||||
Flag_C : integer := 0;
|
||||
Flag_N : integer := 1;
|
||||
Flag_P : integer := 2;
|
||||
Flag_X : integer := 3;
|
||||
Flag_H : integer := 4;
|
||||
Flag_Y : integer := 5;
|
||||
Flag_Z : integer := 6;
|
||||
Flag_S : integer := 7
|
||||
);
|
||||
port(
|
||||
IR : in std_logic_vector(7 downto 0);
|
||||
ISet : in std_logic_vector(1 downto 0);
|
||||
MCycle : in std_logic_vector(2 downto 0);
|
||||
F : in std_logic_vector(7 downto 0);
|
||||
NMICycle : in std_logic;
|
||||
IntCycle : in std_logic;
|
||||
XY_State : in std_logic_vector(1 downto 0);
|
||||
MCycles : out std_logic_vector(2 downto 0);
|
||||
TStates : out std_logic_vector(2 downto 0);
|
||||
Prefix : out std_logic_vector(1 downto 0); -- None,BC,ED,DD/FD
|
||||
Inc_PC : out std_logic;
|
||||
Inc_WZ : out std_logic;
|
||||
IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc
|
||||
Read_To_Reg : out std_logic;
|
||||
Read_To_Acc : out std_logic;
|
||||
Set_BusA_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F
|
||||
Set_BusB_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0
|
||||
ALU_Op : out std_logic_vector(3 downto 0);
|
||||
-- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None
|
||||
Save_ALU : out std_logic;
|
||||
PreserveC : out std_logic;
|
||||
Arith16 : out std_logic;
|
||||
Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI
|
||||
IORQ : out std_logic;
|
||||
Jump : out std_logic;
|
||||
JumpE : out std_logic;
|
||||
JumpXY : out std_logic;
|
||||
Call : out std_logic;
|
||||
RstP : out std_logic;
|
||||
LDZ : out std_logic;
|
||||
LDW : out std_logic;
|
||||
LDSPHL : out std_logic;
|
||||
Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None
|
||||
ExchangeDH : out std_logic;
|
||||
ExchangeRp : out std_logic;
|
||||
ExchangeAF : out std_logic;
|
||||
ExchangeRS : out std_logic;
|
||||
I_DJNZ : out std_logic;
|
||||
I_CPL : out std_logic;
|
||||
I_CCF : out std_logic;
|
||||
I_SCF : out std_logic;
|
||||
I_RETN : out std_logic;
|
||||
I_BT : out std_logic;
|
||||
I_BC : out std_logic;
|
||||
I_BTR : out std_logic;
|
||||
I_RLD : out std_logic;
|
||||
I_RRD : out std_logic;
|
||||
I_INRC : out std_logic;
|
||||
SetDI : out std_logic;
|
||||
SetEI : out std_logic;
|
||||
IMode : out std_logic_vector(1 downto 0);
|
||||
Halt : out std_logic;
|
||||
NoRead : out std_logic;
|
||||
Write : out std_logic;
|
||||
XYbit_undoc : out std_logic
|
||||
);
|
||||
end component;
|
||||
|
||||
component T80_ALU
|
||||
generic(
|
||||
Mode : integer := 0;
|
||||
Flag_C : integer := 0;
|
||||
Flag_N : integer := 1;
|
||||
Flag_P : integer := 2;
|
||||
Flag_X : integer := 3;
|
||||
Flag_H : integer := 4;
|
||||
Flag_Y : integer := 5;
|
||||
Flag_Z : integer := 6;
|
||||
Flag_S : integer := 7
|
||||
);
|
||||
port(
|
||||
Arith16 : in std_logic;
|
||||
Z16 : in std_logic;
|
||||
ALU_Op : in std_logic_vector(3 downto 0);
|
||||
IR : in std_logic_vector(5 downto 0);
|
||||
ISet : in std_logic_vector(1 downto 0);
|
||||
BusA : in std_logic_vector(7 downto 0);
|
||||
BusB : in std_logic_vector(7 downto 0);
|
||||
F_In : in std_logic_vector(7 downto 0);
|
||||
Q : out std_logic_vector(7 downto 0);
|
||||
F_Out : out std_logic_vector(7 downto 0)
|
||||
);
|
||||
end component;
|
||||
|
||||
end;
|
||||
114
tutorials/soc/lesson7c/T80_Reg.vhd
Normal file
114
tutorials/soc/lesson7c/T80_Reg.vhd
Normal file
@@ -0,0 +1,114 @@
|
||||
-- ****
|
||||
-- T80(b) core. In an effort to merge and maintain bug fixes ....
|
||||
--
|
||||
--
|
||||
-- Ver 300 started tidyup
|
||||
-- MikeJ March 2005
|
||||
-- Latest version from www.fpgaarcade.com (original www.opencores.org)
|
||||
--
|
||||
-- ****
|
||||
--
|
||||
-- T80 Registers, technology independent
|
||||
--
|
||||
-- Version : 0244
|
||||
--
|
||||
-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
|
||||
--
|
||||
-- All rights reserved
|
||||
--
|
||||
-- Redistribution and use in source and synthezised forms, with or without
|
||||
-- modification, are permitted provided that the following conditions are met:
|
||||
--
|
||||
-- Redistributions of source code must retain the above copyright notice,
|
||||
-- this list of conditions and the following disclaimer.
|
||||
--
|
||||
-- Redistributions in synthesized form must reproduce the above copyright
|
||||
-- notice, this list of conditions and the following disclaimer in the
|
||||
-- documentation and/or other materials provided with the distribution.
|
||||
--
|
||||
-- Neither the name of the author nor the names of other contributors may
|
||||
-- be used to endorse or promote products derived from this software without
|
||||
-- specific prior written permission.
|
||||
--
|
||||
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
|
||||
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
-- POSSIBILITY OF SUCH DAMAGE.
|
||||
--
|
||||
-- Please report bugs to the author, but before you do so, please
|
||||
-- make sure that this is not a derivative work and that
|
||||
-- you have the latest version of this file.
|
||||
--
|
||||
-- The latest version of this file can be found at:
|
||||
-- http://www.opencores.org/cvsweb.shtml/t51/
|
||||
--
|
||||
-- Limitations :
|
||||
--
|
||||
-- File history :
|
||||
--
|
||||
-- 0242 : Initial release
|
||||
--
|
||||
-- 0244 : Changed to single register file
|
||||
--
|
||||
|
||||
library IEEE;
|
||||
use IEEE.std_logic_1164.all;
|
||||
use IEEE.numeric_std.all;
|
||||
|
||||
entity T80_Reg is
|
||||
port(
|
||||
Clk : in std_logic;
|
||||
CEN : in std_logic;
|
||||
WEH : in std_logic;
|
||||
WEL : in std_logic;
|
||||
AddrA : in std_logic_vector(2 downto 0);
|
||||
AddrB : in std_logic_vector(2 downto 0);
|
||||
AddrC : in std_logic_vector(2 downto 0);
|
||||
DIH : in std_logic_vector(7 downto 0);
|
||||
DIL : in std_logic_vector(7 downto 0);
|
||||
DOAH : out std_logic_vector(7 downto 0);
|
||||
DOAL : out std_logic_vector(7 downto 0);
|
||||
DOBH : out std_logic_vector(7 downto 0);
|
||||
DOBL : out std_logic_vector(7 downto 0);
|
||||
DOCH : out std_logic_vector(7 downto 0);
|
||||
DOCL : out std_logic_vector(7 downto 0)
|
||||
);
|
||||
end T80_Reg;
|
||||
|
||||
architecture rtl of T80_Reg is
|
||||
|
||||
type Register_Image is array (natural range <>) of std_logic_vector(7 downto 0);
|
||||
signal RegsH : Register_Image(0 to 7);
|
||||
signal RegsL : Register_Image(0 to 7);
|
||||
|
||||
begin
|
||||
|
||||
process (Clk)
|
||||
begin
|
||||
if Clk'event and Clk = '1' then
|
||||
if CEN = '1' then
|
||||
if WEH = '1' then
|
||||
RegsH(to_integer(unsigned(AddrA))) <= DIH;
|
||||
end if;
|
||||
if WEL = '1' then
|
||||
RegsL(to_integer(unsigned(AddrA))) <= DIL;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
DOAH <= RegsH(to_integer(unsigned(AddrA)));
|
||||
DOAL <= RegsL(to_integer(unsigned(AddrA)));
|
||||
DOBH <= RegsH(to_integer(unsigned(AddrB)));
|
||||
DOBL <= RegsL(to_integer(unsigned(AddrB)));
|
||||
DOCH <= RegsH(to_integer(unsigned(AddrC)));
|
||||
DOCL <= RegsL(to_integer(unsigned(AddrC)));
|
||||
|
||||
end;
|
||||
190
tutorials/soc/lesson7c/T80s.vhd
Normal file
190
tutorials/soc/lesson7c/T80s.vhd
Normal file
@@ -0,0 +1,190 @@
|
||||
--
|
||||
-- Z80 compatible microprocessor core, synchronous top level
|
||||
-- Different timing than the original z80
|
||||
-- Inputs needs to be synchronous and outputs may glitch
|
||||
--
|
||||
-- Version : 0242
|
||||
--
|
||||
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
|
||||
--
|
||||
-- All rights reserved
|
||||
--
|
||||
-- Redistribution and use in source and synthezised forms, with or without
|
||||
-- modification, are permitted provided that the following conditions are met:
|
||||
--
|
||||
-- Redistributions of source code must retain the above copyright notice,
|
||||
-- this list of conditions and the following disclaimer.
|
||||
--
|
||||
-- Redistributions in synthesized form must reproduce the above copyright
|
||||
-- notice, this list of conditions and the following disclaimer in the
|
||||
-- documentation and/or other materials provided with the distribution.
|
||||
--
|
||||
-- Neither the name of the author nor the names of other contributors may
|
||||
-- be used to endorse or promote products derived from this software without
|
||||
-- specific prior written permission.
|
||||
--
|
||||
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
|
||||
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
-- POSSIBILITY OF SUCH DAMAGE.
|
||||
--
|
||||
-- Please report bugs to the author, but before you do so, please
|
||||
-- make sure that this is not a derivative work and that
|
||||
-- you have the latest version of this file.
|
||||
--
|
||||
-- The latest version of this file can be found at:
|
||||
-- http://www.opencores.org/cvsweb.shtml/t80/
|
||||
--
|
||||
-- Limitations :
|
||||
--
|
||||
-- File history :
|
||||
--
|
||||
-- 0208 : First complete release
|
||||
--
|
||||
-- 0210 : Fixed read with wait
|
||||
--
|
||||
-- 0211 : Fixed interrupt cycle
|
||||
--
|
||||
-- 0235 : Updated for T80 interface change
|
||||
--
|
||||
-- 0236 : Added T2Write generic
|
||||
--
|
||||
-- 0237 : Fixed T2Write with wait state
|
||||
--
|
||||
-- 0238 : Updated for T80 interface change
|
||||
--
|
||||
-- 0240 : Updated for T80 interface change
|
||||
--
|
||||
-- 0242 : Updated for T80 interface change
|
||||
--
|
||||
|
||||
library IEEE;
|
||||
use IEEE.std_logic_1164.all;
|
||||
use IEEE.numeric_std.all;
|
||||
use work.T80_Pack.all;
|
||||
|
||||
entity T80s is
|
||||
generic(
|
||||
Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
|
||||
T2Write : integer := 0; -- 0 => WR_n active in T3, /=0 => WR_n active in T2
|
||||
IOWait : integer := 1 -- 0 => Single cycle I/O, 1 => Std I/O cycle
|
||||
);
|
||||
port(
|
||||
RESET_n : in std_logic;
|
||||
CLK_n : in std_logic;
|
||||
WAIT_n : in std_logic;
|
||||
INT_n : in std_logic;
|
||||
NMI_n : in std_logic;
|
||||
BUSRQ_n : in std_logic;
|
||||
M1_n : out std_logic;
|
||||
MREQ_n : out std_logic;
|
||||
IORQ_n : out std_logic;
|
||||
RD_n : out std_logic;
|
||||
WR_n : out std_logic;
|
||||
RFSH_n : out std_logic;
|
||||
HALT_n : out std_logic;
|
||||
BUSAK_n : out std_logic;
|
||||
A : out std_logic_vector(15 downto 0);
|
||||
DI : in std_logic_vector(7 downto 0);
|
||||
DO : out std_logic_vector(7 downto 0)
|
||||
);
|
||||
end T80s;
|
||||
|
||||
architecture rtl of T80s is
|
||||
|
||||
signal CEN : std_logic;
|
||||
signal IntCycle_n : std_logic;
|
||||
signal NoRead : std_logic;
|
||||
signal Write : std_logic;
|
||||
signal IORQ : std_logic;
|
||||
signal DI_Reg : std_logic_vector(7 downto 0);
|
||||
signal MCycle : std_logic_vector(2 downto 0);
|
||||
signal TState : std_logic_vector(2 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
CEN <= '1';
|
||||
|
||||
u0 : T80
|
||||
generic map(
|
||||
Mode => Mode,
|
||||
IOWait => IOWait)
|
||||
port map(
|
||||
CEN => CEN,
|
||||
M1_n => M1_n,
|
||||
IORQ => IORQ,
|
||||
NoRead => NoRead,
|
||||
Write => Write,
|
||||
RFSH_n => RFSH_n,
|
||||
HALT_n => HALT_n,
|
||||
WAIT_n => Wait_n,
|
||||
INT_n => INT_n,
|
||||
NMI_n => NMI_n,
|
||||
RESET_n => RESET_n,
|
||||
BUSRQ_n => BUSRQ_n,
|
||||
BUSAK_n => BUSAK_n,
|
||||
CLK_n => CLK_n,
|
||||
A => A,
|
||||
DInst => DI,
|
||||
DI => DI_Reg,
|
||||
DO => DO,
|
||||
MC => MCycle,
|
||||
TS => TState,
|
||||
IntCycle_n => IntCycle_n);
|
||||
|
||||
process (RESET_n, CLK_n)
|
||||
begin
|
||||
if RESET_n = '0' then
|
||||
RD_n <= '1';
|
||||
WR_n <= '1';
|
||||
IORQ_n <= '1';
|
||||
MREQ_n <= '1';
|
||||
DI_Reg <= "00000000";
|
||||
elsif CLK_n'event and CLK_n = '1' then
|
||||
RD_n <= '1';
|
||||
WR_n <= '1';
|
||||
IORQ_n <= '1';
|
||||
MREQ_n <= '1';
|
||||
if MCycle = "001" then
|
||||
if TState = "001" or (TState = "010" and Wait_n = '0') then
|
||||
RD_n <= not IntCycle_n;
|
||||
MREQ_n <= not IntCycle_n;
|
||||
IORQ_n <= IntCycle_n;
|
||||
end if;
|
||||
if TState = "011" then
|
||||
MREQ_n <= '0';
|
||||
end if;
|
||||
else
|
||||
if (TState = "001" or (TState = "010" and Wait_n = '0')) and NoRead = '0' and Write = '0' then
|
||||
RD_n <= '0';
|
||||
IORQ_n <= not IORQ;
|
||||
MREQ_n <= IORQ;
|
||||
end if;
|
||||
if T2Write = 0 then
|
||||
if TState = "010" and Write = '1' then
|
||||
WR_n <= '0';
|
||||
IORQ_n <= not IORQ;
|
||||
MREQ_n <= IORQ;
|
||||
end if;
|
||||
else
|
||||
if (TState = "001" or (TState = "010" and Wait_n = '0')) and Write = '1' then
|
||||
WR_n <= '0';
|
||||
IORQ_n <= not IORQ;
|
||||
MREQ_n <= IORQ;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
if TState = "010" and Wait_n = '1' then
|
||||
DI_Reg <= DI;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end;
|
||||
95
tutorials/soc/lesson7c/bin2c.c
Normal file
95
tutorials/soc/lesson7c/bin2c.c
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* bin2c.c - binary to c array converter.
|
||||
*
|
||||
* Written by
|
||||
* Marco van den Heuvel <blackystardust68@yahoo.com>
|
||||
*
|
||||
* This file is part of VICE, the Versatile Commodore Emulator.
|
||||
* See README for copyright notice.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void generate_c_file(char *in_filename, char *out_filename, char *array)
|
||||
{
|
||||
FILE *infile, *outfile;
|
||||
int amount, start, i;
|
||||
unsigned char buffer[8];
|
||||
|
||||
infile=fopen(in_filename,"rb");
|
||||
if (infile==NULL)
|
||||
{
|
||||
printf("cannot open %s for reading\n",in_filename);
|
||||
return;
|
||||
}
|
||||
|
||||
outfile=fopen(out_filename,"wb");
|
||||
if (outfile==NULL)
|
||||
{
|
||||
printf("cannot open %s for writing\n",out_filename);
|
||||
fclose(infile);
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(outfile,"/* Autogenerated file, DO NOT EDIT !!! */\n\n");
|
||||
fprintf(outfile,"%s = {\n", array);
|
||||
|
||||
start = 1;
|
||||
while (!feof(infile))
|
||||
{
|
||||
amount = fread(buffer, 1, 8, infile);
|
||||
if (start == 0)
|
||||
{
|
||||
fprintf(outfile, ",\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
start = 0;
|
||||
}
|
||||
if (amount >= 1)
|
||||
{
|
||||
fprintf(outfile, " 0x%02X", buffer[0]);
|
||||
}
|
||||
for (i = 2; i < 9; i++)
|
||||
{
|
||||
if (amount >= i)
|
||||
{
|
||||
fprintf(outfile, ", 0x%02X", buffer[i - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(outfile,"\n};\n");
|
||||
|
||||
fclose(infile);
|
||||
fclose(outfile);
|
||||
return;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc<4)
|
||||
{
|
||||
printf("too few arguments\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
generate_c_file(argv[1], argv[2], argv[3]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
88
tutorials/soc/lesson7c/block_io.c
Normal file
88
tutorials/soc/lesson7c/block_io.c
Normal file
@@ -0,0 +1,88 @@
|
||||
/*------------------------------------------------------------------------/
|
||||
/ block_io.c
|
||||
/
|
||||
/ simple block_io layer for MIST board. Can be used as a replacement for
|
||||
/ mmc.
|
||||
/
|
||||
/ This code is in the public domain
|
||||
/ (c) 2016 by Till Harbaum
|
||||
/--------------------------------------------------------------------------/
|
||||
*/
|
||||
|
||||
#include "diskio.h"
|
||||
|
||||
// block io registers implemented in block_io.v
|
||||
__sfr __at 0x00 LBA0Port;
|
||||
__sfr __at 0x01 LBA1Port;
|
||||
__sfr __at 0x02 LBA2Port;
|
||||
__sfr __at 0x03 LBA3Port;
|
||||
__sfr __at 0x04 ControlPort;
|
||||
__sfr __at 0x05 DataPort;
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
Public Functions
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Initialize Disk Drive */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DSTATUS disk_initialize (void) {
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Read partial sector */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DRESULT disk_readp (
|
||||
BYTE *buff, /* Pointer to the read buffer (NULL:Read bytes are forwarded to the stream) */
|
||||
DWORD sector, /* Sector number (LBA) */
|
||||
UINT offset, /* Byte offset to read from (0..511) */
|
||||
UINT count /* Number of bytes to read (ofs + cnt mus be <= 512) */
|
||||
)
|
||||
{
|
||||
static BYTE buffer[512];
|
||||
static DWORD buffer_sector = 0xffffffff;
|
||||
BYTE *p;
|
||||
|
||||
// check if sector is already in buffer
|
||||
if(buffer_sector != sector) {
|
||||
BYTE cnt;
|
||||
|
||||
// need to load sector into buffer
|
||||
|
||||
// write 32 bit sector address into block_io controller
|
||||
LBA0Port = (sector >> 24) & 0xff;
|
||||
LBA1Port = (sector >> 16) & 0xff;
|
||||
LBA2Port = (sector >> 8) & 0xff;
|
||||
LBA3Port = (sector >> 0) & 0xff;
|
||||
|
||||
// trigger read
|
||||
ControlPort = 0x01;
|
||||
|
||||
// wait for data to be ready
|
||||
while(ControlPort & 1);
|
||||
|
||||
// read data
|
||||
p=buffer;
|
||||
for(cnt=0;cnt<128;cnt++) {
|
||||
*p++ = DataPort;
|
||||
*p++ = DataPort;
|
||||
*p++ = DataPort;
|
||||
*p++ = DataPort;
|
||||
}
|
||||
|
||||
buffer_sector = sector;
|
||||
}
|
||||
|
||||
// return data from sector buffer
|
||||
p = buffer + offset;
|
||||
while(count--)
|
||||
*buff++ = *p++;
|
||||
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
128
tutorials/soc/lesson7c/block_io.v
Normal file
128
tutorials/soc/lesson7c/block_io.v
Normal file
@@ -0,0 +1,128 @@
|
||||
//
|
||||
// block_io.v
|
||||
//
|
||||
// This file implements a simple block interface to the SD card.
|
||||
// It can be used instead of the sd_card.v whenever there's no need
|
||||
// on core side for a full sd card interface. This is usually the
|
||||
// case if the core is not ported from/to other boards.
|
||||
//
|
||||
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
|
||||
//
|
||||
// This source file is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the Lesser GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
module block_io (
|
||||
// link to user_io for io controller
|
||||
output reg [31:0] io_lba,
|
||||
output reg io_rd,
|
||||
output io_wr,
|
||||
input io_ack,
|
||||
output io_conf,
|
||||
output io_sdhc,
|
||||
|
||||
// data coming in from io controller
|
||||
input [7:0] io_din,
|
||||
input io_din_strobe,
|
||||
|
||||
// data going out to io controller
|
||||
output [7:0] io_dout,
|
||||
input io_dout_strobe,
|
||||
|
||||
// interface to the cpu
|
||||
input reset,
|
||||
input clk,
|
||||
input rd,
|
||||
input wr,
|
||||
input [7:0] din,
|
||||
input [2:0] addr,
|
||||
output [7:0] dout
|
||||
);
|
||||
|
||||
assign io_wr = 1'b0; // we never write ...
|
||||
assign io_dout = 1'b0; // ... and thus never send data to the io controller
|
||||
assign io_conf = 1'b0; // we need no configuration info from the SD card
|
||||
|
||||
// raise io_rd signal whenever SoC requests a sector and release it
|
||||
// once IO controller acknowleges it
|
||||
always @(posedge io_rd_req or posedge io_ack) begin
|
||||
if(io_ack) io_rd <= 1'b0;
|
||||
else io_rd <= 1'b1;
|
||||
end
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// --------------------- sector buffer ---------------------------
|
||||
// ---------------------------------------------------------------
|
||||
reg [7:0] buffer [511:0];
|
||||
reg [8:0] buffer_wptr; // buffer write pointer
|
||||
reg [8:0] buffer_rptr; // buffer read pointer
|
||||
|
||||
// IO controller writes to buffer
|
||||
always @(posedge io_din_strobe)
|
||||
buffer[buffer_wptr] <= io_din;
|
||||
|
||||
// buffer is not busy anymore if IO controller ack'd io_rd and has
|
||||
// tranferred 512 bytes (counter wrapped to 0 again)
|
||||
wire busy = io_rd || (buffer_wptr != 0);
|
||||
|
||||
// write pointer increases whenever io controller writes a byte. It's reset
|
||||
// when the SoC requests a new sector.
|
||||
always @(negedge io_din_strobe or posedge io_rd_req) begin
|
||||
if(io_rd_req) buffer_wptr <= 9'd0;
|
||||
else buffer_wptr <= buffer_wptr + 9'd1;
|
||||
end
|
||||
|
||||
// clock data out of buffer to allow for embedded ram
|
||||
reg [7:0] buffer_dout;
|
||||
always @(posedge clk)
|
||||
buffer_dout <= buffer[buffer_rptr];
|
||||
|
||||
// read pointer increases whenever cpu reads a byte from the buffer. It's
|
||||
// reset when the SoC requests a new sector
|
||||
always @(posedge cpu_byte_rd or posedge io_rd_req) begin
|
||||
if(io_rd_req) buffer_rptr <= 9'd0;
|
||||
else buffer_rptr <= buffer_rptr + 9'd1;
|
||||
end
|
||||
|
||||
// ---------------------- CPU register read/write -----------------
|
||||
|
||||
reg io_rd_req; // cpu triggers a sector read
|
||||
reg cpu_byte_rd; // cpu read a byte
|
||||
|
||||
// only addresses 4 and 5 can be read and return valid data
|
||||
assign dout = (addr == 4)?{7'b0000000, busy }:
|
||||
(addr == 5)?buffer_dout:
|
||||
8'hff;
|
||||
|
||||
always @(negedge clk) begin
|
||||
io_rd_req <= 1'b0;
|
||||
cpu_byte_rd <= 1'b0;
|
||||
|
||||
// cpu reads from the data register
|
||||
if(rd && addr == 5)
|
||||
cpu_byte_rd <= 1'b1;
|
||||
|
||||
if(wr) begin
|
||||
case(addr)
|
||||
// cpu writes the four bytes of the sector address
|
||||
0: io_lba[31:24] <= din;
|
||||
1: io_lba[23:16] <= din;
|
||||
2: io_lba[15: 8] <= din;
|
||||
3: io_lba[ 7: 0] <= din;
|
||||
// cpu writes 1 to bit 0 of the control register
|
||||
4: io_rd_req <= din[0];
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
138
tutorials/soc/lesson7c/boot_rom.c
Normal file
138
tutorials/soc/lesson7c/boot_rom.c
Normal file
@@ -0,0 +1,138 @@
|
||||
// boot_rom.c
|
||||
// Boot ROM for the Z80 system on a chip (SoC)
|
||||
// (c) 2015 Till Harbaum
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "pff.h"
|
||||
|
||||
extern unsigned char font[];
|
||||
|
||||
unsigned char cur_x=0, cur_y=0;
|
||||
void putchar(char c) {
|
||||
unsigned char *p;
|
||||
unsigned char *dptr = (unsigned char*)(160*(8*cur_y) + 8*cur_x);
|
||||
char i, j;
|
||||
|
||||
if(c < 32) {
|
||||
if(c == '\r')
|
||||
cur_x=0;
|
||||
|
||||
if(c == '\n') {
|
||||
cur_y++;
|
||||
cur_x=0;
|
||||
|
||||
if(cur_y >= 12)
|
||||
cur_y = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(c < 0) return;
|
||||
|
||||
p = font+8*(unsigned char)(c-32);
|
||||
for(i=0;i<8;i++) {
|
||||
unsigned char l = *p++;
|
||||
for(j=0;j<8;j++) {
|
||||
*dptr++ = (l & 0x80)?0xff:0x00;
|
||||
l <<= 1;
|
||||
}
|
||||
dptr += (160-8);
|
||||
}
|
||||
|
||||
cur_x++;
|
||||
if(cur_x >= 20) {
|
||||
cur_x = 0;
|
||||
cur_y++;
|
||||
|
||||
if(cur_y >= 12)
|
||||
cur_y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
volatile unsigned char global_color = 0x55;
|
||||
|
||||
// 16 topleft pixels flicker so we know the vsync interrupt is working
|
||||
void isr(void) __interrupt {
|
||||
unsigned char x, y;
|
||||
unsigned char *v = (unsigned char*)(160*2+2);
|
||||
|
||||
for(y=0;y<4;y++) {
|
||||
for(x=0;x<4;x++)
|
||||
*v++ = global_color;
|
||||
|
||||
v += 160-4;
|
||||
}
|
||||
|
||||
global_color++;
|
||||
|
||||
__asm
|
||||
ei
|
||||
__endasm;
|
||||
}
|
||||
|
||||
void cls(void) {
|
||||
unsigned char i;
|
||||
unsigned char *p = (unsigned char*)0;
|
||||
|
||||
for(i=0;i<100;i++) {
|
||||
memset(p, 0, 160);
|
||||
p+=160;
|
||||
}
|
||||
}
|
||||
|
||||
void ei() {
|
||||
// set interrupt mode 1 and enable interrupts
|
||||
__asm
|
||||
im 1
|
||||
ei
|
||||
__endasm;
|
||||
}
|
||||
|
||||
void die (FRESULT rc) {
|
||||
printf("Fail rc=%u", rc);
|
||||
for (;;) ;
|
||||
}
|
||||
|
||||
|
||||
void main() {
|
||||
FATFS fatfs; /* File system object */
|
||||
DIR dir; /* Directory object */
|
||||
FILINFO fno; /* File information object */
|
||||
FRESULT rc;
|
||||
char i;
|
||||
|
||||
ei();
|
||||
cls();
|
||||
|
||||
puts(" << Z80 SoC >>");
|
||||
|
||||
printf("Reading SD card ...\r");
|
||||
|
||||
rc = pf_mount(&fatfs);
|
||||
if (rc) die(rc);
|
||||
|
||||
// list first 11 files on card
|
||||
rc = pf_opendir(&dir, "/");
|
||||
if (rc) die(rc);
|
||||
|
||||
printf(" \r");
|
||||
for(i=0;i<11;i++) {
|
||||
rc = pf_readdir(&dir, &fno);
|
||||
if (rc != FR_OK || fno.fname[0] == 0) break;
|
||||
if (fno.fattrib & AM_DIR) {
|
||||
printf("<DIR> %s\n", fno.fname);
|
||||
} else {
|
||||
printf(" %s\n", fno.fname);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
printf("Open CORE.RBF ...\n");
|
||||
rc = pf_open("CORE.RBF");
|
||||
if (rc) die(rc);
|
||||
#endif
|
||||
|
||||
while(1);
|
||||
}
|
||||
116
tutorials/soc/lesson7c/data_io.v
Normal file
116
tutorials/soc/lesson7c/data_io.v
Normal file
@@ -0,0 +1,116 @@
|
||||
//
|
||||
// data_io.v
|
||||
//
|
||||
// io controller writable ram for the MiST board
|
||||
// http://code.google.com/p/mist-board/
|
||||
//
|
||||
// ZX Spectrum adapted version
|
||||
//
|
||||
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
|
||||
//
|
||||
// This source file is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
module data_io (
|
||||
// io controller spi interface
|
||||
input sck,
|
||||
input ss,
|
||||
input sdi,
|
||||
|
||||
output downloading, // signal indicating an active download
|
||||
output reg [4:0] index, // menu index used to upload the file
|
||||
|
||||
// external ram interface
|
||||
input clk,
|
||||
output reg wr,
|
||||
output reg [24:0] addr,
|
||||
output reg [7:0] data
|
||||
);
|
||||
|
||||
// *********************************************************************************
|
||||
// spi client
|
||||
// *********************************************************************************
|
||||
|
||||
// this core supports only the display related OSD commands
|
||||
// of the minimig
|
||||
reg [6:0] sbuf;
|
||||
reg [7:0] cmd;
|
||||
reg [4:0] cnt;
|
||||
reg rclk;
|
||||
|
||||
localparam UIO_FILE_TX = 8'h53;
|
||||
localparam UIO_FILE_TX_DAT = 8'h54;
|
||||
localparam UIO_FILE_INDEX = 8'h55;
|
||||
|
||||
assign downloading = downloading_reg;
|
||||
reg downloading_reg = 1'b0;
|
||||
|
||||
// data_io has its own SPI interface to the io controller
|
||||
always@(posedge sck, posedge ss) begin
|
||||
if(ss == 1'b1)
|
||||
cnt <= 5'd0;
|
||||
else begin
|
||||
rclk <= 1'b0;
|
||||
|
||||
// don't shift in last bit. It is evaluated directly
|
||||
// when writing to ram
|
||||
if(cnt != 15)
|
||||
sbuf <= { sbuf[5:0], sdi};
|
||||
|
||||
// increase target address after write
|
||||
if(rclk)
|
||||
addr <= addr + 1;
|
||||
|
||||
// count 0-7 8-15 8-15 ...
|
||||
if(cnt < 15) cnt <= cnt + 4'd1;
|
||||
else cnt <= 4'd8;
|
||||
|
||||
// finished command byte
|
||||
if(cnt == 7)
|
||||
cmd <= {sbuf, sdi};
|
||||
|
||||
// prepare/end transmission
|
||||
if((cmd == UIO_FILE_TX) && (cnt == 15)) begin
|
||||
// prepare
|
||||
if(sdi) begin
|
||||
addr <= 25'd0;
|
||||
downloading_reg <= 1'b1;
|
||||
end else
|
||||
downloading_reg <= 1'b0;
|
||||
end
|
||||
|
||||
// command 0x54: UIO_FILE_TX
|
||||
if((cmd == UIO_FILE_TX_DAT) && (cnt == 15)) begin
|
||||
data <= {sbuf, sdi};
|
||||
rclk <= 1'b1;
|
||||
end
|
||||
|
||||
// expose file (menu) index
|
||||
if((cmd == UIO_FILE_INDEX) && (cnt == 15))
|
||||
index <= {sbuf[3:0], sdi};
|
||||
end
|
||||
end
|
||||
|
||||
reg rclkD, rclkD2;
|
||||
always@(posedge clk) begin
|
||||
// bring rclk from spi clock domain into c64 clock domain
|
||||
rclkD <= rclk;
|
||||
rclkD2 <= rclkD;
|
||||
wr <= 1'b0;
|
||||
|
||||
if(rclkD && !rclkD2)
|
||||
wr <= 1'b1;
|
||||
end
|
||||
|
||||
endmodule
|
||||
42
tutorials/soc/lesson7c/diskio.h
Normal file
42
tutorials/soc/lesson7c/diskio.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*-----------------------------------------------------------------------
|
||||
/ PFF - Low level disk interface modlue include file (C)ChaN, 2014
|
||||
/-----------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _DISKIO_DEFINED
|
||||
#define _DISKIO_DEFINED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "integer.h"
|
||||
|
||||
|
||||
/* Status of Disk Functions */
|
||||
typedef BYTE DSTATUS;
|
||||
|
||||
|
||||
/* Results of Disk Functions */
|
||||
typedef enum {
|
||||
RES_OK = 0, /* 0: Function succeeded */
|
||||
RES_ERROR, /* 1: Disk error */
|
||||
RES_NOTRDY, /* 2: Not ready */
|
||||
RES_PARERR /* 3: Invalid parameter */
|
||||
} DRESULT;
|
||||
|
||||
|
||||
/*---------------------------------------*/
|
||||
/* Prototypes for disk control functions */
|
||||
|
||||
DSTATUS disk_initialize (void);
|
||||
DRESULT disk_readp (BYTE* buff, DWORD sector, UINT offser, UINT count);
|
||||
DRESULT disk_writep (const BYTE* buff, DWORD sc);
|
||||
|
||||
#define STA_NOINIT 0x01 /* Drive not initialized */
|
||||
#define STA_NODISK 0x02 /* No medium in the drive */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DISKIO_DEFINED */
|
||||
101
tutorials/soc/lesson7c/font.c
Normal file
101
tutorials/soc/lesson7c/font.c
Normal file
@@ -0,0 +1,101 @@
|
||||
/* Autogenerated file, DO NOT EDIT !!! */
|
||||
|
||||
unsigned char font[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x30, 0x78, 0x78, 0x78, 0x30, 0x00, 0x30, 0x00,
|
||||
0xCC, 0x66, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x36, 0x7F, 0x36, 0x36, 0x7F, 0x36, 0x00,
|
||||
0x7C, 0xD6, 0xD0, 0x7C, 0x16, 0xD6, 0x7C, 0x10,
|
||||
0xE3, 0xA6, 0xEC, 0x18, 0x37, 0x65, 0xC7, 0x00,
|
||||
0x38, 0x4C, 0x38, 0x45, 0xC6, 0xCE, 0x7A, 0x01,
|
||||
0x06, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0C,
|
||||
0x60, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60,
|
||||
0x10, 0x54, 0x38, 0xFE, 0x38, 0x54, 0x10, 0x00,
|
||||
0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30,
|
||||
0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||
0x00, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00,
|
||||
0x7C, 0xCE, 0xDE, 0xFE, 0xEE, 0xCE, 0x7C, 0x00,
|
||||
0x1C, 0x3C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x00,
|
||||
0x7C, 0xCE, 0x0E, 0x1C, 0x38, 0x70, 0xFE, 0x00,
|
||||
0x7C, 0xCE, 0x0E, 0x3C, 0x0E, 0xCE, 0x7C, 0x00,
|
||||
0xCE, 0xCE, 0xCE, 0xCE, 0xFE, 0x0E, 0x0E, 0x00,
|
||||
0xFE, 0xE0, 0xE0, 0xFC, 0x0E, 0x0E, 0xFC, 0x00,
|
||||
0x7C, 0xE6, 0xE0, 0xFC, 0xE6, 0xE6, 0x7C, 0x00,
|
||||
0xFE, 0x06, 0x0E, 0x1C, 0x38, 0x38, 0x38, 0x00,
|
||||
0x7C, 0xE6, 0xE6, 0x7C, 0xE6, 0xE6, 0x7C, 0x00,
|
||||
0x7C, 0xCE, 0xCE, 0x7E, 0x0E, 0x0E, 0xFC, 0x00,
|
||||
0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
|
||||
0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x60, 0x00,
|
||||
0x00, 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00,
|
||||
0x00, 0x30, 0x18, 0x0C, 0x18, 0x30, 0x00, 0x00,
|
||||
0x7C, 0xC6, 0x0E, 0x1C, 0x38, 0x00, 0x38, 0x00,
|
||||
0x7C, 0xC6, 0xDE, 0xDE, 0xDC, 0xC0, 0x7C, 0x00,
|
||||
0x7C, 0xE6, 0xE6, 0xE6, 0xFE, 0xE6, 0xE6, 0x00,
|
||||
0xFC, 0xE6, 0xE6, 0xFC, 0xE6, 0xE6, 0xFC, 0x00,
|
||||
0x7C, 0xE6, 0xE0, 0xE0, 0xE6, 0xE6, 0x7C, 0x00,
|
||||
0xFC, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xFC, 0x00,
|
||||
0xFE, 0xE0, 0xE0, 0xFE, 0xE0, 0xE0, 0xFE, 0x00,
|
||||
0xFE, 0xE0, 0xE0, 0xFE, 0xE0, 0xE0, 0xE0, 0x00,
|
||||
0x7C, 0xE6, 0xE0, 0xEE, 0xE6, 0xE6, 0x7C, 0x00,
|
||||
0xE6, 0xE6, 0xE6, 0xFE, 0xE6, 0xE6, 0xE6, 0x00,
|
||||
0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x00,
|
||||
0x0E, 0x0E, 0x0E, 0x0E, 0xCE, 0xCE, 0x7C, 0x00,
|
||||
0xE6, 0xEC, 0xF8, 0xF0, 0xF8, 0xEC, 0xE6, 0x00,
|
||||
0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xFE, 0x00,
|
||||
0xC6, 0xEE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0x00,
|
||||
0xC6, 0xE6, 0xF6, 0xFE, 0xEE, 0xE6, 0xE6, 0x00,
|
||||
0x7C, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x7C, 0x00,
|
||||
0xFC, 0xE6, 0xE6, 0xFC, 0xE0, 0xE0, 0xE0, 0x00,
|
||||
0x7C, 0xE6, 0xE6, 0xE6, 0xE6, 0xEA, 0x74, 0x02,
|
||||
0xFC, 0xE6, 0xE6, 0xFC, 0xE6, 0xE6, 0xE6, 0x00,
|
||||
0x7C, 0xE6, 0xE0, 0x7C, 0x0E, 0xCE, 0x7C, 0x00,
|
||||
0xFE, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x00,
|
||||
0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x7C, 0x00,
|
||||
0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0x7C, 0x38, 0x00,
|
||||
0xC6, 0xC6, 0xC6, 0xD6, 0xD6, 0xFE, 0xFC, 0x00,
|
||||
0xE3, 0x76, 0x3C, 0x18, 0x3C, 0x6E, 0xC7, 0x00,
|
||||
0xE6, 0xE6, 0x7C, 0x38, 0x38, 0x38, 0x38, 0x00,
|
||||
0xFE, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0xFE, 0x00,
|
||||
0x1C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1C,
|
||||
0x00, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x00,
|
||||
0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x70,
|
||||
0x18, 0x3C, 0x66, 0xC3, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
|
||||
0x30, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7C, 0x0E, 0x7E, 0xCE, 0x7E, 0x00,
|
||||
0xC0, 0xC0, 0xFC, 0xE6, 0xE6, 0xE6, 0xFC, 0x00,
|
||||
0x00, 0x00, 0x7C, 0xE6, 0xE0, 0xE6, 0x7C, 0x00,
|
||||
0x06, 0x06, 0x7E, 0xCE, 0xCE, 0xCE, 0x7E, 0x00,
|
||||
0x00, 0x00, 0x7C, 0xE6, 0xFE, 0xE0, 0x7E, 0x00,
|
||||
0x3C, 0x70, 0x70, 0xFC, 0x70, 0x70, 0x70, 0x00,
|
||||
0x00, 0x00, 0x7C, 0xCE, 0xCE, 0x7E, 0x0E, 0x7C,
|
||||
0xC0, 0xC0, 0xFC, 0xE6, 0xE6, 0xE6, 0xE6, 0x00,
|
||||
0x18, 0x00, 0x18, 0x38, 0x38, 0x38, 0x38, 0x00,
|
||||
0x0C, 0x00, 0x0C, 0x1C, 0x1C, 0x1C, 0x1C, 0xF8,
|
||||
0xC0, 0xC0, 0xCC, 0xD8, 0xF0, 0xD8, 0xCC, 0x00,
|
||||
0x18, 0x18, 0x38, 0x38, 0x38, 0x38, 0x38, 0x00,
|
||||
0x00, 0x00, 0xFC, 0xD6, 0xD6, 0xD6, 0xD6, 0x00,
|
||||
0x00, 0x00, 0xFC, 0xE6, 0xE6, 0xE6, 0xE6, 0x00,
|
||||
0x00, 0x00, 0x7C, 0xE6, 0xE6, 0xE6, 0x7C, 0x00,
|
||||
0x00, 0x00, 0xFC, 0xE6, 0xE6, 0xFC, 0xE0, 0xE0,
|
||||
0x00, 0x00, 0x7E, 0xCE, 0xCE, 0x7E, 0x0E, 0x0E,
|
||||
0x00, 0x00, 0xFC, 0xE6, 0xE0, 0xE0, 0xE0, 0x00,
|
||||
0x00, 0x00, 0x7E, 0xE0, 0x7C, 0x0E, 0xFC, 0x00,
|
||||
0x18, 0x18, 0x7E, 0x38, 0x38, 0x38, 0x38, 0x00,
|
||||
0x00, 0x00, 0xE6, 0xE6, 0xE6, 0xE6, 0x7E, 0x00,
|
||||
0x00, 0x00, 0xE6, 0xE6, 0xE6, 0x6C, 0x38, 0x00,
|
||||
0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xFC, 0x00,
|
||||
0x00, 0x00, 0xE6, 0x7C, 0x38, 0x7C, 0xCE, 0x00,
|
||||
0x00, 0x00, 0xCE, 0xCE, 0xCE, 0x7E, 0x0E, 0xFC,
|
||||
0x00, 0x00, 0xFE, 0x1C, 0x38, 0x70, 0xFE, 0x00,
|
||||
0x0C, 0x18, 0x18, 0x30, 0x18, 0x18, 0x0C, 0x00,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x60, 0x30, 0x30, 0x18, 0x30, 0x30, 0x60, 0x00,
|
||||
0x70, 0xDB, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x10, 0x28, 0x44, 0xFE, 0x00, 0x00,
|
||||
|
||||
};
|
||||
BIN
tutorials/soc/lesson7c/font.fnt
Normal file
BIN
tutorials/soc/lesson7c/font.fnt
Normal file
Binary file not shown.
33
tutorials/soc/lesson7c/integer.h
Normal file
33
tutorials/soc/lesson7c/integer.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*-------------------------------------------*/
|
||||
/* Integer type definitions for FatFs module */
|
||||
/*-------------------------------------------*/
|
||||
|
||||
#ifndef _FF_INTEGER
|
||||
#define _FF_INTEGER
|
||||
|
||||
#ifdef _WIN32 /* FatFs development platform */
|
||||
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#else /* Embedded platform */
|
||||
|
||||
/* This type MUST be 8 bit */
|
||||
typedef unsigned char BYTE;
|
||||
|
||||
/* These types MUST be 16 bit */
|
||||
typedef short SHORT;
|
||||
typedef unsigned short WORD;
|
||||
typedef unsigned short WCHAR;
|
||||
|
||||
/* These types MUST be 16 bit or 32 bit */
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
|
||||
/* These types MUST be 32 bit */
|
||||
typedef long LONG;
|
||||
typedef unsigned long DWORD;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
9
tutorials/soc/lesson7c/irqvec.s
Normal file
9
tutorials/soc/lesson7c/irqvec.s
Normal file
@@ -0,0 +1,9 @@
|
||||
;; This is a nasty hack. This overwrites the reti at 0x38 which has already
|
||||
;; been set by crt0.s with a jump into our interrupt routine. This results
|
||||
;; in two contradicting entries in the hex file and the converter has to deal
|
||||
;; with that. srec_cat can be told to accept it. Quartus accepts it by default
|
||||
.globl _isr
|
||||
.area VECTOR (ABS)
|
||||
|
||||
.org 0x38
|
||||
jp _isr
|
||||
182
tutorials/soc/lesson7c/osd.v
Normal file
182
tutorials/soc/lesson7c/osd.v
Normal file
@@ -0,0 +1,182 @@
|
||||
// A simple OSD implementation. Can be hooked up between a cores
|
||||
// VGA output and the physical VGA pins
|
||||
|
||||
module osd (
|
||||
// OSDs pixel clock, should be synchronous to cores pixel clock to
|
||||
// avoid jitter.
|
||||
input pclk,
|
||||
|
||||
// SPI interface
|
||||
input sck,
|
||||
input ss,
|
||||
input sdi,
|
||||
|
||||
// VGA signals coming from core
|
||||
input [5:0] red_in,
|
||||
input [5:0] green_in,
|
||||
input [5:0] blue_in,
|
||||
input hs_in,
|
||||
input vs_in,
|
||||
|
||||
// VGA signals going to video connector
|
||||
output [5:0] red_out,
|
||||
output [5:0] green_out,
|
||||
output [5:0] blue_out,
|
||||
output hs_out,
|
||||
output vs_out
|
||||
);
|
||||
|
||||
parameter OSD_X_OFFSET = 10'd0;
|
||||
parameter OSD_Y_OFFSET = 10'd0;
|
||||
parameter OSD_COLOR = 3'd0;
|
||||
|
||||
localparam OSD_WIDTH = 10'd256;
|
||||
localparam OSD_HEIGHT = 10'd128;
|
||||
|
||||
// *********************************************************************************
|
||||
// spi client
|
||||
// *********************************************************************************
|
||||
|
||||
// this core supports only the display related OSD commands
|
||||
// of the minimig
|
||||
reg [7:0] sbuf;
|
||||
reg [7:0] cmd;
|
||||
reg [4:0] cnt;
|
||||
reg [10:0] bcnt;
|
||||
reg osd_enable;
|
||||
|
||||
reg [7:0] osd_buffer [2047:0]; // the OSD buffer itself
|
||||
|
||||
// the OSD has its own SPI interface to the io controller
|
||||
always@(posedge sck, posedge ss) begin
|
||||
if(ss == 1'b1) begin
|
||||
cnt <= 5'd0;
|
||||
bcnt <= 11'd0;
|
||||
end else begin
|
||||
sbuf <= { sbuf[6:0], sdi};
|
||||
|
||||
// 0:7 is command, rest payload
|
||||
if(cnt < 15)
|
||||
cnt <= cnt + 4'd1;
|
||||
else
|
||||
cnt <= 4'd8;
|
||||
|
||||
if(cnt == 7) begin
|
||||
cmd <= {sbuf[6:0], sdi};
|
||||
|
||||
// lower three command bits are line address
|
||||
bcnt <= { sbuf[1:0], sdi, 8'h00};
|
||||
|
||||
// command 0x40: OSDCMDENABLE, OSDCMDDISABLE
|
||||
if(sbuf[6:3] == 4'b0100)
|
||||
osd_enable <= sdi;
|
||||
end
|
||||
|
||||
// command 0x20: OSDCMDWRITE
|
||||
if((cmd[7:3] == 5'b00100) && (cnt == 15)) begin
|
||||
osd_buffer[bcnt] <= {sbuf[6:0], sdi};
|
||||
bcnt <= bcnt + 11'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// *********************************************************************************
|
||||
// video timing and sync polarity anaylsis
|
||||
// *********************************************************************************
|
||||
|
||||
// horizontal counter
|
||||
reg [9:0] h_cnt;
|
||||
reg hsD, hsD2;
|
||||
reg [9:0] hs_low, hs_high;
|
||||
wire hs_pol = hs_high < hs_low;
|
||||
wire [9:0] h_dsp_width = hs_pol?hs_low:hs_high;
|
||||
wire [9:0] h_dsp_ctr = { 1'b0, h_dsp_width[9:1] };
|
||||
|
||||
always @(posedge pclk) begin
|
||||
// bring hsync into local clock domain
|
||||
hsD <= hs_in;
|
||||
hsD2 <= hsD;
|
||||
|
||||
// falling edge of hs_in
|
||||
if(!hsD && hsD2) begin
|
||||
h_cnt <= 10'd0;
|
||||
hs_high <= h_cnt;
|
||||
end
|
||||
|
||||
// rising edge of hs_in
|
||||
else if(hsD && !hsD2) begin
|
||||
h_cnt <= 10'd0;
|
||||
hs_low <= h_cnt;
|
||||
end
|
||||
|
||||
else
|
||||
h_cnt <= h_cnt + 10'd1;
|
||||
end
|
||||
|
||||
// vertical counter
|
||||
reg [9:0] v_cnt;
|
||||
reg vsD, vsD2;
|
||||
reg [9:0] vs_low, vs_high;
|
||||
wire vs_pol = vs_high < vs_low;
|
||||
wire [9:0] v_dsp_width = vs_pol?vs_low:vs_high;
|
||||
wire [9:0] v_dsp_ctr = { 1'b0, v_dsp_width[9:1] };
|
||||
|
||||
always @(posedge hs_in) begin
|
||||
// bring vsync into local clock domain
|
||||
vsD <= vs_in;
|
||||
vsD2 <= vsD;
|
||||
|
||||
// falling edge of vs_in
|
||||
if(!vsD && vsD2) begin
|
||||
v_cnt <= 10'd0;
|
||||
vs_high <= v_cnt;
|
||||
end
|
||||
|
||||
// rising edge of vs_in
|
||||
else if(vsD && !vsD2) begin
|
||||
v_cnt <= 10'd0;
|
||||
vs_low <= v_cnt;
|
||||
end
|
||||
|
||||
else
|
||||
v_cnt <= v_cnt + 10'd1;
|
||||
end
|
||||
|
||||
// area in which OSD is being displayed
|
||||
wire [9:0] h_osd_start = h_dsp_ctr + OSD_X_OFFSET - (OSD_WIDTH >> 1);
|
||||
wire [9:0] h_osd_end = h_dsp_ctr + OSD_X_OFFSET + (OSD_WIDTH >> 1) - 1;
|
||||
wire [9:0] v_osd_start = v_dsp_ctr + OSD_Y_OFFSET - (OSD_HEIGHT >> 1);
|
||||
wire [9:0] v_osd_end = v_dsp_ctr + OSD_Y_OFFSET + (OSD_HEIGHT >> 1) - 1;
|
||||
|
||||
reg h_osd_active, v_osd_active;
|
||||
always @(posedge pclk) begin
|
||||
if(hs_in != hs_pol) begin
|
||||
if(h_cnt == h_osd_start) h_osd_active <= 1'b1;
|
||||
if(h_cnt == h_osd_end) h_osd_active <= 1'b0;
|
||||
end
|
||||
if(vs_in != vs_pol) begin
|
||||
if(v_cnt == v_osd_start) v_osd_active <= 1'b1;
|
||||
if(v_cnt == v_osd_end) v_osd_active <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
wire osd_de = osd_enable && h_osd_active && v_osd_active;
|
||||
|
||||
wire [7:0] osd_hcnt = h_cnt - h_osd_start + 7'd1; // one pixel offset for osd_byte register
|
||||
wire [6:0] osd_vcnt = v_cnt - v_osd_start;
|
||||
|
||||
wire osd_pixel = osd_byte[osd_vcnt[3:1]];
|
||||
|
||||
reg [7:0] osd_byte;
|
||||
always @(posedge pclk)
|
||||
osd_byte <= osd_buffer[{osd_vcnt[6:4], osd_hcnt}];
|
||||
|
||||
wire [2:0] osd_color = OSD_COLOR;
|
||||
assign red_out = !osd_de?red_in: {osd_pixel, osd_pixel, osd_color[2], red_in[5:3] };
|
||||
assign green_out = !osd_de?green_in:{osd_pixel, osd_pixel, osd_color[1], green_in[5:3]};
|
||||
assign blue_out = !osd_de?blue_in: {osd_pixel, osd_pixel, osd_color[0], blue_in[5:3] };
|
||||
|
||||
assign hs_out = hs_in;
|
||||
assign vs_out = vs_in;
|
||||
|
||||
endmodule
|
||||
1108
tutorials/soc/lesson7c/pff.c
Normal file
1108
tutorials/soc/lesson7c/pff.c
Normal file
File diff suppressed because it is too large
Load Diff
159
tutorials/soc/lesson7c/pff.h
Normal file
159
tutorials/soc/lesson7c/pff.h
Normal file
@@ -0,0 +1,159 @@
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Petit FatFs - FAT file system module include file R0.03 (C)ChaN, 2014
|
||||
/----------------------------------------------------------------------------/
|
||||
/ Petit FatFs module is an open source software to implement FAT file system to
|
||||
/ small embedded systems. This is a free software and is opened for education,
|
||||
/ research and commercial developments under license policy of following trems.
|
||||
/
|
||||
/ Copyright (C) 2014, ChaN, all right reserved.
|
||||
/
|
||||
/ * The Petit FatFs module is a free software and there is NO WARRANTY.
|
||||
/ * No restriction on use. You can use, modify and redistribute it for
|
||||
/ personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY.
|
||||
/ * Redistributions of source code must retain the above copyright notice.
|
||||
/
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _PFATFS
|
||||
#define _PFATFS 4004 /* Revision ID */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "integer.h"
|
||||
#include "pffconf.h"
|
||||
|
||||
#if _PFATFS != _PFFCONF
|
||||
#error Wrong configuration file (pffconf.h).
|
||||
#endif
|
||||
|
||||
#if _FS_FAT32
|
||||
#define CLUST DWORD
|
||||
#else
|
||||
#define CLUST WORD
|
||||
#endif
|
||||
|
||||
|
||||
/* File system object structure */
|
||||
|
||||
typedef struct {
|
||||
BYTE fs_type; /* FAT sub type */
|
||||
BYTE flag; /* File status flags */
|
||||
BYTE csize; /* Number of sectors per cluster */
|
||||
BYTE pad1;
|
||||
WORD n_rootdir; /* Number of root directory entries (0 on FAT32) */
|
||||
CLUST n_fatent; /* Number of FAT entries (= number of clusters + 2) */
|
||||
DWORD fatbase; /* FAT start sector */
|
||||
DWORD dirbase; /* Root directory start sector (Cluster# on FAT32) */
|
||||
DWORD database; /* Data start sector */
|
||||
DWORD fptr; /* File R/W pointer */
|
||||
DWORD fsize; /* File size */
|
||||
CLUST org_clust; /* File start cluster */
|
||||
CLUST curr_clust; /* File current cluster */
|
||||
DWORD dsect; /* File current data sector */
|
||||
} FATFS;
|
||||
|
||||
|
||||
|
||||
/* Directory object structure */
|
||||
|
||||
typedef struct {
|
||||
WORD index; /* Current read/write index number */
|
||||
BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
|
||||
CLUST sclust; /* Table start cluster (0:Static table) */
|
||||
CLUST clust; /* Current cluster */
|
||||
DWORD sect; /* Current sector */
|
||||
} DIR;
|
||||
|
||||
|
||||
|
||||
/* File status structure */
|
||||
|
||||
typedef struct {
|
||||
DWORD fsize; /* File size */
|
||||
WORD fdate; /* Last modified date */
|
||||
WORD ftime; /* Last modified time */
|
||||
BYTE fattrib; /* Attribute */
|
||||
char fname[13]; /* File name */
|
||||
} FILINFO;
|
||||
|
||||
|
||||
|
||||
/* File function return code (FRESULT) */
|
||||
|
||||
typedef enum {
|
||||
FR_OK = 0, /* 0 */
|
||||
FR_DISK_ERR, /* 1 */
|
||||
FR_NOT_READY, /* 2 */
|
||||
FR_NO_FILE, /* 3 */
|
||||
FR_NOT_OPENED, /* 4 */
|
||||
FR_NOT_ENABLED, /* 5 */
|
||||
FR_NO_FILESYSTEM /* 6 */
|
||||
} FRESULT;
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Petit FatFs module application interface */
|
||||
|
||||
FRESULT pf_mount (FATFS* fs); /* Mount/Unmount a logical drive */
|
||||
FRESULT pf_open (const char* path); /* Open a file */
|
||||
FRESULT pf_read (void* buff, UINT btr, UINT* br); /* Read data from the open file */
|
||||
FRESULT pf_write (const void* buff, UINT btw, UINT* bw); /* Write data to the open file */
|
||||
FRESULT pf_lseek (DWORD ofs); /* Move file pointer of the open file */
|
||||
FRESULT pf_opendir (DIR* dj, const char* path); /* Open a directory */
|
||||
FRESULT pf_readdir (DIR* dj, FILINFO* fno); /* Read a directory item from the open directory */
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Flags and offset address */
|
||||
|
||||
/* File status flag (FATFS.flag) */
|
||||
|
||||
#define FA_OPENED 0x01
|
||||
#define FA_WPRT 0x02
|
||||
#define FA__WIP 0x40
|
||||
|
||||
|
||||
/* FAT sub type (FATFS.fs_type) */
|
||||
|
||||
#define FS_FAT12 1
|
||||
#define FS_FAT16 2
|
||||
#define FS_FAT32 3
|
||||
|
||||
|
||||
/* File attribute bits for directory entry */
|
||||
|
||||
#define AM_RDO 0x01 /* Read only */
|
||||
#define AM_HID 0x02 /* Hidden */
|
||||
#define AM_SYS 0x04 /* System */
|
||||
#define AM_VOL 0x08 /* Volume label */
|
||||
#define AM_LFN 0x0F /* LFN entry */
|
||||
#define AM_DIR 0x10 /* Directory */
|
||||
#define AM_ARC 0x20 /* Archive */
|
||||
#define AM_MASK 0x3F /* Mask of defined bits */
|
||||
|
||||
|
||||
/*--------------------------------*/
|
||||
/* Multi-byte word access macros */
|
||||
|
||||
#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */
|
||||
#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
|
||||
#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
|
||||
#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val)
|
||||
#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
|
||||
#else /* Use byte-by-byte access to the FAT structure */
|
||||
#define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))
|
||||
#define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr))
|
||||
#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8)
|
||||
#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PFATFS */
|
||||
89
tutorials/soc/lesson7c/pffconf.h
Normal file
89
tutorials/soc/lesson7c/pffconf.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Petit FatFs - Configuration file R0.03 (C)ChaN, 2014
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _PFFCONF
|
||||
#define _PFFCONF 4004 /* Revision ID */
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Function Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define _USE_READ 1 /* Enable pf_read() function */
|
||||
#define _USE_DIR 1 /* Enable pf_opendir() and pf_readdir() function */
|
||||
#define _USE_LSEEK 0 /* Enable pf_lseek() function */
|
||||
#define _USE_WRITE 0 /* Enable pf_write() function */
|
||||
|
||||
#define _FS_FAT12 0 /* Enable FAT12 */
|
||||
#define _FS_FAT16 1 /* Enable FAT16 */
|
||||
#define _FS_FAT32 1 /* Enable FAT32 */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Locale and Namespace Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define _USE_LCC 0 /* Allow lower case characters for path name */
|
||||
|
||||
#define _CODE_PAGE 437
|
||||
/* The _CODE_PAGE specifies the code page to be used on the target system.
|
||||
/ SBCS code pages with _USE_LCC == 1 requiers a 128 byte of case conversion
|
||||
/ table. This might occupy RAM on some platforms, e.g. avr-gcc.
|
||||
/ When _USE_LCC == 0, _CODE_PAGE has no effect.
|
||||
/
|
||||
/ 932 - Japanese Shift_JIS (DBCS, OEM, Windows)
|
||||
/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows)
|
||||
/ 949 - Korean (DBCS, OEM, Windows)
|
||||
/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows)
|
||||
/ 1250 - Central Europe (Windows)
|
||||
/ 1251 - Cyrillic (Windows)
|
||||
/ 1252 - Latin 1 (Windows)
|
||||
/ 1253 - Greek (Windows)
|
||||
/ 1254 - Turkish (Windows)
|
||||
/ 1255 - Hebrew (Windows)
|
||||
/ 1256 - Arabic (Windows)
|
||||
/ 1257 - Baltic (Windows)
|
||||
/ 1258 - Vietnam (OEM, Windows)
|
||||
/ 437 - U.S. (OEM)
|
||||
/ 720 - Arabic (OEM)
|
||||
/ 737 - Greek (OEM)
|
||||
/ 775 - Baltic (OEM)
|
||||
/ 850 - Multilingual Latin 1 (OEM)
|
||||
/ 858 - Multilingual Latin 1 + Euro (OEM)
|
||||
/ 852 - Latin 2 (OEM)
|
||||
/ 855 - Cyrillic (OEM)
|
||||
/ 866 - Russian (OEM)
|
||||
/ 857 - Turkish (OEM)
|
||||
/ 862 - Hebrew (OEM)
|
||||
/ 874 - Thai (OEM, Windows)
|
||||
*/
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ System Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define _WORD_ACCESS 0
|
||||
/* The _WORD_ACCESS option is an only platform dependent option. It defines
|
||||
/ which access method is used to the word data on the FAT volume.
|
||||
/
|
||||
/ 0: Byte-by-byte access. Always compatible with all platforms.
|
||||
/ 1: Word access. Do not choose this unless under both the following conditions.
|
||||
/
|
||||
/ * Address misaligned memory access is always allowed for ALL instructions.
|
||||
/ * Byte order on the memory is little-endian.
|
||||
/
|
||||
/ If it is the case, _WORD_ACCESS can also be set to 1 to improve performance and
|
||||
/ reduce code size. Following table shows an example of some processor types.
|
||||
/
|
||||
/ ARM7TDMI 0 ColdFire 0 V850E 0
|
||||
/ Cortex-M3 0 Z80 0/1 V850ES 0/1
|
||||
/ Cortex-M0 0 RX600(LE) 0/1 TLCS-870 0/1
|
||||
/ AVR 0/1 RX600(BE) 0 TLCS-900 0/1
|
||||
/ AVR32 0 RL78 0 R32C 0
|
||||
/ PIC18 0/1 SH-2 0 M16C 0/1
|
||||
/ PIC24 0 H8S 0 MSP430 0
|
||||
/ PIC32 0 H8/300H 0 x86 0/1
|
||||
*/
|
||||
|
||||
#endif /* _PFFCONF */
|
||||
4
tutorials/soc/lesson7c/pll.qip
Normal file
4
tutorials/soc/lesson7c/pll.qip
Normal file
@@ -0,0 +1,4 @@
|
||||
set_global_assignment -name IP_TOOL_NAME "ALTPLL"
|
||||
set_global_assignment -name IP_TOOL_VERSION "13.1"
|
||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"]
|
||||
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll.ppf"]
|
||||
365
tutorials/soc/lesson7c/pll.v
Normal file
365
tutorials/soc/lesson7c/pll.v
Normal file
@@ -0,0 +1,365 @@
|
||||
// megafunction wizard: %ALTPLL%
|
||||
// GENERATION: STANDARD
|
||||
// VERSION: WM1.0
|
||||
// MODULE: altpll
|
||||
|
||||
// ============================================================
|
||||
// File Name: pll.v
|
||||
// Megafunction Name(s):
|
||||
// altpll
|
||||
//
|
||||
// Simulation Library Files(s):
|
||||
// altera_mf
|
||||
// ============================================================
|
||||
// ************************************************************
|
||||
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
|
||||
//
|
||||
// 13.1.4 Build 182 03/12/2014 SJ Web Edition
|
||||
// ************************************************************
|
||||
|
||||
|
||||
//Copyright (C) 1991-2014 Altera Corporation
|
||||
//Your use of Altera Corporation's design tools, logic functions
|
||||
//and other software and tools, and its AMPP partner logic
|
||||
//functions, and any output files from any of the foregoing
|
||||
//(including device programming or simulation files), and any
|
||||
//associated documentation or information are expressly subject
|
||||
//to the terms and conditions of the Altera Program License
|
||||
//Subscription Agreement, Altera MegaCore Function License
|
||||
//Agreement, or other applicable license agreement, including,
|
||||
//without limitation, that your use is for the sole purpose of
|
||||
//programming logic devices manufactured by Altera and sold by
|
||||
//Altera or its authorized distributors. Please refer to the
|
||||
//applicable agreement for further details.
|
||||
|
||||
|
||||
// synopsys translate_off
|
||||
`timescale 1 ps / 1 ps
|
||||
// synopsys translate_on
|
||||
module pll (
|
||||
inclk0,
|
||||
c0,
|
||||
c1,
|
||||
c2,
|
||||
locked);
|
||||
|
||||
input inclk0;
|
||||
output c0;
|
||||
output c1;
|
||||
output c2;
|
||||
output locked;
|
||||
|
||||
wire [4:0] sub_wire0;
|
||||
wire sub_wire2;
|
||||
wire [0:0] sub_wire7 = 1'h0;
|
||||
wire [2:2] sub_wire4 = sub_wire0[2:2];
|
||||
wire [0:0] sub_wire3 = sub_wire0[0:0];
|
||||
wire [1:1] sub_wire1 = sub_wire0[1:1];
|
||||
wire c1 = sub_wire1;
|
||||
wire locked = sub_wire2;
|
||||
wire c0 = sub_wire3;
|
||||
wire c2 = sub_wire4;
|
||||
wire sub_wire5 = inclk0;
|
||||
wire [1:0] sub_wire6 = {sub_wire7, sub_wire5};
|
||||
|
||||
altpll altpll_component (
|
||||
.inclk (sub_wire6),
|
||||
.clk (sub_wire0),
|
||||
.locked (sub_wire2),
|
||||
.activeclock (),
|
||||
.areset (1'b0),
|
||||
.clkbad (),
|
||||
.clkena ({6{1'b1}}),
|
||||
.clkloss (),
|
||||
.clkswitch (1'b0),
|
||||
.configupdate (1'b0),
|
||||
.enable0 (),
|
||||
.enable1 (),
|
||||
.extclk (),
|
||||
.extclkena ({4{1'b1}}),
|
||||
.fbin (1'b1),
|
||||
.fbmimicbidir (),
|
||||
.fbout (),
|
||||
.fref (),
|
||||
.icdrclk (),
|
||||
.pfdena (1'b1),
|
||||
.phasecounterselect ({4{1'b1}}),
|
||||
.phasedone (),
|
||||
.phasestep (1'b1),
|
||||
.phaseupdown (1'b1),
|
||||
.pllena (1'b1),
|
||||
.scanaclr (1'b0),
|
||||
.scanclk (1'b0),
|
||||
.scanclkena (1'b1),
|
||||
.scandata (1'b0),
|
||||
.scandataout (),
|
||||
.scandone (),
|
||||
.scanread (1'b0),
|
||||
.scanwrite (1'b0),
|
||||
.sclkout0 (),
|
||||
.sclkout1 (),
|
||||
.vcooverrange (),
|
||||
.vcounderrange ());
|
||||
defparam
|
||||
altpll_component.bandwidth_type = "AUTO",
|
||||
altpll_component.clk0_divide_by = 15,
|
||||
altpll_component.clk0_duty_cycle = 50,
|
||||
altpll_component.clk0_multiply_by = 14,
|
||||
altpll_component.clk0_phase_shift = "0",
|
||||
altpll_component.clk1_divide_by = 27,
|
||||
altpll_component.clk1_duty_cycle = 50,
|
||||
altpll_component.clk1_multiply_by = 32,
|
||||
altpll_component.clk1_phase_shift = "0",
|
||||
altpll_component.clk2_divide_by = 27,
|
||||
altpll_component.clk2_duty_cycle = 50,
|
||||
altpll_component.clk2_multiply_by = 32,
|
||||
altpll_component.clk2_phase_shift = "-2500",
|
||||
altpll_component.compensate_clock = "CLK0",
|
||||
altpll_component.inclk0_input_frequency = 37037,
|
||||
altpll_component.intended_device_family = "Cyclone III",
|
||||
altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll",
|
||||
altpll_component.lpm_type = "altpll",
|
||||
altpll_component.operation_mode = "NORMAL",
|
||||
altpll_component.pll_type = "AUTO",
|
||||
altpll_component.port_activeclock = "PORT_UNUSED",
|
||||
altpll_component.port_areset = "PORT_UNUSED",
|
||||
altpll_component.port_clkbad0 = "PORT_UNUSED",
|
||||
altpll_component.port_clkbad1 = "PORT_UNUSED",
|
||||
altpll_component.port_clkloss = "PORT_UNUSED",
|
||||
altpll_component.port_clkswitch = "PORT_UNUSED",
|
||||
altpll_component.port_configupdate = "PORT_UNUSED",
|
||||
altpll_component.port_fbin = "PORT_UNUSED",
|
||||
altpll_component.port_inclk0 = "PORT_USED",
|
||||
altpll_component.port_inclk1 = "PORT_UNUSED",
|
||||
altpll_component.port_locked = "PORT_USED",
|
||||
altpll_component.port_pfdena = "PORT_UNUSED",
|
||||
altpll_component.port_phasecounterselect = "PORT_UNUSED",
|
||||
altpll_component.port_phasedone = "PORT_UNUSED",
|
||||
altpll_component.port_phasestep = "PORT_UNUSED",
|
||||
altpll_component.port_phaseupdown = "PORT_UNUSED",
|
||||
altpll_component.port_pllena = "PORT_UNUSED",
|
||||
altpll_component.port_scanaclr = "PORT_UNUSED",
|
||||
altpll_component.port_scanclk = "PORT_UNUSED",
|
||||
altpll_component.port_scanclkena = "PORT_UNUSED",
|
||||
altpll_component.port_scandata = "PORT_UNUSED",
|
||||
altpll_component.port_scandataout = "PORT_UNUSED",
|
||||
altpll_component.port_scandone = "PORT_UNUSED",
|
||||
altpll_component.port_scanread = "PORT_UNUSED",
|
||||
altpll_component.port_scanwrite = "PORT_UNUSED",
|
||||
altpll_component.port_clk0 = "PORT_USED",
|
||||
altpll_component.port_clk1 = "PORT_USED",
|
||||
altpll_component.port_clk2 = "PORT_USED",
|
||||
altpll_component.port_clk3 = "PORT_UNUSED",
|
||||
altpll_component.port_clk4 = "PORT_UNUSED",
|
||||
altpll_component.port_clk5 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena0 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena1 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena2 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena3 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena4 = "PORT_UNUSED",
|
||||
altpll_component.port_clkena5 = "PORT_UNUSED",
|
||||
altpll_component.port_extclk0 = "PORT_UNUSED",
|
||||
altpll_component.port_extclk1 = "PORT_UNUSED",
|
||||
altpll_component.port_extclk2 = "PORT_UNUSED",
|
||||
altpll_component.port_extclk3 = "PORT_UNUSED",
|
||||
altpll_component.self_reset_on_loss_lock = "OFF",
|
||||
altpll_component.width_clock = 5;
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
// ============================================================
|
||||
// CNX file retrieval info
|
||||
// ============================================================
|
||||
// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
|
||||
// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1"
|
||||
// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
|
||||
// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"
|
||||
// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1"
|
||||
// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0"
|
||||
// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"
|
||||
// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
|
||||
// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0"
|
||||
// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8"
|
||||
// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "15"
|
||||
// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
|
||||
// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
|
||||
// Retrieval info: PRIVATE: DUTY_CYCLE2 STRING "50.00000000"
|
||||
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "25.200001"
|
||||
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "32.000000"
|
||||
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "32.000000"
|
||||
// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
|
||||
// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
|
||||
// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
|
||||
// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0"
|
||||
// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
|
||||
// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
|
||||
// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000"
|
||||
// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
|
||||
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
|
||||
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
|
||||
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
|
||||
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
|
||||
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
|
||||
// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
|
||||
// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1"
|
||||
// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
|
||||
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available"
|
||||
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
|
||||
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "ps"
|
||||
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT2 STRING "ps"
|
||||
// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
|
||||
// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
|
||||
// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0"
|
||||
// Retrieval info: PRIVATE: MIRROR_CLK2 STRING "0"
|
||||
// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "14"
|
||||
// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "25.17500000"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "32.00000000"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "32.00000000"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "1"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE2 STRING "1"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT2 STRING "MHz"
|
||||
// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
|
||||
// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
|
||||
// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000"
|
||||
// Retrieval info: PRIVATE: PHASE_SHIFT2 STRING "-2500.00000000"
|
||||
// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"
|
||||
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "ps"
|
||||
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT2 STRING "ps"
|
||||
// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
|
||||
// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif"
|
||||
// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1"
|
||||
// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"
|
||||
// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
|
||||
// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
|
||||
// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
|
||||
// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
|
||||
// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
|
||||
// Retrieval info: PRIVATE: SPREAD_USE STRING "0"
|
||||
// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0"
|
||||
// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
|
||||
// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1"
|
||||
// Retrieval info: PRIVATE: STICKY_CLK2 STRING "1"
|
||||
// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1"
|
||||
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
|
||||
// Retrieval info: PRIVATE: USE_CLK0 STRING "1"
|
||||
// Retrieval info: PRIVATE: USE_CLK1 STRING "1"
|
||||
// Retrieval info: PRIVATE: USE_CLK2 STRING "1"
|
||||
// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0"
|
||||
// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0"
|
||||
// Retrieval info: PRIVATE: USE_CLKENA2 STRING "0"
|
||||
// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
|
||||
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
|
||||
// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO"
|
||||
// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "15"
|
||||
// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
|
||||
// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "14"
|
||||
// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
|
||||
// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "27"
|
||||
// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
|
||||
// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "32"
|
||||
// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0"
|
||||
// Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "27"
|
||||
// Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50"
|
||||
// Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "32"
|
||||
// Retrieval info: CONSTANT: CLK2_PHASE_SHIFT STRING "-2500"
|
||||
// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
|
||||
// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037"
|
||||
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
|
||||
// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"
|
||||
// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL"
|
||||
// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO"
|
||||
// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"
|
||||
// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED"
|
||||
// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
|
||||
// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED"
|
||||
// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_USED"
|
||||
// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED"
|
||||
// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF"
|
||||
// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5"
|
||||
// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]"
|
||||
// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
|
||||
// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1"
|
||||
// Retrieval info: USED_PORT: c2 0 0 0 0 OUTPUT_CLK_EXT VCC "c2"
|
||||
// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
|
||||
// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked"
|
||||
// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0
|
||||
// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0
|
||||
// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0
|
||||
// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1
|
||||
// Retrieval info: CONNECT: c2 0 0 0 0 @clk 0 0 1 2
|
||||
// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE
|
||||
// Retrieval info: LIB_FILE: altera_mf
|
||||
// Retrieval info: CBX_MODULE_PREFIX: ON
|
||||
147
tutorials/soc/lesson7c/sdram.v
Normal file
147
tutorials/soc/lesson7c/sdram.v
Normal file
@@ -0,0 +1,147 @@
|
||||
//
|
||||
// sdram.v
|
||||
//
|
||||
// sdram controller implementation for the MiST board
|
||||
// http://code.google.com/p/mist-board/
|
||||
//
|
||||
// Copyright (c) 2013 Till Harbaum <till@harbaum.org>
|
||||
//
|
||||
// This source file is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
module sdram (
|
||||
|
||||
// interface to the MT48LC16M16 chip
|
||||
inout [15:0] sd_data, // 16 bit bidirectional data bus
|
||||
output [12:0] sd_addr, // 13 bit multiplexed address bus
|
||||
output [1:0] sd_dqm, // two byte masks
|
||||
output [1:0] sd_ba, // two banks
|
||||
output sd_cs, // a single chip select
|
||||
output sd_we, // write enable
|
||||
output sd_ras, // row address select
|
||||
output sd_cas, // columns address select
|
||||
|
||||
// cpu/chipset interface
|
||||
input init, // init signal after FPGA config to initialize RAM
|
||||
input clk, // sdram is accessed at up to 128MHz
|
||||
input clkref, // reference clock to sync to
|
||||
|
||||
input [7:0] din, // data input from chipset/cpu
|
||||
output [7:0] dout, // data output to chipset/cpu
|
||||
input [24:0] addr, // 25 bit byte address
|
||||
input oe, // cpu/chipset requests read
|
||||
input we // cpu/chipset requests write
|
||||
);
|
||||
|
||||
// no burst configured
|
||||
localparam RASCAS_DELAY = 3'd3; // tRCD>=20ns -> 2 cycles@64MHz
|
||||
localparam BURST_LENGTH = 3'b000; // 000=none, 001=2, 010=4, 011=8
|
||||
localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved
|
||||
localparam CAS_LATENCY = 3'd2; // 2/3 allowed
|
||||
localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed
|
||||
localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write
|
||||
|
||||
localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH};
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// ------------------------ cycle state machine ------------------------
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
localparam STATE_IDLE = 3'd0; // first state in cycle
|
||||
localparam STATE_CMD_START = 3'd1; // state in which a new command can be started
|
||||
localparam STATE_CMD_CONT = STATE_CMD_START + RASCAS_DELAY - 3'd1; // 4 command can be continued
|
||||
localparam STATE_LAST = 3'd7; // last state in cycle
|
||||
|
||||
reg [2:0] q /* synthesis noprune */;
|
||||
always @(posedge clk) begin
|
||||
// 32Mhz counter synchronous to 4 Mhz clock
|
||||
// force counter to pass state 5->6 exactly after the rising edge of clkref
|
||||
// since clkref is two clocks early
|
||||
if(((q == 7) && ( clkref == 0)) ||
|
||||
((q == 0) && ( clkref == 1)) ||
|
||||
((q != 7) && (q != 0)))
|
||||
q <= q + 3'd1;
|
||||
end
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// --------------------------- startup/reset ---------------------------
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
// wait 1ms (32 clkref cycles) after FPGA config is done before going
|
||||
// into normal operation. Initialize the ram in the last 16 reset cycles (cycles 15-0)
|
||||
reg [4:0] reset;
|
||||
always @(posedge clk) begin
|
||||
if(init) reset <= 5'h1f;
|
||||
else if((q == STATE_LAST) && (reset != 0))
|
||||
reset <= reset - 5'd1;
|
||||
end
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// ------------------ generate ram control signals ---------------------
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
// all possible commands
|
||||
localparam CMD_INHIBIT = 4'b1111;
|
||||
localparam CMD_NOP = 4'b0111;
|
||||
localparam CMD_ACTIVE = 4'b0011;
|
||||
localparam CMD_READ = 4'b0101;
|
||||
localparam CMD_WRITE = 4'b0100;
|
||||
localparam CMD_BURST_TERMINATE = 4'b0110;
|
||||
localparam CMD_PRECHARGE = 4'b0010;
|
||||
localparam CMD_AUTO_REFRESH = 4'b0001;
|
||||
localparam CMD_LOAD_MODE = 4'b0000;
|
||||
|
||||
reg [3:0] sd_cmd; // current command sent to sd ram
|
||||
|
||||
// drive control signals according to current command
|
||||
assign sd_cs = sd_cmd[3];
|
||||
assign sd_ras = sd_cmd[2];
|
||||
assign sd_cas = sd_cmd[1];
|
||||
assign sd_we = sd_cmd[0];
|
||||
|
||||
assign sd_data = we?{din, din}:16'bZZZZZZZZZZZZZZZZ;
|
||||
|
||||
assign dout = sd_data[7:0];
|
||||
|
||||
always @(posedge clk) begin
|
||||
sd_cmd <= CMD_INHIBIT;
|
||||
|
||||
if(reset != 0) begin
|
||||
if(q == STATE_IDLE) begin
|
||||
if(reset == 13) sd_cmd <= CMD_PRECHARGE;
|
||||
if(reset == 2) sd_cmd <= CMD_LOAD_MODE;
|
||||
end
|
||||
end else begin
|
||||
if(q == STATE_IDLE) begin
|
||||
if(we || oe) sd_cmd <= CMD_ACTIVE;
|
||||
else sd_cmd <= CMD_AUTO_REFRESH;
|
||||
end else if(q == STATE_CMD_CONT) begin
|
||||
if(we) sd_cmd <= CMD_WRITE;
|
||||
else if(oe) sd_cmd <= CMD_READ;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
wire [12:0] reset_addr = (reset == 13)?13'b0010000000000:MODE;
|
||||
|
||||
wire [12:0] run_addr =
|
||||
(q == STATE_CMD_START)?addr[20:8]:{ 4'b0010, addr[23], addr[7:0]};
|
||||
|
||||
assign sd_addr = (reset != 0)?reset_addr:run_addr;
|
||||
|
||||
assign sd_ba = addr[22:21];
|
||||
|
||||
assign sd_dqm = 2'b00;
|
||||
|
||||
endmodule
|
||||
30
tutorials/soc/lesson7c/soc.qpf
Normal file
30
tutorials/soc/lesson7c/soc.qpf
Normal file
@@ -0,0 +1,30 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
# Copyright (C) 1991-2010 Altera Corporation
|
||||
# Your use of Altera Corporation's design tools, logic functions
|
||||
# and other software and tools, and its AMPP partner logic
|
||||
# functions, and any output files from any of the foregoing
|
||||
# (including device programming or simulation files), and any
|
||||
# associated documentation or information are expressly subject
|
||||
# to the terms and conditions of the Altera Program License
|
||||
# Subscription Agreement, Altera MegaCore Function License
|
||||
# Agreement, or other applicable license agreement, including,
|
||||
# without limitation, that your use is for the sole purpose of
|
||||
# programming logic devices manufactured by Altera and sold by
|
||||
# Altera or its authorized distributors. Please refer to the
|
||||
# applicable agreement for further details.
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
# Quartus II
|
||||
# Version 10.1 Build 153 11/29/2010 SJ Full Version
|
||||
# Date created = 11:11:11 June 13, 2011
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
|
||||
QUARTUS_VERSION = "10.1"
|
||||
DATE = "11:11:11 June 13, 2011"
|
||||
|
||||
# Revisions
|
||||
|
||||
PROJECT_REVISION = "soc"
|
||||
178
tutorials/soc/lesson7c/soc.qsf
Normal file
178
tutorials/soc/lesson7c/soc.qsf
Normal file
@@ -0,0 +1,178 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
# Copyright (C) 1991-2011 Altera Corporation
|
||||
# Your use of Altera Corporation's design tools, logic functions
|
||||
# and other software and tools, and its AMPP partner logic
|
||||
# functions, and any output files from any of the foregoing
|
||||
# (including device programming or simulation files), and any
|
||||
# associated documentation or information are expressly subject
|
||||
# to the terms and conditions of the Altera Program License
|
||||
# Subscription Agreement, Altera MegaCore Function License
|
||||
# Agreement, or other applicable license agreement, including,
|
||||
# without limitation, that your use is for the sole purpose of
|
||||
# programming logic devices manufactured by Altera and sold by
|
||||
# Altera or its authorized distributors. Please refer to the
|
||||
# applicable agreement for further details.
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
# Quartus II
|
||||
# Version 11.0 Build 157 04/27/2011 SJ Full Version
|
||||
# Date created = 17:14:01 April 10, 2012
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
# Notes:
|
||||
#
|
||||
# 1) The default values for assignments are stored in the file:
|
||||
# led_assignment_defaults.qdf
|
||||
# If this file doesn't exist, see file:
|
||||
# assignment_defaults.qdf
|
||||
#
|
||||
# 2) Altera recommends that you do not modify this file. This
|
||||
# file is updated automatically by the Quartus II software
|
||||
# and any changes you make may be lost or overwritten.
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
|
||||
|
||||
set_global_assignment -name FAMILY "Cyclone III"
|
||||
set_global_assignment -name DEVICE EP3C25E144C8
|
||||
set_global_assignment -name TOP_LEVEL_ENTITY soc
|
||||
set_global_assignment -name ORIGINAL_QUARTUS_VERSION 11.0
|
||||
set_global_assignment -name PROJECT_CREATION_TIME_DATE "17:14:01 APRIL 10, 2012"
|
||||
set_global_assignment -name LAST_QUARTUS_VERSION 13.1
|
||||
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
|
||||
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
|
||||
set_global_assignment -name DEVICE_FILTER_PACKAGE "ANY QFP"
|
||||
set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8
|
||||
set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1
|
||||
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
|
||||
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
|
||||
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
|
||||
set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
|
||||
set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF
|
||||
set_global_assignment -name RESERVE_ALL_UNUSED_PINS_WEAK_PULLUP "AS INPUT TRI-STATED"
|
||||
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise
|
||||
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall
|
||||
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise
|
||||
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall
|
||||
set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL"
|
||||
set_global_assignment -name GENERATE_RBF_FILE ON
|
||||
set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON
|
||||
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
|
||||
|
||||
set_location_assignment PIN_7 -to LED
|
||||
set_location_assignment PIN_22 -to CLOCK_50[0]
|
||||
set_location_assignment PIN_23 -to CLOCK_50[1]
|
||||
set_location_assignment PIN_128 -to CLOCK_32[0]
|
||||
set_location_assignment PIN_129 -to CLOCK_32[1]
|
||||
set_location_assignment PIN_54 -to CLOCK_27[0]
|
||||
set_location_assignment PIN_55 -to CLOCK_27[1]
|
||||
set_location_assignment PIN_144 -to VGA_R[5]
|
||||
set_location_assignment PIN_143 -to VGA_R[4]
|
||||
set_location_assignment PIN_142 -to VGA_R[3]
|
||||
set_location_assignment PIN_141 -to VGA_R[2]
|
||||
set_location_assignment PIN_137 -to VGA_R[1]
|
||||
set_location_assignment PIN_135 -to VGA_R[0]
|
||||
set_location_assignment PIN_133 -to VGA_B[5]
|
||||
set_location_assignment PIN_132 -to VGA_B[4]
|
||||
set_location_assignment PIN_125 -to VGA_B[3]
|
||||
set_location_assignment PIN_121 -to VGA_B[2]
|
||||
set_location_assignment PIN_120 -to VGA_B[1]
|
||||
set_location_assignment PIN_115 -to VGA_B[0]
|
||||
set_location_assignment PIN_114 -to VGA_G[5]
|
||||
set_location_assignment PIN_113 -to VGA_G[4]
|
||||
set_location_assignment PIN_112 -to VGA_G[3]
|
||||
set_location_assignment PIN_111 -to VGA_G[2]
|
||||
set_location_assignment PIN_110 -to VGA_G[1]
|
||||
set_location_assignment PIN_106 -to VGA_G[0]
|
||||
set_location_assignment PIN_136 -to VGA_VS
|
||||
set_location_assignment PIN_119 -to VGA_HS
|
||||
set_location_assignment PIN_65 -to AUDIO_L
|
||||
set_location_assignment PIN_80 -to AUDIO_R
|
||||
set_location_assignment PIN_46 -to UART_TX
|
||||
set_location_assignment PIN_31 -to UART_RX
|
||||
set_location_assignment PIN_105 -to SPI_DO
|
||||
set_location_assignment PIN_88 -to SPI_DI
|
||||
set_location_assignment PIN_126 -to SPI_SCK
|
||||
set_location_assignment PIN_127 -to SPI_SS2
|
||||
set_location_assignment PIN_91 -to SPI_SS3
|
||||
set_location_assignment PIN_90 -to SPI_SS4
|
||||
set_location_assignment PIN_13 -to CONF_DATA0
|
||||
|
||||
set_location_assignment PIN_49 -to SDRAM_A[0]
|
||||
set_location_assignment PIN_44 -to SDRAM_A[1]
|
||||
set_location_assignment PIN_42 -to SDRAM_A[2]
|
||||
set_location_assignment PIN_39 -to SDRAM_A[3]
|
||||
set_location_assignment PIN_4 -to SDRAM_A[4]
|
||||
set_location_assignment PIN_6 -to SDRAM_A[5]
|
||||
set_location_assignment PIN_8 -to SDRAM_A[6]
|
||||
set_location_assignment PIN_10 -to SDRAM_A[7]
|
||||
set_location_assignment PIN_11 -to SDRAM_A[8]
|
||||
set_location_assignment PIN_28 -to SDRAM_A[9]
|
||||
set_location_assignment PIN_50 -to SDRAM_A[10]
|
||||
set_location_assignment PIN_30 -to SDRAM_A[11]
|
||||
set_location_assignment PIN_32 -to SDRAM_A[12]
|
||||
set_location_assignment PIN_83 -to SDRAM_DQ[0]
|
||||
set_location_assignment PIN_79 -to SDRAM_DQ[1]
|
||||
set_location_assignment PIN_77 -to SDRAM_DQ[2]
|
||||
set_location_assignment PIN_76 -to SDRAM_DQ[3]
|
||||
set_location_assignment PIN_72 -to SDRAM_DQ[4]
|
||||
set_location_assignment PIN_71 -to SDRAM_DQ[5]
|
||||
set_location_assignment PIN_69 -to SDRAM_DQ[6]
|
||||
set_location_assignment PIN_68 -to SDRAM_DQ[7]
|
||||
set_location_assignment PIN_86 -to SDRAM_DQ[8]
|
||||
set_location_assignment PIN_87 -to SDRAM_DQ[9]
|
||||
set_location_assignment PIN_98 -to SDRAM_DQ[10]
|
||||
set_location_assignment PIN_99 -to SDRAM_DQ[11]
|
||||
set_location_assignment PIN_100 -to SDRAM_DQ[12]
|
||||
set_location_assignment PIN_101 -to SDRAM_DQ[13]
|
||||
set_location_assignment PIN_103 -to SDRAM_DQ[14]
|
||||
set_location_assignment PIN_104 -to SDRAM_DQ[15]
|
||||
set_location_assignment PIN_58 -to SDRAM_BA[0]
|
||||
set_location_assignment PIN_51 -to SDRAM_BA[1]
|
||||
set_location_assignment PIN_85 -to SDRAM_DQMH
|
||||
set_location_assignment PIN_67 -to SDRAM_DQML
|
||||
set_location_assignment PIN_60 -to SDRAM_nRAS
|
||||
set_location_assignment PIN_64 -to SDRAM_nCAS
|
||||
set_location_assignment PIN_66 -to SDRAM_nWE
|
||||
set_location_assignment PIN_59 -to SDRAM_nCS
|
||||
set_location_assignment PIN_33 -to SDRAM_CKE
|
||||
set_location_assignment PIN_43 -to SDRAM_CLK
|
||||
|
||||
|
||||
set_global_assignment -name ENABLE_SIGNALTAP OFF
|
||||
set_global_assignment -name USE_SIGNALTAP_FILE stp2.stp
|
||||
set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO"
|
||||
set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO"
|
||||
set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO"
|
||||
set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO"
|
||||
set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO"
|
||||
set_global_assignment -name OPTIMIZE_HOLD_TIMING "ALL PATHS"
|
||||
set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING ON
|
||||
set_global_assignment -name FITTER_EFFORT "FAST FIT"
|
||||
set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW"
|
||||
set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
|
||||
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_*
|
||||
set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SDRAM_*
|
||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_*
|
||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ*
|
||||
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ*
|
||||
set_global_assignment -name VERILOG_FILE block_io.v
|
||||
set_global_assignment -name VERILOG_FILE data_io.v
|
||||
set_global_assignment -name VERILOG_FILE user_io.v
|
||||
set_global_assignment -name VERILOG_FILE osd.v
|
||||
set_global_assignment -name VERILOG_FILE sdram.v
|
||||
set_global_assignment -name VHDL_FILE T80s.vhd
|
||||
set_global_assignment -name VHDL_FILE T80_Reg.vhd
|
||||
set_global_assignment -name VHDL_FILE T80_Pack.vhd
|
||||
set_global_assignment -name VHDL_FILE T80_MCode.vhd
|
||||
set_global_assignment -name VHDL_FILE T80_ALU.vhd
|
||||
set_global_assignment -name VHDL_FILE T80.vhd
|
||||
set_global_assignment -name QIP_FILE pll.qip
|
||||
set_global_assignment -name VERILOG_FILE soc.v
|
||||
set_global_assignment -name VERILOG_FILE vga.v
|
||||
set_global_assignment -name SIGNALTAP_FILE soc.stp
|
||||
set_global_assignment -name SIGNALTAP_FILE stp2.stp
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||||
BIN
tutorials/soc/lesson7c/soc.rbf
Normal file
BIN
tutorials/soc/lesson7c/soc.rbf
Normal file
Binary file not shown.
108
tutorials/soc/lesson7c/soc.sdc
Normal file
108
tutorials/soc/lesson7c/soc.sdc
Normal file
@@ -0,0 +1,108 @@
|
||||
## Generated SDC file "constraints.sdc"
|
||||
|
||||
## Copyright (C) 1991-2011 Altera Corporation
|
||||
## Your use of Altera Corporation's design tools, logic functions
|
||||
## and other software and tools, and its AMPP partner logic
|
||||
## functions, and any output files from any of the foregoing
|
||||
## (including device programming or simulation files), and any
|
||||
## associated documentation or information are expressly subject
|
||||
## to the terms and conditions of the Altera Program License
|
||||
## Subscription Agreement, Altera MegaCore Function License
|
||||
## Agreement, or other applicable license agreement, including,
|
||||
## without limitation, that your use is for the sole purpose of
|
||||
## programming logic devices manufactured by Altera and sold by
|
||||
## Altera or its authorized distributors. Please refer to the
|
||||
## applicable agreement for further details.
|
||||
|
||||
|
||||
## VENDOR "Altera"
|
||||
## PROGRAM "Quartus II"
|
||||
## VERSION "Version 11.1 Build 216 11/23/2011 Service Pack 1 SJ Web Edition"
|
||||
|
||||
## DATE "Fri Jul 06 23:05:47 2012"
|
||||
|
||||
##
|
||||
## DEVICE "EP3C25E144C8"
|
||||
##
|
||||
|
||||
|
||||
#**************************************************************
|
||||
# Time Information
|
||||
#**************************************************************
|
||||
|
||||
set_time_format -unit ns -decimal_places 3
|
||||
|
||||
|
||||
|
||||
#**************************************************************
|
||||
# Create Clock
|
||||
#**************************************************************
|
||||
|
||||
create_clock -name {clk_27} -period 37.037 -waveform { 0.000 18.500 } [get_ports {CLOCK_27[0]}]
|
||||
|
||||
#**************************************************************
|
||||
# Create Generated Clock
|
||||
#**************************************************************
|
||||
|
||||
derive_pll_clocks
|
||||
create_generated_clock -name sdclk_pin -source [get_pins {clock|altpll_component|auto_generated|pll1|clk[2]}] [get_ports {SDRAM_CLK}]
|
||||
|
||||
#**************************************************************
|
||||
# Set Clock Latency
|
||||
#**************************************************************
|
||||
|
||||
|
||||
#**************************************************************
|
||||
# Set Clock Uncertainty
|
||||
#**************************************************************
|
||||
|
||||
derive_clock_uncertainty;
|
||||
|
||||
#**************************************************************
|
||||
# Set Input Delay
|
||||
#**************************************************************
|
||||
|
||||
set_input_delay -clock sdclk_pin -max 6.4 [get_ports SDRAM_DQ*]
|
||||
set_input_delay -clock sdclk_pin -min 3.2 [get_ports SDRAM_DQ*]
|
||||
|
||||
#**************************************************************
|
||||
# Set Output Delay
|
||||
#**************************************************************
|
||||
|
||||
set_output_delay -clock sdclk_pin -max 1.5 [get_ports SDRAM_*]
|
||||
set_output_delay -clock sdclk_pin -min -0.8 [get_ports SDRAM_*]
|
||||
|
||||
#**************************************************************
|
||||
# Set Clock Groups
|
||||
#**************************************************************
|
||||
|
||||
|
||||
|
||||
#**************************************************************
|
||||
# Set False Path
|
||||
#**************************************************************
|
||||
|
||||
|
||||
|
||||
#**************************************************************
|
||||
# Set Multicycle Path
|
||||
#**************************************************************
|
||||
|
||||
set_multicycle_path -from [get_clocks {sdclk_pin}] -to [get_clocks {clock|altpll_component|auto_generated|pll1|clk[2]}] -setup -end 2
|
||||
|
||||
|
||||
#**************************************************************
|
||||
# Set Maximum Delay
|
||||
#**************************************************************
|
||||
|
||||
|
||||
|
||||
#**************************************************************
|
||||
# Set Minimum Delay
|
||||
#**************************************************************
|
||||
|
||||
|
||||
|
||||
#**************************************************************
|
||||
# Set Input Transition
|
||||
#**************************************************************
|
||||
298
tutorials/soc/lesson7c/soc.v
Normal file
298
tutorials/soc/lesson7c/soc.v
Normal file
@@ -0,0 +1,298 @@
|
||||
// A simple system-on-a-chip (SoC) for the MiST
|
||||
// (c) 2015 Till Harbaum
|
||||
|
||||
module soc (
|
||||
input [1:0] CLOCK_27,
|
||||
|
||||
// SDRAM interface
|
||||
inout [15:0] SDRAM_DQ, // SDRAM Data bus 16 Bits
|
||||
output [12:0] SDRAM_A, // SDRAM Address bus 13 Bits
|
||||
output SDRAM_DQML, // SDRAM Low-byte Data Mask
|
||||
output SDRAM_DQMH, // SDRAM High-byte Data Mask
|
||||
output SDRAM_nWE, // SDRAM Write Enable
|
||||
output SDRAM_nCAS, // SDRAM Column Address Strobe
|
||||
output SDRAM_nRAS, // SDRAM Row Address Strobe
|
||||
output SDRAM_nCS, // SDRAM Chip Select
|
||||
output [1:0] SDRAM_BA, // SDRAM Bank Address
|
||||
output SDRAM_CLK, // SDRAM Clock
|
||||
output SDRAM_CKE, // SDRAM Clock Enable
|
||||
|
||||
// SPI interface to arm io controller
|
||||
output SPI_DO,
|
||||
input SPI_DI,
|
||||
input SPI_SCK,
|
||||
input SPI_SS2,
|
||||
input SPI_SS3,
|
||||
input SPI_SS4,
|
||||
input CONF_DATA0,
|
||||
|
||||
// VGA interface
|
||||
output VGA_HS,
|
||||
output VGA_VS,
|
||||
output [5:0] VGA_R,
|
||||
output [5:0] VGA_G,
|
||||
output [5:0] VGA_B
|
||||
);
|
||||
|
||||
wire pixel_clock;
|
||||
|
||||
// the configuration string is returned to the io controller to allow
|
||||
// it to control the menu on the OSD
|
||||
parameter CONF_STR = {
|
||||
"Z80_SOC;;",
|
||||
"O1,Scanlines,On,Off;",
|
||||
"T2,Reset"
|
||||
};
|
||||
|
||||
parameter CONF_STR_LEN = 9+20+8;
|
||||
|
||||
// the status register is controlled by the on screen display (OSD)
|
||||
wire [7:0] status;
|
||||
|
||||
// conections between user_io (implementing the SPIU communication
|
||||
// to the io controller) and the legacy
|
||||
wire [31:0] sd_lba;
|
||||
wire sd_rd;
|
||||
wire sd_wr;
|
||||
wire sd_ack;
|
||||
wire sd_conf;
|
||||
wire [7:0] sd_dout;
|
||||
wire sd_dout_strobe;
|
||||
wire [7:0] sd_din;
|
||||
wire sd_din_strobe;
|
||||
|
||||
// include user_io module for arm controller communication
|
||||
user_io #(.STRLEN(CONF_STR_LEN)) user_io (
|
||||
.conf_str ( CONF_STR ),
|
||||
|
||||
.SPI_CLK ( SPI_SCK ),
|
||||
.SPI_SS_IO ( CONF_DATA0 ),
|
||||
.SPI_MISO ( SPI_DO ),
|
||||
.SPI_MOSI ( SPI_DI ),
|
||||
|
||||
.status ( status ),
|
||||
|
||||
// interface to embedded legacy sd card wrapper
|
||||
.sd_lba ( sd_lba),
|
||||
.sd_rd ( sd_rd),
|
||||
.sd_wr ( sd_wr),
|
||||
.sd_ack ( sd_ack),
|
||||
.sd_conf ( sd_conf),
|
||||
.sd_sdhc ( 1'b1 ), // sdhc is ok for us
|
||||
.sd_dout ( sd_dout),
|
||||
.sd_dout_strobe (sd_dout_strobe),
|
||||
.sd_din ( sd_din),
|
||||
.sd_din_strobe (sd_din_strobe)
|
||||
);
|
||||
|
||||
// include the on screen display
|
||||
osd #(0,0,4) osd (
|
||||
.pclk ( pixel_clock ),
|
||||
|
||||
// spi for OSD
|
||||
.sdi ( SPI_DI ),
|
||||
.sck ( SPI_SCK ),
|
||||
.ss ( SPI_SS3 ),
|
||||
|
||||
.red_in ( video_r ),
|
||||
.green_in ( video_g ),
|
||||
.blue_in ( video_b ),
|
||||
.hs_in ( video_hs ),
|
||||
.vs_in ( video_vs ),
|
||||
|
||||
.red_out ( VGA_R ),
|
||||
.green_out ( VGA_G ),
|
||||
.blue_out ( VGA_B ),
|
||||
.hs_out ( VGA_HS ),
|
||||
.vs_out ( VGA_VS )
|
||||
);
|
||||
|
||||
wire [5:0] video_r, video_g, video_b;
|
||||
wire video_hs, video_vs;
|
||||
|
||||
// include VGA controller
|
||||
vga vga (
|
||||
.pclk ( pixel_clock ),
|
||||
|
||||
.cpu_clk ( cpu_clock ),
|
||||
.cpu_wr ( !cpu_wr_n && !cpu_mreq_n && !cpu_addr[15] ),
|
||||
.cpu_addr ( cpu_addr[13:0] ),
|
||||
.cpu_data ( cpu_dout ),
|
||||
|
||||
.scanlines ( !status[1] ),
|
||||
|
||||
// video output as fed into the on screen display engine
|
||||
.hs ( video_hs ),
|
||||
.vs ( video_vs ),
|
||||
.r ( video_r ),
|
||||
.g ( video_g ),
|
||||
.b ( video_b )
|
||||
);
|
||||
|
||||
// The CPU is kept in reset for further 256 cycles after the PLL is generating stable clocks
|
||||
// to make sure things like the SDRAM have some time to initialize
|
||||
// status 0 is arm controller power up reset, status 2 is reset entry in OSD
|
||||
reg [7:0] cpu_reset_cnt = 8'h00;
|
||||
wire cpu_reset = (cpu_reset_cnt != 255);
|
||||
always @(posedge cpu_clock) begin
|
||||
if(!pll_locked || status[0] || status[2] || dio_download)
|
||||
cpu_reset_cnt <= 8'd0;
|
||||
else
|
||||
if(cpu_reset_cnt != 255)
|
||||
cpu_reset_cnt <= cpu_reset_cnt + 8'd1;
|
||||
end
|
||||
|
||||
// SDRAM control signals
|
||||
wire ram_clock;
|
||||
assign SDRAM_CKE = 1'b1;
|
||||
|
||||
// during ROM download data_io writes the ram. Otherwise the CPU
|
||||
wire [7:0] sdram_din = dio_download?dio_data:cpu_dout;
|
||||
wire [24:0] sdram_addr = dio_download?dio_addr:{ 9'd0, cpu_addr[15:0] };
|
||||
wire sdram_wr = dio_download?dio_write:(!cpu_wr_n && !cpu_mreq_n && cpu_addr[15]);
|
||||
wire sdram_oe = dio_download?1'b1:(!cpu_rd_n && !cpu_mreq_n);
|
||||
|
||||
sdram sdram (
|
||||
// interface to the MT48LC16M16 chip
|
||||
.sd_data ( SDRAM_DQ ),
|
||||
.sd_addr ( SDRAM_A ),
|
||||
.sd_dqm ( {SDRAM_DQMH, SDRAM_DQML} ),
|
||||
.sd_cs ( SDRAM_nCS ),
|
||||
.sd_ba ( SDRAM_BA ),
|
||||
.sd_we ( SDRAM_nWE ),
|
||||
.sd_ras ( SDRAM_nRAS ),
|
||||
.sd_cas ( SDRAM_nCAS ),
|
||||
|
||||
// system interface
|
||||
.clk ( ram_clock ),
|
||||
.clkref ( cpu_clock ),
|
||||
.init ( !pll_locked ),
|
||||
|
||||
// cpu interface
|
||||
.din ( sdram_din ),
|
||||
.addr ( sdram_addr ),
|
||||
.we ( sdram_wr ),
|
||||
.oe ( sdram_oe ),
|
||||
.dout ( ram_data_out )
|
||||
);
|
||||
|
||||
// CPU control signals
|
||||
wire cpu_clock;
|
||||
wire [15:0] cpu_addr;
|
||||
wire [7:0] cpu_din;
|
||||
wire [7:0] cpu_dout;
|
||||
wire cpu_rd_n;
|
||||
wire cpu_wr_n;
|
||||
wire cpu_mreq_n;
|
||||
wire cpu_m1_n;
|
||||
wire cpu_iorq_n;
|
||||
|
||||
// include Z80 CPU
|
||||
T80s T80s (
|
||||
.RESET_n ( !cpu_reset ),
|
||||
.CLK_n ( cpu_clock ),
|
||||
.WAIT_n ( 1'b1 ),
|
||||
.INT_n ( irq_n ),
|
||||
.NMI_n ( 1'b1 ),
|
||||
.BUSRQ_n ( 1'b1 ),
|
||||
.MREQ_n ( cpu_mreq_n ),
|
||||
.M1_n ( cpu_m1_n ),
|
||||
.IORQ_n ( cpu_iorq_n ),
|
||||
.RD_n ( cpu_rd_n ),
|
||||
.WR_n ( cpu_wr_n ),
|
||||
.A ( cpu_addr ),
|
||||
.DI ( cpu_din ),
|
||||
.DO ( cpu_dout )
|
||||
);
|
||||
|
||||
// currently the spi interface is the only device using IO
|
||||
wire [7:0] io_dout = block_sel?block_dout:8'h00;
|
||||
|
||||
// block controller uses IO addresses 0 to 7
|
||||
wire block_sel = !cpu_iorq_n && cpu_m1_n && ({ cpu_addr[7:3], 3'b000} == 8'h00 );
|
||||
wire [7:0] block_dout;
|
||||
|
||||
block_io block_io (
|
||||
// connection to io controller
|
||||
.io_lba (sd_lba ),
|
||||
.io_rd (sd_rd),
|
||||
.io_wr (sd_wr),
|
||||
.io_ack (sd_ack),
|
||||
.io_conf (sd_conf),
|
||||
.io_din (sd_dout),
|
||||
.io_din_strobe (sd_dout_strobe),
|
||||
.io_dout (sd_din),
|
||||
.io_dout_strobe ( sd_din_strobe),
|
||||
|
||||
.reset ( cpu_reset ),
|
||||
.clk ( cpu_clock ),
|
||||
|
||||
// CPU interface
|
||||
.rd ( !cpu_rd_n && block_sel ),
|
||||
.wr ( !cpu_wr_n && block_sel ),
|
||||
.addr ( cpu_addr[2:0] ),
|
||||
.din ( cpu_dout ),
|
||||
.dout ( block_dout )
|
||||
);
|
||||
|
||||
// irq is asserted until cpu acknowledges it
|
||||
reg vsD, vsD2;
|
||||
reg irq_n;
|
||||
always @(posedge cpu_clock) begin
|
||||
vsD <= video_vs;
|
||||
vsD2 <= vsD;
|
||||
|
||||
if(cpu_reset)
|
||||
irq_n <= 1'b1;
|
||||
else begin
|
||||
if(vsD && !vsD2)
|
||||
irq_n <= 1'b0;
|
||||
|
||||
if(!cpu_iorq_n && !cpu_m1_n)
|
||||
irq_n <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
// map 32k SDRAN into upper half od the address space (A15=1)
|
||||
// and ROM (now also placed in SDRAM) into the lower half (A15=0)
|
||||
wire [7:0] ram_data_out;
|
||||
assign cpu_din = (!cpu_iorq_n)?io_dout:ram_data_out;
|
||||
|
||||
wire dio_download;
|
||||
wire [24:0] dio_addr;
|
||||
wire [7:0] dio_data;
|
||||
wire dio_write;
|
||||
|
||||
// include ROM download helper
|
||||
data_io data_io (
|
||||
// io controller spi interface
|
||||
.sck ( SPI_SCK ),
|
||||
.ss ( SPI_SS2 ),
|
||||
.sdi ( SPI_DI ),
|
||||
|
||||
.downloading ( dio_download ), // signal indicating an active rom download
|
||||
|
||||
// external ram interface
|
||||
.clk ( cpu_clock ),
|
||||
.wr ( dio_write ),
|
||||
.addr ( dio_addr ),
|
||||
.data ( dio_data )
|
||||
);
|
||||
|
||||
// derive 4Mhz cpu clock from 32Mhz sdram clock
|
||||
assign cpu_clock = clk_div[2];
|
||||
reg [7:0] clk_div /* synthesis noprune */;
|
||||
always @(posedge ram_clock)
|
||||
clk_div <= clk_div + 3'd1;
|
||||
|
||||
// PLL to generate 32Mhz ram clock and 25Mhz video clock from MiSTs 27Mhz on board clock
|
||||
wire pll_locked;
|
||||
pll pll (
|
||||
.inclk0 ( CLOCK_27[0] ),
|
||||
.locked ( pll_locked ), // PLL is running stable
|
||||
.c0 ( pixel_clock ), // 25.175 MHz
|
||||
.c1 ( ram_clock ), // 32 MHz
|
||||
.c2 ( SDRAM_CLK ) // 32 MHz slightly phase shiftet
|
||||
);
|
||||
|
||||
endmodule
|
||||
412
tutorials/soc/lesson7c/user_io.v
Normal file
412
tutorials/soc/lesson7c/user_io.v
Normal file
@@ -0,0 +1,412 @@
|
||||
//
|
||||
// user_io.v
|
||||
//
|
||||
// user_io for the MiST board
|
||||
// http://code.google.com/p/mist-board/
|
||||
//
|
||||
// Copyright (c) 2014 Till Harbaum <till@harbaum.org>
|
||||
//
|
||||
// This source file is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
// parameter STRLEN and the actual length of conf_str have to match
|
||||
|
||||
module user_io #(parameter STRLEN=0) (
|
||||
input [(8*STRLEN)-1:0] conf_str,
|
||||
|
||||
input SPI_CLK,
|
||||
input SPI_SS_IO,
|
||||
output reg SPI_MISO,
|
||||
input SPI_MOSI,
|
||||
|
||||
output reg [7:0] joystick_0,
|
||||
output reg [7:0] joystick_1,
|
||||
output reg [15:0] joystick_analog_0,
|
||||
output reg [15:0] joystick_analog_1,
|
||||
output [1:0] buttons,
|
||||
output [1:0] switches,
|
||||
|
||||
output reg [7:0] status,
|
||||
|
||||
// connection to sd card emulation
|
||||
input [31:0] sd_lba,
|
||||
input sd_rd,
|
||||
input sd_wr,
|
||||
output reg sd_ack,
|
||||
input sd_conf,
|
||||
input sd_sdhc,
|
||||
output [7:0] sd_dout, // valid on rising edge of sd_dout_strobe
|
||||
output reg sd_dout_strobe,
|
||||
input [7:0] sd_din,
|
||||
output reg sd_din_strobe,
|
||||
|
||||
|
||||
// ps2 keyboard emulation
|
||||
input ps2_clk, // 12-16khz provided by core
|
||||
output ps2_kbd_clk,
|
||||
output reg ps2_kbd_data,
|
||||
output ps2_mouse_clk,
|
||||
output reg ps2_mouse_data,
|
||||
|
||||
// serial com port
|
||||
input [7:0] serial_data,
|
||||
input serial_strobe
|
||||
);
|
||||
|
||||
reg [6:0] sbuf;
|
||||
reg [7:0] cmd;
|
||||
reg [2:0] bit_cnt; // counts bits 0-7 0-7 ...
|
||||
reg [7:0] byte_cnt; // counts bytes
|
||||
reg [5:0] joystick0;
|
||||
reg [5:0] joystick1;
|
||||
reg [3:0] but_sw;
|
||||
reg [2:0] stick_idx;
|
||||
|
||||
assign buttons = but_sw[1:0];
|
||||
assign switches = but_sw[3:2];
|
||||
assign sd_dout = { sbuf, SPI_MOSI};
|
||||
|
||||
// this variant of user_io is for 8 bit cores (type == a4) only
|
||||
wire [7:0] core_type = 8'ha4;
|
||||
|
||||
// command byte read by the io controller
|
||||
wire [7:0] sd_cmd = { 4'h5, sd_conf, sd_sdhc, sd_wr, sd_rd };
|
||||
|
||||
// filter spi clock. the 8 bit gate delay is ~2.5ns in total
|
||||
wire [7:0] spi_sck_D = { spi_sck_D[6:0], SPI_CLK } /* synthesis keep */;
|
||||
wire spi_sck = (spi_sck && spi_sck_D != 8'h00) || (!spi_sck && spi_sck_D == 8'hff);
|
||||
|
||||
// drive MISO only when transmitting core id
|
||||
always@(negedge spi_sck or posedge SPI_SS_IO) begin
|
||||
if(SPI_SS_IO == 1) begin
|
||||
SPI_MISO <= 1'bZ;
|
||||
end else begin
|
||||
|
||||
// first byte returned is always core type, further bytes are
|
||||
// command dependent
|
||||
if(byte_cnt == 0) begin
|
||||
SPI_MISO <= core_type[~bit_cnt];
|
||||
|
||||
end else begin
|
||||
// reading serial fifo
|
||||
if(cmd == 8'h1b) begin
|
||||
// send alternating flag byte and data
|
||||
if(byte_cnt[0]) SPI_MISO <= serial_out_status[~bit_cnt];
|
||||
else SPI_MISO <= serial_out_byte[~bit_cnt];
|
||||
end
|
||||
|
||||
// reading config string
|
||||
else if(cmd == 8'h14) begin
|
||||
// returning a byte from string
|
||||
if(byte_cnt < STRLEN + 1)
|
||||
SPI_MISO <= conf_str[{STRLEN - byte_cnt,~bit_cnt}];
|
||||
else
|
||||
SPI_MISO <= 1'b0;
|
||||
end
|
||||
|
||||
// reading sd card status
|
||||
else if(cmd == 8'h16) begin
|
||||
if(byte_cnt == 1)
|
||||
SPI_MISO <= sd_cmd[~bit_cnt];
|
||||
else if((byte_cnt >= 2) && (byte_cnt < 6))
|
||||
SPI_MISO <= sd_lba[{5-byte_cnt, ~bit_cnt}];
|
||||
else
|
||||
SPI_MISO <= 1'b0;
|
||||
end
|
||||
|
||||
// reading sd card write data
|
||||
else if(cmd == 8'h18)
|
||||
SPI_MISO <= sd_din[~bit_cnt];
|
||||
|
||||
else
|
||||
SPI_MISO <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// ---------------- PS2 ---------------------
|
||||
|
||||
// 8 byte fifos to store ps2 bytes
|
||||
localparam PS2_FIFO_BITS = 3;
|
||||
|
||||
// keyboard
|
||||
reg [7:0] ps2_kbd_fifo [(2**PS2_FIFO_BITS)-1:0];
|
||||
reg [PS2_FIFO_BITS-1:0] ps2_kbd_wptr;
|
||||
reg [PS2_FIFO_BITS-1:0] ps2_kbd_rptr;
|
||||
|
||||
// ps2 transmitter state machine
|
||||
reg [3:0] ps2_kbd_tx_state;
|
||||
reg [7:0] ps2_kbd_tx_byte;
|
||||
reg ps2_kbd_parity;
|
||||
|
||||
assign ps2_kbd_clk = ps2_clk || (ps2_kbd_tx_state == 0);
|
||||
|
||||
// ps2 transmitter
|
||||
// Takes a byte from the FIFO and sends it in a ps2 compliant serial format.
|
||||
reg ps2_kbd_r_inc;
|
||||
always@(posedge ps2_clk) begin
|
||||
ps2_kbd_r_inc <= 1'b0;
|
||||
|
||||
if(ps2_kbd_r_inc)
|
||||
ps2_kbd_rptr <= ps2_kbd_rptr + 1;
|
||||
|
||||
// transmitter is idle?
|
||||
if(ps2_kbd_tx_state == 0) begin
|
||||
// data in fifo present?
|
||||
if(ps2_kbd_wptr != ps2_kbd_rptr) begin
|
||||
// load tx register from fifo
|
||||
ps2_kbd_tx_byte <= ps2_kbd_fifo[ps2_kbd_rptr];
|
||||
ps2_kbd_r_inc <= 1'b1;
|
||||
|
||||
// reset parity
|
||||
ps2_kbd_parity <= 1'b1;
|
||||
|
||||
// start transmitter
|
||||
ps2_kbd_tx_state <= 4'd1;
|
||||
|
||||
// put start bit on data line
|
||||
ps2_kbd_data <= 1'b0; // start bit is 0
|
||||
end
|
||||
end else begin
|
||||
|
||||
// transmission of 8 data bits
|
||||
if((ps2_kbd_tx_state >= 1)&&(ps2_kbd_tx_state < 9)) begin
|
||||
ps2_kbd_data <= ps2_kbd_tx_byte[0]; // data bits
|
||||
ps2_kbd_tx_byte[6:0] <= ps2_kbd_tx_byte[7:1]; // shift down
|
||||
if(ps2_kbd_tx_byte[0])
|
||||
ps2_kbd_parity <= !ps2_kbd_parity;
|
||||
end
|
||||
|
||||
// transmission of parity
|
||||
if(ps2_kbd_tx_state == 9)
|
||||
ps2_kbd_data <= ps2_kbd_parity;
|
||||
|
||||
// transmission of stop bit
|
||||
if(ps2_kbd_tx_state == 10)
|
||||
ps2_kbd_data <= 1'b1; // stop bit is 1
|
||||
|
||||
// advance state machine
|
||||
if(ps2_kbd_tx_state < 11)
|
||||
ps2_kbd_tx_state <= ps2_kbd_tx_state + 4'd1;
|
||||
else
|
||||
ps2_kbd_tx_state <= 4'd0;
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
// mouse
|
||||
reg [7:0] ps2_mouse_fifo [(2**PS2_FIFO_BITS)-1:0];
|
||||
reg [PS2_FIFO_BITS-1:0] ps2_mouse_wptr;
|
||||
reg [PS2_FIFO_BITS-1:0] ps2_mouse_rptr;
|
||||
|
||||
// ps2 transmitter state machine
|
||||
reg [3:0] ps2_mouse_tx_state;
|
||||
reg [7:0] ps2_mouse_tx_byte;
|
||||
reg ps2_mouse_parity;
|
||||
|
||||
assign ps2_mouse_clk = ps2_clk || (ps2_mouse_tx_state == 0);
|
||||
|
||||
// ps2 transmitter
|
||||
// Takes a byte from the FIFO and sends it in a ps2 compliant serial format.
|
||||
reg ps2_mouse_r_inc;
|
||||
always@(posedge ps2_clk) begin
|
||||
ps2_mouse_r_inc <= 1'b0;
|
||||
|
||||
if(ps2_mouse_r_inc)
|
||||
ps2_mouse_rptr <= ps2_mouse_rptr + 1;
|
||||
|
||||
// transmitter is idle?
|
||||
if(ps2_mouse_tx_state == 0) begin
|
||||
// data in fifo present?
|
||||
if(ps2_mouse_wptr != ps2_mouse_rptr) begin
|
||||
// load tx register from fifo
|
||||
ps2_mouse_tx_byte <= ps2_mouse_fifo[ps2_mouse_rptr];
|
||||
ps2_mouse_r_inc <= 1'b1;
|
||||
|
||||
// reset parity
|
||||
ps2_mouse_parity <= 1'b1;
|
||||
|
||||
// start transmitter
|
||||
ps2_mouse_tx_state <= 4'd1;
|
||||
|
||||
// put start bit on data line
|
||||
ps2_mouse_data <= 1'b0; // start bit is 0
|
||||
end
|
||||
end else begin
|
||||
|
||||
// transmission of 8 data bits
|
||||
if((ps2_mouse_tx_state >= 1)&&(ps2_mouse_tx_state < 9)) begin
|
||||
ps2_mouse_data <= ps2_mouse_tx_byte[0]; // data bits
|
||||
ps2_mouse_tx_byte[6:0] <= ps2_mouse_tx_byte[7:1]; // shift down
|
||||
if(ps2_mouse_tx_byte[0])
|
||||
ps2_mouse_parity <= !ps2_mouse_parity;
|
||||
end
|
||||
|
||||
// transmission of parity
|
||||
if(ps2_mouse_tx_state == 9)
|
||||
ps2_mouse_data <= ps2_mouse_parity;
|
||||
|
||||
// transmission of stop bit
|
||||
if(ps2_mouse_tx_state == 10)
|
||||
ps2_mouse_data <= 1'b1; // stop bit is 1
|
||||
|
||||
// advance state machine
|
||||
if(ps2_mouse_tx_state < 11)
|
||||
ps2_mouse_tx_state <= ps2_mouse_tx_state + 4'd1;
|
||||
else
|
||||
ps2_mouse_tx_state <= 4'd0;
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
// fifo to receive serial data from core to be forwarded to io controller
|
||||
|
||||
// 16 byte fifo to store serial bytes
|
||||
localparam SERIAL_OUT_FIFO_BITS = 6;
|
||||
reg [7:0] serial_out_fifo [(2**SERIAL_OUT_FIFO_BITS)-1:0];
|
||||
reg [SERIAL_OUT_FIFO_BITS-1:0] serial_out_wptr;
|
||||
reg [SERIAL_OUT_FIFO_BITS-1:0] serial_out_rptr;
|
||||
|
||||
wire serial_out_data_available = serial_out_wptr != serial_out_rptr;
|
||||
wire [7:0] serial_out_byte = serial_out_fifo[serial_out_rptr] /* synthesis keep */;
|
||||
wire [7:0] serial_out_status = { 7'b1000000, serial_out_data_available};
|
||||
|
||||
// status[0] is reset signal from io controller and is thus used to flush
|
||||
// the fifo
|
||||
always @(posedge serial_strobe or posedge status[0]) begin
|
||||
if(status[0] == 1) begin
|
||||
serial_out_wptr <= 0;
|
||||
end else begin
|
||||
serial_out_fifo[serial_out_wptr] <= serial_data;
|
||||
serial_out_wptr <= serial_out_wptr + 1;
|
||||
end
|
||||
end
|
||||
|
||||
always@(negedge spi_sck or posedge status[0]) begin
|
||||
if(status[0] == 1) begin
|
||||
serial_out_rptr <= 0;
|
||||
end else begin
|
||||
if((byte_cnt != 0) && (cmd == 8'h1b)) begin
|
||||
// read last bit -> advance read pointer
|
||||
if((bit_cnt == 7) && !byte_cnt[0] && serial_out_data_available)
|
||||
serial_out_rptr <= serial_out_rptr + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// SPI receiver
|
||||
always@(posedge spi_sck or posedge SPI_SS_IO) begin
|
||||
|
||||
if(SPI_SS_IO == 1) begin
|
||||
bit_cnt <= 3'd0;
|
||||
byte_cnt <= 8'd0;
|
||||
sd_ack <= 1'b0;
|
||||
sd_dout_strobe <= 1'b0;
|
||||
sd_din_strobe <= 1'b0;
|
||||
end else begin
|
||||
sd_dout_strobe <= 1'b0;
|
||||
sd_din_strobe <= 1'b0;
|
||||
|
||||
if(bit_cnt != 7)
|
||||
sbuf[6:0] <= { sbuf[5:0], SPI_MOSI };
|
||||
|
||||
bit_cnt <= bit_cnt + 3'd1;
|
||||
if((bit_cnt == 7)&&(byte_cnt != 8'd255))
|
||||
byte_cnt <= byte_cnt + 8'd1;
|
||||
|
||||
// finished reading command byte
|
||||
if(bit_cnt == 7) begin
|
||||
if(byte_cnt == 0) begin
|
||||
cmd <= { sbuf, SPI_MOSI};
|
||||
|
||||
// fetch first byte when sectore FPGA->IO command has been seen
|
||||
if({ sbuf, SPI_MOSI} == 8'h18)
|
||||
sd_din_strobe <= 1'b1;
|
||||
|
||||
if(({ sbuf, SPI_MOSI} == 8'h17) || ({ sbuf, SPI_MOSI} == 8'h18))
|
||||
sd_ack <= 1'b1;
|
||||
|
||||
end else begin
|
||||
|
||||
// buttons and switches
|
||||
if(cmd == 8'h01)
|
||||
but_sw <= { sbuf[2:0], SPI_MOSI };
|
||||
|
||||
if(cmd == 8'h02)
|
||||
joystick_0 <= { sbuf, SPI_MOSI };
|
||||
|
||||
if(cmd == 8'h03)
|
||||
joystick_1 <= { sbuf, SPI_MOSI };
|
||||
|
||||
if(cmd == 8'h04) begin
|
||||
// store incoming ps2 mouse bytes
|
||||
ps2_mouse_fifo[ps2_mouse_wptr] <= { sbuf, SPI_MOSI };
|
||||
ps2_mouse_wptr <= ps2_mouse_wptr + 1;
|
||||
end
|
||||
|
||||
if(cmd == 8'h05) begin
|
||||
// store incoming ps2 keyboard bytes
|
||||
ps2_kbd_fifo[ps2_kbd_wptr] <= { sbuf, SPI_MOSI };
|
||||
ps2_kbd_wptr <= ps2_kbd_wptr + 1;
|
||||
end
|
||||
|
||||
if(cmd == 8'h15)
|
||||
status <= { sbuf[6:0], SPI_MOSI };
|
||||
|
||||
// send sector IO -> FPGA
|
||||
if(cmd == 8'h17) begin
|
||||
// flag that download begins
|
||||
// sd_dout <= { sbuf, SPI_MOSI};
|
||||
sd_dout_strobe <= 1'b1;
|
||||
end
|
||||
|
||||
// send sector FPGA -> IO
|
||||
if(cmd == 8'h18)
|
||||
sd_din_strobe <= 1'b1;
|
||||
|
||||
// send SD config IO -> FPGA
|
||||
if(cmd == 8'h19) begin
|
||||
// flag that download begins
|
||||
// sd_dout <= { sbuf, SPI_MOSI};
|
||||
// sd card knows data is config if sd_dout_strobe is asserted
|
||||
// with sd_ack still being inactive (low)
|
||||
sd_dout_strobe <= 1'b1;
|
||||
end
|
||||
|
||||
// joystick analog
|
||||
if(cmd == 8'h1a) begin
|
||||
// first byte is joystick indes
|
||||
if(byte_cnt == 1)
|
||||
stick_idx <= { sbuf[1:0], SPI_MOSI };
|
||||
else if(byte_cnt == 2) begin
|
||||
// second byte is x axis
|
||||
if(stick_idx == 0)
|
||||
joystick_analog_0[15:8] <= { sbuf, SPI_MOSI };
|
||||
else if(stick_idx == 1)
|
||||
joystick_analog_1[15:8] <= { sbuf, SPI_MOSI };
|
||||
end else if(byte_cnt == 3) begin
|
||||
// third byte is y axis
|
||||
if(stick_idx == 0)
|
||||
joystick_analog_0[7:0] <= { sbuf, SPI_MOSI };
|
||||
else if(stick_idx == 1)
|
||||
joystick_analog_1[7:0] <= { sbuf, SPI_MOSI };
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
121
tutorials/soc/lesson7c/vga.v
Normal file
121
tutorials/soc/lesson7c/vga.v
Normal file
@@ -0,0 +1,121 @@
|
||||
// A simple system-on-a-chip (SoC) for the MiST
|
||||
// (c) 2015 Till Harbaum
|
||||
|
||||
// VGA controller generating 160x100 pixles. The VGA mode ised is 640x400
|
||||
// combining every 4 row and column
|
||||
|
||||
// http://tinyvga.com/vga-timing/640x400@70Hz
|
||||
|
||||
module vga (
|
||||
// pixel clock
|
||||
input pclk,
|
||||
|
||||
// CPU interface (write only!)
|
||||
input cpu_clk,
|
||||
input cpu_wr,
|
||||
input [13:0] cpu_addr,
|
||||
input [7:0] cpu_data,
|
||||
|
||||
// enable/disable scanlines
|
||||
input scanlines,
|
||||
|
||||
// output to VGA screen
|
||||
output reg hs,
|
||||
output reg vs,
|
||||
output [5:0] r,
|
||||
output [5:0] g,
|
||||
output [5:0] b
|
||||
);
|
||||
|
||||
// 640x400 70HZ VESA according to http://tinyvga.com/vga-timing/640x400@70Hz
|
||||
parameter H = 640; // width of visible area
|
||||
parameter HFP = 16; // unused time before hsync
|
||||
parameter HS = 96; // width of hsync
|
||||
parameter HBP = 48; // unused time after hsync
|
||||
|
||||
parameter V = 400; // height of visible area
|
||||
parameter VFP = 12; // unused time before vsync
|
||||
parameter VS = 2; // width of vsync
|
||||
parameter VBP = 35; // unused time after vsync
|
||||
|
||||
reg[9:0] h_cnt; // horizontal pixel counter
|
||||
reg[9:0] v_cnt; // vertical pixel counter
|
||||
|
||||
// both counters count from the begin of the visibla area
|
||||
|
||||
// horizontal pixel counter
|
||||
always@(posedge pclk) begin
|
||||
if(h_cnt==H+HFP+HS+HBP-1) h_cnt <= 10'd0;
|
||||
else h_cnt <= h_cnt + 10'd1;
|
||||
|
||||
// generate negative hsync signal
|
||||
if(h_cnt == H+HFP) hs <= 1'b0;
|
||||
if(h_cnt == H+HFP+HS) hs <= 1'b1;
|
||||
end
|
||||
|
||||
// veritical pixel counter
|
||||
always@(posedge pclk) begin
|
||||
// the vertical counter is processed at the begin of each hsync
|
||||
if(h_cnt == H+HFP) begin
|
||||
if(v_cnt==VS+VBP+V+VFP-1) v_cnt <= 10'd0;
|
||||
else v_cnt <= v_cnt + 10'd1;
|
||||
|
||||
// generate positive vsync signal
|
||||
if(v_cnt == V+VFP) vs <= 1'b1;
|
||||
if(v_cnt == V+VFP+VS) vs <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
// 16000 bytes of internal video memory for 160x100 pixel at 8 Bit (RGB 332)
|
||||
reg [7:0] vmem [160*100-1:0];
|
||||
|
||||
reg [13:0] video_counter;
|
||||
reg [7:0] pixel;
|
||||
|
||||
// write VRAM via CPU interface
|
||||
always @(posedge cpu_clk)
|
||||
if(cpu_wr)
|
||||
vmem[cpu_addr] <= cpu_data;
|
||||
|
||||
// read VRAM for video generation
|
||||
always@(posedge pclk) begin
|
||||
// The video counter is being reset at the begin of each vsync.
|
||||
// Otherwise it's increased every fourth pixel in the visible area.
|
||||
// At the end of the first three of four lines the counter is
|
||||
// decreased by the total line length to display the same contents
|
||||
// for four lines so 100 different lines are displayed on the 400
|
||||
// VGA lines.
|
||||
|
||||
// visible area?
|
||||
if((v_cnt < V) && (h_cnt < H)) begin
|
||||
// increase video counter after each pixel
|
||||
if(h_cnt[1:0] == 2'd3)
|
||||
video_counter <= video_counter + 14'd1;
|
||||
|
||||
pixel <= vmem[video_counter]; // read VRAM
|
||||
end else begin
|
||||
// video counter is manipulated at the end of a line outside
|
||||
// the visible area
|
||||
if(h_cnt == H+HFP) begin
|
||||
// the video counter is reset at the begin of the vsync
|
||||
// at the end of three of four lines it's decremented
|
||||
// one line to repeat the same pixels over four display
|
||||
// lines
|
||||
if(v_cnt == V+VFP)
|
||||
video_counter <= 14'd0;
|
||||
else if((v_cnt < V) && (v_cnt[1:0] != 2'd3))
|
||||
video_counter <= video_counter - 14'd160;
|
||||
end
|
||||
|
||||
pixel <= 8'h00; // color outside visible area: black
|
||||
end
|
||||
end
|
||||
|
||||
// split the 8 rgb bits into the three base colors. Every second line is
|
||||
// darker when scanlines are enabled
|
||||
wire scanline = scanlines && v_cnt[0];
|
||||
assign r = (!scanline)?{ pixel[7:5], 3'b000 }:{ 1'b0, pixel[7:5], 2'b00 };
|
||||
assign g = (!scanline)?{ pixel[4:2], 3'b000 }:{ 1'b0, pixel[4:2], 2'b00 };
|
||||
assign b = (!scanline)?{ pixel[1:0], 4'b0000 }:{ 1'b0, pixel[1:0], 3'b000 };
|
||||
|
||||
endmodule
|
||||
BIN
tutorials/soc/lesson7c/z80_soc.rom
Normal file
BIN
tutorials/soc/lesson7c/z80_soc.rom
Normal file
Binary file not shown.
@@ -407,6 +407,33 @@ Files required on SD card:
|
||||
- [`z80_soc.rom`](https://github.com/mist-devel/mist-board/raw/master/tutorials/soc/lesson7b/z80_soc.rom)
|
||||
- other files to show up in the directory listing
|
||||
|
||||
[Lesson 7c](https://github.com/mist-devel/mist-board/tree/master/tutorials/soc/lesson7c): Minimal block IO
|
||||
-----------------------
|
||||
|
||||
The fake SD card implementation in the previous two lessons used is
|
||||
useful for cores that already come with full SD card support or for
|
||||
cores which are supposed to be ported from the MIST to boards that
|
||||
have an SD card directly connected to the FPGA.
|
||||
|
||||
If this is not the case and you only want to get simple and direct
|
||||
access to the SD cards contents and don't plan to run your core on
|
||||
anything else than the MIST board then it's possible to bypass all the
|
||||
complexity of SD card handling and just request sector data from the
|
||||
IO controller.
|
||||
|
||||
This lesson implements such a simple interface. All SD card and SPI
|
||||
handling is removed from the core as well as the code running on the
|
||||
Z80. Thus the files `sd_card.v` and `spi.v` have been removed from the
|
||||
core and the file `mmc.c` has been removed from the Z80 source
|
||||
code. Intead the files `block_io.v` and `block_io.c` now provide the
|
||||
same functionality in a much simpler way and without going through the
|
||||
fake SD card.
|
||||
|
||||
Files required on SD card:
|
||||
- [`soc.rbf`](https://github.com/mist-devel/mist-board/raw/master/tutorials/soc/lesson7c/soc.rbf) renamed to `core.rbf`
|
||||
- [`z80_soc.rom`](https://github.com/mist-devel/mist-board/raw/master/tutorials/soc/lesson7c/z80_soc.rom)
|
||||
- other files to show up in the directory listing
|
||||
|
||||
[Lesson 8](https://github.com/mist-devel/mist-board/tree/master/tutorials/soc/lesson8): Audio
|
||||
---------------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user