diff --git a/dsp/boot_rom.vhdl.in b/dsp/boot_rom.vhdl.in new file mode 100644 index 0000000..94bb32d --- /dev/null +++ b/dsp/boot_rom.vhdl.in @@ -0,0 +1,49 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity boot_rom is + generic + ( + addressWidth : in positive := 16; + busWidth : in positive := 16 + ); + port + ( + clk: in std_logic; + code_addr : in std_logic_vector(15 downto 0); + code_out : out std_logic_vector(15 downto 0); + + data_addr : in std_logic_vector(15 downto 0); + data_out : out std_logic_vector(15 downto 0) + ); +end boot_rom; + +architecture Behavioral of boot_rom is + constant alignment: positive := busWidth / 8; + constant romsize: natural := $nwords; + + type romtype is array(0 to romsize - 1) of std_logic_vector(15 downto 0); + signal romdata: romtype := ( +$words + ); +begin + + process(clk) is + variable code_index: natural; + variable data_index: natural; + begin + if rising_edge(clk) then + code_index := to_integer(unsigned(code_addr)) / alignment; + if code_index < romsize then + code_out <= romdata(code_index); + else + code_out <= x"0000"; + end if; + + data_index := to_integer(unsigned(data_addr)) / alignment; + data_out <= romdata(data_index); + end if; + end process; + +end Behavioral; diff --git a/dsp/dsp.vhdl b/dsp/dsp.vhdl new file mode 100644 index 0000000..5740676 --- /dev/null +++ b/dsp/dsp.vhdl @@ -0,0 +1,287 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use std.textio.all; + +entity dsp is + port + ( + clk: in std_logic; + rst: in std_logic; + + led: out std_logic_vector(7 downto 0); + + uart_rx: in std_logic; + uart_tx: out std_logic; + + pdmout0_pin: out std_logic + ); +end dsp; + +architecture rtl of dsp is + + component cpu is port + ( + clk: in std_logic; + rst: in std_logic; + + code_data: in std_logic_vector(15 downto 0); + code_addr: out std_logic_vector(15 downto 0); + + mem_in: in std_logic_vector(15 downto 0); + mem_out: out std_logic_vector(15 downto 0); + mem_addr: out std_logic_vector(15 downto 0); + mem_write: out std_logic; + mem_read: out std_logic; + mem_busy: in std_logic + ); + end component; + + component ram is + generic + ( + addressWidth : in positive := 16; + busWidth : in positive := 16; + size : in positive := 1024 + ); + port + ( + clk : in std_logic; + address : in std_logic_vector(addressWidth - 1 downto 0); + writeEnable : in std_logic; + dataIn : in std_logic_vector(busWidth - 1 downto 0); + dataOut : out std_logic_vector(busWidth - 1 downto 0) + ); + end component; + + component boot_rom is port + ( + clk: in std_logic; + + code_addr : in std_logic_vector(15 downto 0); + code_out : out std_logic_vector(15 downto 0); + + data_addr : in std_logic_vector(15 downto 0); + data_out : out std_logic_vector(15 downto 0) + ); + end component; + + component uart is + port + ( + clk : in std_logic; + rst : in std_logic; + + -- hardware + rx_pin : in std_logic; + tx_pin : out std_logic; + + -- bus interface + we : in std_logic; + re : in std_logic; + addr : in std_logic_vector(15 downto 0); + din : in std_logic_vector(15 downto 0); + dout : out std_logic_vector(15 downto 0) + ); + end component; + + component sysbus is + port + ( + clk: in std_logic; + rst: in std_logic; + + -- master port 0 + m0_addr: in std_logic_vector(15 downto 0); + m0_wdata: in std_logic_vector(15 downto 0); + m0_rdata: out std_logic_vector(15 downto 0); + m0_re: in std_logic; + m0_we: in std_logic; + m0_busy: out std_logic; + + -- master port 1 + m1_addr: in std_logic_vector(15 downto 0); + m1_wdata: in std_logic_vector(15 downto 0); + m1_rdata: out std_logic_vector(15 downto 0); + m1_re: in std_logic; + m1_we: in std_logic; + m1_busy: out std_logic; + + -- actual bus + bus_addr: out std_logic_vector(15 downto 0); + bus_wdata: out std_logic_vector(15 downto 0); + bus_rdata: in std_logic_vector(15 downto 0); + bus_re: out std_logic; + bus_we: out std_logic + ); + end component; + + component pdmout is + port + ( + clk : in std_logic; + rst : in std_logic; + + -- hardware + out_pin : out std_logic; + + -- bus interface + we : in std_logic; + addr : in std_logic_vector(15 downto 0); + din : in std_logic_vector(15 downto 0) + ); + end component; + + component square is + port + ( + clk : in std_logic; + rst : in std_logic; + + -- bus slave interface + s_we : in std_logic; + s_addr : in std_logic_vector(15 downto 0); + s_din : in std_logic_vector(15 downto 0); + + -- bus master interface (DMA!!) + m_busy : in std_logic; + m_we : out std_logic; + m_addr : out std_logic_vector(15 downto 0); + m_dout : out std_logic_vector(15 downto 0) + ); + end component; + + signal mem_write : std_logic; + signal rom_code_addr, rom_code_out, mem_in, mem_out, mem_addr: std_logic_vector(15 downto 0); + signal rom_data_addr, rom_data_out: std_logic_vector(15 downto 0); + + signal uart_din, uart_dout, uart_addr: std_logic_vector(15 downto 0); + signal uart_we, uart_re: std_logic; + + signal cpu_write, cpu_read, cpu_busy: std_logic; + signal cpu_mosi, cpu_miso, cpu_addr: std_logic_vector(15 downto 0); + + signal square_write, square_busy: std_logic; + signal square_mosi, square_addr: std_logic_vector(15 downto 0); + signal square0_s_din, square0_s_addr: std_logic_vector(15 downto 0); + signal square0_s_we : std_logic; + + signal pdmout0_din, pdmout0_addr: std_logic_vector(15 downto 0); + signal pdmout0_we : std_logic; + + signal bus_write, bus_read: std_logic; + signal bus_mosi, bus_miso, bus_addr: std_logic_vector(15 downto 0); + + signal led_r, led_next: std_logic_vector(7 downto 0); + +begin + cpu0: cpu port map(clk => clk, rst => rst, + code_data => rom_code_out, code_addr => rom_code_addr, + mem_in => cpu_miso, mem_out => cpu_mosi, mem_addr => cpu_addr, + mem_write => cpu_write, mem_read => cpu_read, mem_busy => cpu_busy); + + rom: boot_rom port map(clk => clk, code_addr => rom_code_addr, code_out => rom_code_out, + data_addr => rom_data_addr, data_out => rom_data_out); + + mem: ram port map(clk => clk, address => mem_addr, writeEnable => mem_write, + dataIn => mem_in, dataOut => mem_out); + + uart0: uart port map(clk => clk, rst => rst, rx_pin => uart_rx, tx_pin => uart_tx, + addr => uart_addr, din => uart_din, dout => uart_dout, + re => uart_re, we => uart_we); + + square0: square port map(clk => clk, rst => rst, + s_we => square0_s_we, s_addr => square0_s_addr, s_din => square0_s_din, + m_busy => square_busy, m_we => square_write, + m_addr => square_addr, m_dout => square_mosi); + + pdmout0: pdmout port map(clk => clk, rst => rst, + out_pin => pdmout0_pin, + we => pdmout0_we, addr => pdmout0_addr, din => pdmout0_din); + + + main_bus: sysbus port map(clk => clk, rst => rst, + m0_addr => cpu_addr, m0_wdata => cpu_mosi, m0_rdata => cpu_miso, + m0_re => cpu_read, m0_we => cpu_write, m0_busy => cpu_busy, + + m1_addr => square_addr, m1_wdata => square_mosi, m1_rdata => open, + m1_re => '0', m1_we => square_write, m1_busy => square_busy, + + bus_addr => bus_addr, bus_wdata => bus_mosi, bus_rdata => bus_miso, + bus_re => bus_read, bus_we => bus_write + ); + + -- system map + -- 0x0000 - 0x0fff ROM + -- 0x1000 - 0x1fff RAM + -- 0xc000 - 0xc00f LED0 + -- 0xc010 - 0xc01f UART0 + -- 0xc020 - 0xc02f PDMOUT0 + -- 0xc030 - 0xc03f SQUARE0 + + led <= led_r; + + process(clk, rst) + begin + if rising_edge(clk) then + led_r <= led_next; + end if; + + if rst = '1' then + led_r <= x"00"; + end if; + end process; + + process(bus_addr, bus_mosi, bus_write, mem_out, rst, rom_data_out, led_r, bus_read) + begin + + bus_miso <= x"0000"; + + rom_data_addr <= bus_addr and x"0fff"; + + mem_addr <= bus_addr and x"0fff"; + mem_in <= bus_mosi; + mem_write <= '0'; + + led_next <= led_r; + + uart_din <= bus_mosi; + uart_addr <= bus_addr and x"000f"; + uart_we <= '0'; + uart_re <= '0'; + + pdmout0_we <= '0'; + pdmout0_addr <= bus_addr and x"000f"; + pdmout0_din <= bus_mosi; + + square0_s_we <= '0'; + square0_s_addr <= bus_addr and x"000f"; + square0_s_din <= bus_mosi; + + case bus_addr(15 downto 12) is + when x"0" => + bus_miso <= rom_data_out; + when x"1" => + bus_miso <= mem_out; + mem_write <= bus_write; + when x"c" => + case bus_addr(7 downto 4) is + when x"0" => -- LED + if bus_write = '1' then + led_next <= bus_mosi(7 downto 0); + end if; + when x"1" => -- UART0 + bus_miso <= uart_dout; + uart_we <= bus_write; + uart_re <= bus_read; + when x"2" => -- PDMOUT0 + pdmout0_we <= bus_write; + when x"3" => -- SQUARE0 + square0_s_we <= bus_write; + when others => + end case; + when others => + end case; + end process; + +end rtl; diff --git a/dsp/dsp_test.vhdl b/dsp/dsp_test.vhdl new file mode 100644 index 0000000..6c8bd0e --- /dev/null +++ b/dsp/dsp_test.vhdl @@ -0,0 +1,80 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use std.textio.all; + +entity dsp_test is +end dsp_test; + +architecture rtl of dsp_test is + + component clock is port(clk: out std_logic); + end component; + + component dsp is + port( + clk: in std_logic; + rst: in std_logic; + + led: out std_logic_vector(7 downto 0); + + uart_rx: in std_logic; + uart_tx: out std_logic; + + pdmout0_pin: out std_logic + ); + end component; + + signal finished, clk, rst: std_logic := '0'; + + signal led: std_logic_vector(7 downto 0); + + signal uart_rx: std_logic; + signal uart_tx: std_logic; + signal pdmout0: std_logic; + + type str is array(integer range <>) of std_logic_vector(7 downto 0); + signal blarg: str(0 to 4) := (x"61", x"64", x"64", x"61", x"64"); + +begin + dut: dsp port map(clk => clk, rst => rst, + led => led, uart_rx => uart_rx, uart_tx => uart_tx, + pdmout0_pin => pdmout0); + + + clk <= not clk after 5 ns when finished /= '1' else '0'; + + process + begin + rst <= '1'; + + uart_rx <= '1'; + + wait for 15 ns; + assert(led=x"00") report "Fail rst" severity error; + + rst <= '0'; + + wait for 20 us; + for i in 0 to 4 loop + uart_rx <= '0'; -- start bit + wait for 8681 ns; + + for j in 0 to 7 loop + uart_rx <= blarg(i)(j); + wait for 8681 ns; + end loop; + + uart_rx <= '1'; -- stop bit + wait for 8681 ns; + + end loop; + + wait for 2 ms; + + assert false report "Test done." severity note; + + finished <= '1'; + wait; + end process; +end rtl; diff --git a/dsp/led.h b/dsp/led.h new file mode 100644 index 0000000..ec46a78 --- /dev/null +++ b/dsp/led.h @@ -0,0 +1,5 @@ +#pragma once + +struct led { + volatile uint8_t output; +}; diff --git a/dsp/main.c b/dsp/main.c new file mode 100644 index 0000000..06cd6ce --- /dev/null +++ b/dsp/main.c @@ -0,0 +1,35 @@ +#include "sys.h" + +void init() { + square0->output_address = pdmout0; + square0->high_val = 0xffff; + square0->low_val = 0x0000; + square0->flags = SQUARE_FLAG_ENABLE_msk; + // will set the period later +} + +int main() { + init(); + + while(1) { + uint8_t c = uart_read(uart0); + uint16_t period; + if (c == 'c') { + period = 1493; // C4, 262.63 Hz, maybe + } else if (c == 'd') { + period = 1330; // D4, 293.66 Hz, maybe + } else if (c == 'e') { + period = 1185; // E4, 329.63 Hz, maybe + } else if (c == 'f') { + period = 1119; // F4, 249.23 Hz, maybe + } else if (c == 'g') { + period = 996; // G4, 392.00 Hz, maybe + } else if (c == 'a') { + period = 887; // A4, 440.00 Hz, maybe + } else if (c == 'b') { + period = 791; // B4, 493.88 Hz, maybe + } + + square0->period = period; + } +} diff --git a/dsp/makefile b/dsp/makefile new file mode 100644 index 0000000..6d5da1c --- /dev/null +++ b/dsp/makefile @@ -0,0 +1,39 @@ +all: sim rom +sim: dsp_test.ghw +rom: boot_rom.gen.vhdl + +CC = ../bin/cc +LD = ../bin/ld + +CFLAGS = -I../wave -I../uart + +boot_rom.gen.vhdl: main.o ../uart/uart.o + +sim_sources = dsp_test.vhdl +sources = boot_rom.gen.vhdl dsp.vhdl \ + ../cpu/cpu.vhdl ../cpu/reg.vhdl \ + $(wildcard ../wave/*.vhdl) \ + $(wildcard ../sysbus/*.vhdl) \ + ../uart/uart.vhdl \ + ../first/ram.vhdl + + +%.gen.vhdl: + $(LD) -o $@ --vhdl $*.vhdl.in $^ + + +%.ghw: work-obj93.cf + ghdl -r $* --wave=$@ --assert-level=error + + +work-obj93.cf: $(sim_sources) $(sources) + ghdl -a $^ + +PHONY: sim clean + +clean: + rm -rf *.o *.gen.vhdl *.ghw work-obj93.cf + +.DELETE_ON_ERROR: + +.PRECIOUS: %.ghw diff --git a/dsp/sys.h b/dsp/sys.h new file mode 100644 index 0000000..d07c08e --- /dev/null +++ b/dsp/sys.h @@ -0,0 +1,15 @@ +#pragma once + +#include "led.h" +#include "uart.h" +#include "wave.h" + +#define LED0_BASE 0xc000 +#define UART0_BASE 0xc010 +#define PDMOUT0_BASE 0xc020 +#define SQUARE0_BASE 0xc030 + +#define led0 ((struct led*) LED0_BASE) +#define uart0 ((struct uart*) UART0_BASE) +#define pdmout0 ((struct pdmout*) PDMOUT0_BASE) +#define square0 ((struct square*) SQUARE0_BASE)