M1: Blockschaltbilder und spi_transmitter

This commit is contained in:
Matthias Biermann
2024-10-21 00:21:47 +02:00
parent 60548dd462
commit 5d6d85a198
4 changed files with 237 additions and 228 deletions
Binary file not shown.
+30 -10
View File
@@ -20,10 +20,14 @@ end;
architecture rtl of spi2display is
constant AW : POSITIVE := 8;
constant AW : POSITIVE := 8;
signal addr : std_logic_vector(AW-1 downto 0);
signal data : std_logic_vector(9 downto 0);
signal addr : std_logic_vector(AW-1 downto 0);
signal data_rom : std_logic_vector(9 downto 0);
signal data : std_logic_vector(7 downto 0);
signal valid : std_logic;
signal ready : std_logic;
begin
@@ -33,13 +37,16 @@ begin
CLKDIV => CLOCK_FREQ / (SCK_FREQ * 4)
)
port map (
clk => clk,
reset => reset,
data => data,
addr => addr,
mosi => mosi,
sck => sck,
ssel => ssel
clk => clk,
reset => reset,
s_data => data,
s_valid => valid,
s_ready => ready,
mosi => mosi,
sck => sck,
ssel => ssel
);
Rom_Inst: entity work.spi2display_rom
@@ -52,4 +59,17 @@ begin
dout => data
);
Control_Inst: entity work.spi_rom_control
port map (
clk => clk,
reset => reset,
addr => addr,
din => data_rom,
m_data => data,
m_valid => valid,
m_ready => ready
)
end rtl;
+29
View File
@@ -0,0 +1,29 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity spi_rom_control is
port (
-- control io
clk : in std_logic;
reset : in std_logic;
-- Interface rom
addr : out std_logic_vector(7 downto 0);
din : in std_logic_vector(9 downto 0);
-- Streaming Interface spi_transmitter
m_data : out std_logic_vector(7 downto 0);
m_valid : out std_logic;
m_ready : in std_logic;
);
end entity;
architecture rtl of spi_rom_control is
begin
end architecture;
+178 -218
View File
@@ -9,245 +9,205 @@ entity spi_transmitter is
AW : positive := 8;
CLKDIV : positive := 100000/4
);
port (
clk : in std_logic;
reset : in std_logic := '1';
data : in std_logic_vector ( 9 downto 0);
addr : out std_logic_vector (AW-1 downto 0);
s_data : in std_logic_vector (7 downto 0);
s_valid : in std_logic;
s_ready : out std_logic;
mosi : out std_logic:='1';
sck : out std_logic:='1';
ssel : out std_logic:='1'
);
end;
);
end;
architecture rtl of spi_transmitter is
architecture rtl of spi_transmitter is
-- Steuersignale zwischen Steuerwerk und Rechenwerk
signal cntAddrRst : std_logic := '0';
signal cntAddrEn : std_logic := '0';
signal CntSckTc : std_logic := '0';
signal CntSckRst : std_logic := '0';
signal RegDataLd : std_logic := '0';
signal RegDataShift : std_logic := '0';
signal RegDataEn : std_logic := '0';
signal CntBitsEn : std_logic := '0';
signal CntBitsTC : std_logic := '0';
signal CtrlBits : std_logic_vector(1 downto 0) := "00";
signal CntBitsRst : std_logic := '0';
-- Finite state machine
type state_t is (S_IDLE, S_STEP_1, S_STEP_2, S_STEP_3, S_STEP_4, S_ERROR);
signal state : state_t := S_IDLE;
signal state_next : state_t;
begin
Rechenwerk : block
begin
-- Zaehler fuer Adresse
CntAddr: process
variable cntVal : unsigned(AW-1 downto 0) := (others=>'0');
begin
wait until rising_edge(clk);
if reset = '1' or CntAddrRst = '1' then
cntVal := (others=>'0');
elsif cntAddrEn = '1' then
cntVal := cntVal + 1;
end if;
addr <= std_logic_vector(cntVal);
end process;
-- Zaehler fuer SPI-Takt SCK
CntSck: process
variable cntVal : unsigned(31 downto 0) := (others=>'0');
begin
wait until rising_edge(clk);
if reset = '1' or cntVal = 0 then
cntVal := to_unsigned(CLKDIV-1, 32);
else
cntVal := cntVal - 1;
end if;
if cntVal = 0 then
CntSckTc <= '1';
else
CntSckTc <= '0';
end if;
end process;
-- Zaheler fuer zu sendende Bits
CntBits: process
variable cntVal : unsigned(2 downto 0) := (others=>'0');
begin
wait until rising_edge(clk);
if reset = '1' then
cntVal := to_unsigned(0, 3);
elsif CntBitsEn = '1' then
if cntVal = 0 then
cntVal := to_unsigned(7, 3);
else
cntVal := cntVal - 1;
end if;
end if;
if cntVal = 0 then
CntBitsTC <= '1';
else
CntBitsTC <= '0';
end if;
end process;
-- Schieberegister Daten
RegData: process
variable Q : std_logic_vector(7 downto 0) := (others=>'0');
begin
wait until rising_edge(clk);
if RegDataLd = '1' then
Q := data(7 downto 0);
elsif RegDataShift = '1' then
Q := Q(6 downto 0) & '0';
end if;
mosi <= Q(7);
end process;
end block;
Steuerwerk : block
-- Typ fuer die Zustandswerte
type state_t is (S_START, S_STEP_1, S_STEP_2, S_STEP_3, S_STEP_4, S_DEAD_END, S_ERROR);
-- Interne Signale fuer Rechenwerk
signal state : state_t := S_START;
signal state_next : state_t;
-- Interne Signale fuer "Mealy"- Ausgaenge
signal RegDataLd_next : std_logic := '0';
signal RegDataShift_next : std_logic := '0';
signal cntAddrEn_next : std_logic := '0';
signal CntBitsEn_next : std_logic := '0';
signal cntAddrRst_next : std_logic := '0';
-- Zaehler fuer SPI-Takt SCK
CntSck: process
variable cntVal : unsigned(31 downto 0) := (others=>'0');
begin
-- Kontrollbits
CtrlBits <= data(9 downto 8);
wait until rising_edge(clk);
if CntSckRst = '1' or cntVal = 0 then
cntVal := to_unsigned(CLKDIV-1, 32);
else
cntVal := cntVal - 1;
end if;
-- Prozess zur Berechnung des Folgezustandes und der Mealy-Ausgaenge
Transition: process(Reset, CntSckTc, CntBitsTC, CtrlBits)
begin
-- Default-Werte fuer Folgezustand und Mealy-Ausgaenge
state_next <= S_ERROR;
RegDataLd_next <= '0';
RegDataShift_next <= '0';
cntAddrEn_next <= '0';
CntBitsEn_next <= '0';
cntAddrRst_next <= '0';
if cntVal = 0 then
CntSckTc <= '1';
else
CntSckTc <= '0';
end if;
end process;
-- Berechnung des Folgezustandes und der Mealy-Ausgaenge
case state is
when S_START =>
If reset = '1' then
state_next <= S_START;
elsif CntSckTc = '1' then
state_next <= S_STEP_1;
RegDataLd_next <= '1';
elsif CntSckTc = '0' then
state_next <= S_START;
end if;
when S_STEP_1 =>
If reset = '1' then
state_next <= S_START;
elsif CntSckTc = '1' then
state_next <= S_STEP_2;
elsif CntSckTc = '0' then
state_next <= S_STEP_1;
end if;
when S_STEP_2 =>
If reset = '1' then
state_next <= S_START;
elsif CntSckTc = '1' then
state_next <= S_STEP_3;
elsif CntSckTc = '0' then
state_next <= S_STEP_2;
end if;
when S_STEP_3 =>
If reset = '1' then
state_next <= S_START;
elsif CntSckTc = '1' then
state_next <= S_STEP_4;
CntBitsEn_next <= '1';
elsif CntSckTc = '0' then
state_next <= S_STEP_3;
end if;
when S_STEP_4 =>
If reset = '1' then
state_next <= S_START;
elsif CntSckTc = '0' then
state_next <= S_STEP_4;
elsif CntSckTc = '1' and CntBitsTC = '0' then
state_next <= S_STEP_1;
RegDataShift_next <= '1';
elsif CntSckTc = '1' and CntBitsTC = '1' then
if CtrlBits = "10" then
state_next <= S_DEAD_END;
elsif CtrlBits = "00" then
state_next <= S_START;
cntAddrEn_next <= '1';
elsif CtrlBits = "11" or CtrlBits = "01" then
state_next <= S_START;
cntAddrRst_next <= '1';
end if;
end if;
when S_DEAD_END =>
if reset = '1' then
state_next <= S_START;
else
state_next <= S_DEAD_END;
end if;
when S_ERROR =>
if reset = '1' then
state_next <= S_START;
else
state_next <= S_ERROR;
RegDataLd_next <= 'X';
RegDataShift_next <= 'X';
cntAddrEn_next <= 'X';
end if;
end case;
end process;
-- Zaheler fuer zu sendende Bits
CntBits: process
variable cntVal : unsigned(2 downto 0) := (others=>'0');
begin
wait until rising_edge(clk);
if CntBitsRst = '1' then
cntVal := to_unsigned(0, 3);
elsif CntBitsEn = '1' then
cntVal := cntVal - 1;
end if;
-- Register fuer Zustand und Ausgaenge
Reg: process
begin
wait until rising_edge(clk);
if cntVal = 0 then
CntBitsTC <= '1';
else
CntBitsTC <= '0';
end if;
end process;
-- Zustandswechsel
state <= state_next;
-- Ausgeange, welche abhaengig von Zustand und Eingaengen sind
RegDataLd <= RegDataLd_next;
RegDataShift <= RegDataShift_next;
cntAddrEn <= cntAddrEn_next;
CntBitsEn <= CntBitsEn_next;
cntAddrRst <= cntAddrRst_next;
-- Schieberegister Daten
RegData: process
variable Q : std_logic_vector(7 downto 0) := (others=>'0');
begin
wait until rising_edge(clk);
if RegDataLd = '1' then
Q := data; -- laden
elsif RegDataEn = '1' then
Q := Q(6 downto 0) & '0'; -- linksschieben
end if;
mosi <= Q(7);
end process;
-- Berechnung der Moore-Ausgaenge, die nur vom Zustand abhaengen
-- Default-Werte
ssel <= 'X';
sck <= 'X';
-- Prozesse fuer endlichen Automaten
Transition: process(reset, CntSckTc, CntBitsTC, s_valid)
begin
-- Default-Werte fuer Folgezustand und Mealy-Ausgaenge
state_next <= S_ERROR;
CntSckRst <= '0';
RegDataLd <= '0';
RegDataEn <= '0';
CntBitsEn <= '0';
CntBitsRst <= '0';
case state_next is
when S_START =>
ssel <= '1';
sck <= '0';
when S_STEP_1 =>
ssel <= '0';
sck <= '0';
when S_STEP_2 =>
ssel <= '0';
sck <= '1';
when S_STEP_3 =>
ssel <= '0';
sck <= '1';
when S_STEP_4 =>
ssel <= '0';
sck <= '0';
when S_DEAD_END =>
ssel <= '1';
sck <= '0';
when S_ERROR =>
ssel <= 'X';
sck <= 'X';
end case;
end process;
end block;
-- Berechnung des Folgezustandes und der Mealy-Ausgaenge
case state is
when S_IDLE =>
If reset = '1' then
state_next <= S_IDLE;
elsif s_valid = '1' then
state_next <= S_STEP_1;
RegDataLd <= '1';
CntBitsRst <= '1';
CntSckRst <= '1';
elsif s_valid = '0' then
state_next <= S_IDLE;
end if;
when S_STEP_1 =>
If reset = '1' then
state_next <= S_IDLE;
elsif CntSckTc = '1' then
state_next <= S_STEP_2;
elsif CntSckTc = '0' then
state_next <= S_STEP_1;
end if;
when S_STEP_2 =>
If reset = '1' then
state_next <= S_IDLE;
elsif CntSckTc = '1' then
state_next <= S_STEP_3;
elsif CntSckTc = '0' then
state_next <= S_STEP_2;
end if;
when S_STEP_3 =>
If reset = '1' then
state_next <= S_IDLE;
elsif CntSckTc = '1' then
state_next <= S_STEP_4;
CntBitsEn <= '1';
elsif CntSckTc = '0' then
state_next <= S_STEP_3;
end if;
when S_STEP_4 =>
If reset = '1' then
state_next <= S_IDLE;
elsif CntSckTc = '0' then
state_next <= S_STEP_4;
elsif CntSckTc = '1' and CntBitsTC = '0' then
state_next <= S_STEP_1;
RegDataEn <= '1';
CntBitsEn <= '1';
elsif CntSckTc = '1' and CntBitsTC = '1' then
state_next <= S_IDLE;
end if;
when S_ERROR =>
if reset = '1' then
state_next <= S_IDLE;
else
state_next <= S_ERROR;
CntSckRst <= 'X';
RegDataLd <= 'X';
RegDataEn <= 'X';
CntBitsEn <= 'X';
CntBitsRst <= 'X';
end if;
end case;
end process;
-- Register fuer Zustand und Ausgaenge
Reg: process
begin
wait until rising_edge(clk);
-- Zustandswechsel
state <= state_next;
-- Berechnung der Moore-Ausgaenge, die nur vom Zustand abhaengen
-- Default-Werte
ssel <= 'X';
sck <= 'X';
s_ready <= 'X';
case state_next is
when S_IDLE =>
ssel <= '1';
sck <= '0';
s_ready <= '1';
when S_STEP_1 =>
ssel <= '0';
sck <= '0';
s_ready <= '0';
when S_STEP_2 =>
ssel <= '0';
sck <= '1';
s_ready <= '0';
when S_STEP_3 =>
ssel <= '0';
sck <= '1';
s_ready <= '0';
when S_STEP_4 =>
ssel <= '0';
sck <= '0';
s_ready <= '0';
when S_DEAD_END =>
ssel <= '1';
sck <= '0';
s_ready <= '0';
when S_ERROR =>
ssel <= 'X';
sck <= 'X';
s_ready <= 'X';
end case;
end process;
end rtl;