M1: spi_transmitter architecture

This commit is contained in:
Matthias Biermann
2024-10-12 23:37:17 +02:00
parent 2e43230495
commit 1da70e5a1c
5 changed files with 266 additions and 15 deletions
+1 -1
View File
@@ -60,7 +60,7 @@
<Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/>
<Option Name="EnableBDX" Val="FALSE"/>
<Option Name="DSABoardId" Val="zybo-z7-20"/>
<Option Name="WTXSimLaunchSim" Val="0"/>
<Option Name="WTXSimLaunchSim" Val="3"/>
<Option Name="WTModelSimLaunchSim" Val="0"/>
<Option Name="WTQuestaLaunchSim" Val="0"/>
<Option Name="WTIesLaunchSim" Val="0"/>
+9 -8
View File
@@ -29,16 +29,17 @@ begin
SPI_Transmitter_Inst: entity work.spi_transmitter
generic map (
AW => AW
AW => AW,
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,
data => data,
addr => addr,
mosi => mosi,
sck => sck,
ssel => ssel
);
Rom_Inst: entity work.spi2display_rom
+6 -6
View File
@@ -7,14 +7,14 @@ end;
architecture rtl of spi2display_tb is
constant EXT_CLOCK_FREQ : integer := 125000000;
constant SCK_FREQ : integer := 1000000;
constant CPOL : std_logic := '0';
constant CPHA : std_logic := '0';
constant clk_half_period : time := 1 sec / EXT_CLOCK_FREQ / 2;
signal clk : std_logic := '0';
signal reset : std_logic := '1';
@@ -25,11 +25,11 @@ begin
end process;
reset <= '0' after 100 * clk_half_period;
dut: entity work.spi2display
generic map (
CPOL => CPOL,
CPHA => CPHA,
-- CPOL => CPOL,
-- CPHA => CPHA,
CLOCK_FREQ => EXT_CLOCK_FREQ,
SCK_FREQ => SCK_FREQ
)
@@ -40,5 +40,5 @@ begin
sck => open,
ssel => open
);
end;
+200
View File
@@ -1,5 +1,6 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity spi_transmitter is
generic(
@@ -22,7 +23,206 @@ end;
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 RegDataLd : std_logic := '0';
signal RegDataShift : std_logic := '0';
signal CntBitsEn : std_logic := '0';
signal CntBitsTC : std_logic := '0';
signal CtrlBits : std_logic_vector(1 downto 0) := "00";
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' or cntVal = 0 then
cntVal := to_unsigned(7, 3);
CntBitsTC <= '0';
elsif CntBitsEn = '1' then
cntVal := cntVal - 1;
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;
begin
-- Kontrollbits
CtrlBits <= data(9 downto 8);
-- 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 <= '0';
RegDataShift <= '0';
cntAddrEn <= '0';
CntBitsEn <= '0';
-- 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 <= '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;
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;
RegDataLd <= '1';
CntBitsEn <= '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 <= '1';
elsif CtrlBits = "11" or CtrlBits = "01" then
state_next <= S_START;
cntAddrRst <= '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 <= 'X';
RegDataShift <= 'X';
cntAddrEn <= 'X';
end if;
end case;
end process;
-- Register fuer Zustand und Moore-Ausgaenge
Reg: process
begin
wait until rising_edge(clk);
state <= state_next;
-- Berechnung der Moore-Ausgaenge
-- Default-Werte
ssel <= 'X';
sck <= 'X';
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;
end rtl;
+50
View File
@@ -0,0 +1,50 @@
# work-Bibliothek erzeugen, falls nicht schon vorhanden
if { [file exists work] == 0} {
vlib work
}
# Benoetigte Dateien uebersetzen
vcom -work work spi_transmitter.vhd
vcom -work work spi2display_rom.vhd
vcom -work work spi2display.vhd
vcom -work work spi2display_tb.vhd
# Simulator starten
vsim -voptargs=+acc spi2display_tb
# Breite der Namensspalte
configure wave -namecolwidth 128
configure wave -datasetprefix 0
configure wave -signalnamewidth 1
configure wave -namecolwidth 154
configure wave -valuecolwidth 100
set NumericStdNoWarnings 1
if {1} {
add wave -divider "Externe Signale - spi2display"
add wave -noupdate /spi2display_tb/dut/clk
add wave -noupdate /spi2display_tb/dut/reset
add wave -noupdate /spi2display_tb/dut/sck
add wave -noupdate /spi2display_tb/dut/mosi
add wave -noupdate /spi2display_tb/dut/ssel
}
if {1} {
add wave -divider "Interne Signale"
add wave -noupdate /spi2display_tb/dut/SPI_Transmitter_Inst/data
add wave -noupdate /spi2display_tb/dut/SPI_Transmitter_Inst/addr
add wave -divider "Steuerwerk"
add wave -noupdate /spi2display_tb/dut/SPI_Transmitter_Inst/Steuerwerk/state
add wave -noupdate /spi2display_tb/dut/SPI_Transmitter_Inst/Steuerwerk/state_next
add wave -divider "Steuersignale"
add wave -noupdate /spi2display_tb/dut/SPI_Transmitter_Inst/CntSckTc
add wave -noupdate /spi2display_tb/dut/SPI_Transmitter_Inst/CntBitsTC
add wave -noupdate /spi2display_tb/dut/SPI_Transmitter_Inst/CtrlBits
add wave -noupdate /spi2display_tb/dut/SPI_Transmitter_Inst/cntAddrEn
add wave -noupdate /spi2display_tb/dut/SPI_Transmitter_Inst/cntAddrRst
add wave -noupdate /spi2display_tb/dut/SPI_Transmitter_Inst/RegDataLd
add wave -noupdate /spi2display_tb/dut/SPI_Transmitter_Inst/RegDataShift
add wave -noupdate /spi2display_tb/dut/SPI_Transmitter_Inst/CntBitsEn
}
run 100 us