441 lines
18 KiB
VHDL
441 lines
18 KiB
VHDL
--
|
|
-- Top-level FPGA design for Red Pitaya PuzzleFW firmware.
|
|
--
|
|
-- Joris van Rantwijk 2024
|
|
--
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.numeric_std.all;
|
|
|
|
library unisim;
|
|
use unisim.vcomponents.all;
|
|
|
|
library xpm;
|
|
use xpm.vcomponents.all;
|
|
|
|
use work.puzzlefw_pkg.all;
|
|
|
|
|
|
entity puzzlefw_top is
|
|
|
|
port (
|
|
|
|
-- Ports directly connected to ARM/PS.
|
|
DDR_0_addr: inout std_logic_vector(14 downto 0);
|
|
DDR_0_ba: inout std_logic_vector(2 downto 0);
|
|
DDR_0_cas_n: inout std_logic;
|
|
DDR_0_ck_n: inout std_logic;
|
|
DDR_0_ck_p: inout std_logic;
|
|
DDR_0_cke: inout std_logic;
|
|
DDR_0_cs_n: inout std_logic;
|
|
DDR_0_dm: inout std_logic_vector(3 downto 0);
|
|
DDR_0_dq: inout std_logic_vector(31 downto 0);
|
|
DDR_0_dqs_n: inout std_logic_vector(3 downto 0);
|
|
DDR_0_dqs_p: inout std_logic_vector(3 downto 0);
|
|
DDR_0_odt: inout std_logic;
|
|
DDR_0_ras_n: inout std_logic;
|
|
DDR_0_reset_n: inout std_logic;
|
|
DDR_0_we_n: inout std_logic;
|
|
FIXED_IO_0_ddr_vrn: inout std_logic;
|
|
FIXED_IO_0_ddr_vrp: inout std_logic;
|
|
FIXED_IO_0_mio: inout std_logic_vector(53 downto 0);
|
|
FIXED_IO_0_ps_clk: inout std_logic;
|
|
FIXED_IO_0_ps_porb: inout std_logic;
|
|
FIXED_IO_0_ps_srstb: inout std_logic;
|
|
|
|
-- Ports controlled by FPGA.
|
|
adc_dat_i: in adc_data_input_type; -- ADC data
|
|
adc_clk_i: in std_logic_vector(1 downto 0); -- ADC clock 1=pos, 0=neg
|
|
adc_clk_o: out std_logic_vector(1 downto 0); -- optional clock output for ADC
|
|
adc_cdcs_o: out std_logic; -- ADC clock duty cycle stabilizer
|
|
dac_dat_o: out std_logic_vector(13 downto 0); -- DAC data
|
|
dac_wrt_o: out std_logic; -- DAC write control
|
|
dac_sel_o: out std_logic; -- DAC channel select
|
|
dac_clk_o: out std_logic; -- DAC clock
|
|
dac_rst_o: out std_logic; -- DAC reset
|
|
dac_pwm_o: out std_logic_vector(3 downto 0); -- PWM DAC
|
|
exp_p_io: inout std_logic_vector(7 downto 0); -- extension I/O pos
|
|
exp_n_io: inout std_logic_vector(7 downto 0); -- extension I/O neg
|
|
led_o: inout std_logic_vector(7 downto 0) -- LEDs
|
|
);
|
|
|
|
end puzzlefw_top;
|
|
|
|
architecture arch of puzzlefw_top is
|
|
|
|
-- Main 125 MHz clock, derived from ADC clock input port.
|
|
signal clk_adc: std_logic;
|
|
|
|
-- Auxiliary clock from FCLK0.
|
|
signal clk_fclk: std_logic;
|
|
|
|
-- Main reset signal, derived from FCLK_RESET0, active high, synchronous to clk_adc.
|
|
signal s_reset: std_logic;
|
|
|
|
signal s_adc_clk_ibuf: std_logic;
|
|
signal r_fclk_cnt: unsigned(26 downto 0);
|
|
signal r_fclk_led: std_logic;
|
|
signal r_adcclk_cnt: unsigned(26 downto 0);
|
|
signal r_adcclk_led: std_logic;
|
|
|
|
signal s_apb_paddr: std_logic_vector(31 downto 0);
|
|
signal s_apb_penable: std_logic;
|
|
signal s_apb_prdata: std_logic_vector(31 downto 0);
|
|
signal s_apb_pready: std_logic;
|
|
signal s_apb_psel: std_logic;
|
|
signal s_apb_pslverr: std_logic;
|
|
signal s_apb_pwdata: std_logic_vector(31 downto 0);
|
|
signal s_apb_pwrite: std_logic;
|
|
|
|
signal s_axi_awid: std_logic_vector(5 downto 0);
|
|
signal s_axi_awaddr: std_logic_vector(31 downto 0);
|
|
signal s_axi_awlen: std_logic_vector(3 downto 0);
|
|
signal s_axi_awsize: std_logic_vector(2 downto 0);
|
|
signal s_axi_awburst: std_logic_vector(1 downto 0);
|
|
signal s_axi_awlock: std_logic_vector(1 downto 0);
|
|
signal s_axi_awcache: std_logic_vector(3 downto 0);
|
|
signal s_axi_awprot: std_logic_vector(2 downto 0);
|
|
signal s_axi_awqos: std_logic_vector(3 downto 0);
|
|
signal s_axi_awvalid: std_logic;
|
|
signal s_axi_awready: std_logic;
|
|
signal s_axi_wid: std_logic_vector(5 downto 0);
|
|
signal s_axi_wdata: std_logic_vector(63 downto 0);
|
|
signal s_axi_wstrb: std_logic_vector(7 downto 0);
|
|
signal s_axi_wlast: std_logic;
|
|
signal s_axi_wvalid: std_logic;
|
|
signal s_axi_wready: std_logic;
|
|
signal s_axi_bid: std_logic_vector(5 downto 0);
|
|
signal s_axi_bresp: std_logic_vector(1 downto 0);
|
|
signal s_axi_bvalid: std_logic;
|
|
signal s_axi_bready: std_logic;
|
|
signal s_axi_arid: std_logic_vector(5 downto 0);
|
|
signal s_axi_araddr: std_logic_vector(31 downto 0);
|
|
signal s_axi_arlen: std_logic_vector(3 downto 0);
|
|
signal s_axi_arsize: std_logic_vector(2 downto 0);
|
|
signal s_axi_arburst: std_logic_vector(1 downto 0);
|
|
signal s_axi_arlock: std_logic_vector(1 downto 0);
|
|
signal s_axi_arcache: std_logic_vector(3 downto 0);
|
|
signal s_axi_arprot: std_logic_vector(2 downto 0);
|
|
signal s_axi_arqos: std_logic_vector(3 downto 0);
|
|
signal s_axi_arvalid: std_logic;
|
|
signal s_axi_arready: std_logic;
|
|
signal s_axi_rid: std_logic_vector(5 downto 0);
|
|
signal s_axi_rdata: std_logic_vector(63 downto 0);
|
|
signal s_axi_rresp: std_logic_vector(1 downto 0);
|
|
signal s_axi_rlast: std_logic;
|
|
signal s_axi_rvalid: std_logic;
|
|
signal s_axi_rready: std_logic;
|
|
|
|
signal s_irq: std_logic_vector(7 downto 0);
|
|
|
|
signal s_reg_control: registers_control;
|
|
signal s_reg_status: registers_status;
|
|
signal s_reg_trigger: registers_trigger;
|
|
|
|
signal s_dma_read_cmd_addr: dma_address_type;
|
|
signal s_dma_read_cmd_valid: std_logic;
|
|
signal s_dma_read_cmd_ready: std_logic;
|
|
signal s_dma_read_data: dma_data_type;
|
|
signal s_dma_read_data_valid: std_logic;
|
|
signal s_dma_write_cmd_addr: dma_address_type;
|
|
signal s_dma_write_cmd_valid: std_logic;
|
|
signal s_dma_write_cmd_ready: std_logic;
|
|
signal s_dma_write_data: dma_data_type;
|
|
signal s_dma_write_data_ready: std_logic;
|
|
signal s_dma_write_finished: std_logic;
|
|
|
|
signal r_test_prefetch: std_logic;
|
|
signal r_test_raddr: std_logic_vector(9 downto 0);
|
|
signal r_test_waddr: std_logic_vector(9 downto 0);
|
|
signal s_test_dout: std_logic_vector(63 downto 0);
|
|
signal s_test_ren: std_logic;
|
|
|
|
begin
|
|
|
|
s_irq <= s_reg_control.test_irq;
|
|
led_o(7 downto 2) <= s_reg_control.test_led(7 downto 2);
|
|
|
|
-- Differential clock input for ADC clock.
|
|
inst_ibuf_adc_clk: IBUFDS
|
|
port map (
|
|
O => s_adc_clk_ibuf,
|
|
I => adc_clk_i(1),
|
|
IB => adc_clk_i(0)
|
|
);
|
|
|
|
-- Clock buffer for ADC clock.
|
|
inst_bufg_adc_clk: BUFG
|
|
port map (
|
|
I => s_adc_clk_ibuf,
|
|
O => clk_adc
|
|
);
|
|
|
|
inst_obuf_led0: OBUF
|
|
port map (
|
|
I => r_fclk_led,
|
|
O => led_o(0)
|
|
);
|
|
|
|
inst_obuf_led1: OBUF
|
|
port map (
|
|
I => r_adcclk_led,
|
|
O => led_o(1)
|
|
);
|
|
|
|
-- ARM/PS block design.
|
|
inst_blockdesign: entity work.puzzlefw_wrapper
|
|
port map (
|
|
sys_clk => clk_adc,
|
|
ps_fclk => clk_fclk,
|
|
peripheral_reset_0(0) => s_reset,
|
|
DDR_0_addr => DDR_0_addr,
|
|
DDR_0_ba => DDR_0_ba,
|
|
DDR_0_cas_n => DDR_0_cas_n,
|
|
DDR_0_ck_n => DDR_0_ck_n,
|
|
DDR_0_ck_p => DDR_0_ck_p,
|
|
DDR_0_cke => DDR_0_cke,
|
|
DDR_0_cs_n => DDR_0_cs_n,
|
|
DDR_0_dm => DDR_0_dm,
|
|
DDR_0_dq => DDR_0_dq,
|
|
DDR_0_dqs_n => DDR_0_dqs_n,
|
|
DDR_0_dqs_p => DDR_0_dqs_p,
|
|
DDR_0_odt => DDR_0_odt,
|
|
DDR_0_ras_n => DDR_0_ras_n,
|
|
DDR_0_reset_n => DDR_0_reset_n,
|
|
DDR_0_we_n => DDR_0_we_n,
|
|
FIXED_IO_0_ddr_vrn => FIXED_IO_0_ddr_vrn,
|
|
FIXED_IO_0_ddr_vrp => FIXED_IO_0_ddr_vrp,
|
|
FIXED_IO_0_mio => FIXED_IO_0_mio,
|
|
FIXED_IO_0_ps_clk => FIXED_IO_0_ps_clk,
|
|
FIXED_IO_0_ps_porb => FIXED_IO_0_ps_porb,
|
|
FIXED_IO_0_ps_srstb => FIXED_IO_0_ps_srstb,
|
|
APB_M_0_paddr => s_apb_paddr,
|
|
APB_M_0_penable => s_apb_penable,
|
|
APB_M_0_prdata => s_apb_prdata,
|
|
APB_M_0_pready(0) => s_apb_pready,
|
|
APB_M_0_psel(0) => s_apb_psel,
|
|
APB_M_0_pslverr(0) => s_apb_pslverr,
|
|
APB_M_0_pwdata => s_apb_pwdata,
|
|
APB_M_0_pwrite => s_apb_pwrite,
|
|
IRQ_F2P => s_irq,
|
|
S_AXI_HP0_0_araddr => s_axi_araddr,
|
|
S_AXI_HP0_0_arburst => s_axi_arburst,
|
|
S_AXI_HP0_0_arcache => s_axi_arcache,
|
|
S_AXI_HP0_0_arid => s_axi_arid,
|
|
S_AXI_HP0_0_arlen => s_axi_arlen,
|
|
S_AXI_HP0_0_arlock => s_axi_arlock,
|
|
S_AXI_HP0_0_arprot => s_axi_arprot,
|
|
S_AXI_HP0_0_arqos => s_axi_arqos,
|
|
S_AXI_HP0_0_arready => s_axi_arready,
|
|
S_AXI_HP0_0_arsize => s_axi_arsize,
|
|
S_AXI_HP0_0_arvalid => s_axi_arvalid,
|
|
S_AXI_HP0_0_awaddr => s_axi_awaddr,
|
|
S_AXI_HP0_0_awburst => s_axi_awburst,
|
|
S_AXI_HP0_0_awcache => s_axi_awcache,
|
|
S_AXI_HP0_0_awid => s_axi_awid,
|
|
S_AXI_HP0_0_awlen => s_axi_awlen,
|
|
S_AXI_HP0_0_awlock => s_axi_awlock,
|
|
S_AXI_HP0_0_awprot => s_axi_awprot,
|
|
S_AXI_HP0_0_awqos => s_axi_awqos,
|
|
S_AXI_HP0_0_awready => s_axi_awready,
|
|
S_AXI_HP0_0_awsize => s_axi_awsize,
|
|
S_AXI_HP0_0_awvalid => s_axi_awvalid,
|
|
S_AXI_HP0_0_bid => s_axi_bid,
|
|
S_AXI_HP0_0_bready => s_axi_bready,
|
|
S_AXI_HP0_0_bresp => s_axi_bresp,
|
|
S_AXI_HP0_0_bvalid => s_axi_bvalid,
|
|
S_AXI_HP0_0_rdata => s_axi_rdata,
|
|
S_AXI_HP0_0_rid => s_axi_rid,
|
|
S_AXI_HP0_0_rlast => s_axi_rlast,
|
|
S_AXI_HP0_0_rready => s_axi_rready,
|
|
S_AXI_HP0_0_rresp => s_axi_rresp,
|
|
S_AXI_HP0_0_rvalid => s_axi_rvalid,
|
|
S_AXI_HP0_0_wdata => s_axi_wdata,
|
|
S_AXI_HP0_0_wid => s_axi_wid,
|
|
S_AXI_HP0_0_wlast => s_axi_wlast,
|
|
S_AXI_HP0_0_wready => s_axi_wready,
|
|
S_AXI_HP0_0_wstrb => s_axi_wstrb,
|
|
S_AXI_HP0_0_wvalid => s_axi_wvalid
|
|
);
|
|
|
|
-- Memory-mapped registers.
|
|
inst_registers: entity work.registers
|
|
port map (
|
|
clk => clk_adc,
|
|
reset => s_reset,
|
|
apb_psel => s_apb_psel,
|
|
apb_penable => s_apb_penable,
|
|
apb_pwrite => s_apb_pwrite,
|
|
apb_paddr => s_apb_paddr,
|
|
apb_pwdata => s_apb_pwdata,
|
|
apb_pready => s_apb_pready,
|
|
apb_pslverr => s_apb_pslverr,
|
|
apb_prdata => s_apb_prdata,
|
|
reg_control => s_reg_control,
|
|
reg_status => s_reg_status,
|
|
reg_trigger => s_reg_trigger
|
|
);
|
|
|
|
-- AXI master.
|
|
inst_axi_master: entity work.dma_axi_master
|
|
generic map (
|
|
transfer_size => 16,
|
|
num_read_channels => 1,
|
|
num_write_channels => 1 )
|
|
port map (
|
|
clk => clk_adc,
|
|
reset => s_reset,
|
|
dma_en => s_reg_control.dma_en,
|
|
dma_busy => s_reg_status.dma_busy,
|
|
window_base_addr => s_reg_control.dma_buf_addr,
|
|
window_size => s_reg_control.dma_buf_size,
|
|
err_read => s_reg_status.dma_err_read,
|
|
err_write => s_reg_status.dma_err_write,
|
|
err_address => s_reg_status.dma_err_address,
|
|
err_any => s_reg_status.dma_err_any,
|
|
clear_errors => s_reg_trigger.dma_clear,
|
|
read_cmd_addr(0) => s_dma_read_cmd_addr,
|
|
read_cmd_valid(0) => s_dma_read_cmd_valid,
|
|
read_cmd_ready(0) => s_dma_read_cmd_ready,
|
|
read_data(0) => s_dma_read_data,
|
|
read_data_valid(0) => s_dma_read_data_valid,
|
|
write_cmd_addr(0) => s_dma_write_cmd_addr,
|
|
write_cmd_valid(0) => s_dma_write_cmd_valid,
|
|
write_cmd_ready(0) => s_dma_write_cmd_ready,
|
|
write_data(0) => s_dma_write_data,
|
|
write_data_ready(0) => s_dma_write_data_ready,
|
|
write_finished(0) => s_dma_write_finished,
|
|
m_axi_awid => s_axi_awid,
|
|
m_axi_awaddr => s_axi_awaddr,
|
|
m_axi_awlen => s_axi_awlen,
|
|
m_axi_awsize => s_axi_awsize,
|
|
m_axi_awburst => s_axi_awburst,
|
|
m_axi_awlock => s_axi_awlock,
|
|
m_axi_awcache => s_axi_awcache,
|
|
m_axi_awprot => s_axi_awprot,
|
|
m_axi_awqos => s_axi_awqos,
|
|
m_axi_awvalid => s_axi_awvalid,
|
|
m_axi_awready => s_axi_awready,
|
|
m_axi_wid => s_axi_wid,
|
|
m_axi_wdata => s_axi_wdata,
|
|
m_axi_wstrb => s_axi_wstrb,
|
|
m_axi_wlast => s_axi_wlast,
|
|
m_axi_wvalid => s_axi_wvalid,
|
|
m_axi_wready => s_axi_wready,
|
|
m_axi_bid => s_axi_bid,
|
|
m_axi_bresp => s_axi_bresp,
|
|
m_axi_bvalid => s_axi_bvalid,
|
|
m_axi_bready => s_axi_bready,
|
|
m_axi_arid => s_axi_arid,
|
|
m_axi_araddr => s_axi_araddr,
|
|
m_axi_arlen => s_axi_arlen,
|
|
m_axi_arsize => s_axi_arsize,
|
|
m_axi_arburst => s_axi_arburst,
|
|
m_axi_arlock => s_axi_arlock,
|
|
m_axi_arcache => s_axi_arcache,
|
|
m_axi_arprot => s_axi_arprot,
|
|
m_axi_arqos => s_axi_arqos,
|
|
m_axi_arvalid => s_axi_arvalid,
|
|
m_axi_arready => s_axi_arready,
|
|
m_axi_rid => s_axi_rid,
|
|
m_axi_rdata => s_axi_rdata,
|
|
m_axi_rresp => s_axi_rresp,
|
|
m_axi_rlast => s_axi_rlast,
|
|
m_axi_rvalid => s_axi_rvalid,
|
|
m_axi_rready => s_axi_rready
|
|
);
|
|
|
|
-- little test machine for DMA
|
|
inst_mem: xpm_memory_sdpram
|
|
generic map (
|
|
CLOCKING_MODE => "common_clock",
|
|
MEMORY_PRIMITIVE => "block",
|
|
MEMORY_SIZE => 1024 * 64,
|
|
ADDR_WIDTH_A => 10,
|
|
ADDR_WIDTH_B => 10,
|
|
WRITE_DATA_WIDTH_A => 64,
|
|
BYTE_WRITE_WIDTH_A => 64,
|
|
READ_DATA_WIDTH_B => 64,
|
|
READ_LATENCY_B => 1 )
|
|
port map (
|
|
clka => clk_adc,
|
|
clkb => clk_adc,
|
|
rstb => s_reset,
|
|
addra => r_test_waddr,
|
|
addrb => r_test_raddr,
|
|
dina => s_dma_read_data,
|
|
doutb => s_test_dout,
|
|
ena => s_dma_read_data_valid,
|
|
enb => s_test_ren,
|
|
wea => "1",
|
|
regceb => '1',
|
|
injectdbiterra => '0',
|
|
injectsbiterra => '0',
|
|
sleep => '0' );
|
|
|
|
s_dma_write_data <= not s_test_dout;
|
|
s_test_ren <= r_test_prefetch or s_dma_write_data_ready;
|
|
|
|
process (clk_adc) is
|
|
begin
|
|
if rising_edge(clk_adc) then
|
|
r_test_prefetch <= '0';
|
|
if s_dma_read_cmd_ready = '1' and s_dma_read_cmd_valid = '1' then
|
|
if unsigned(s_dma_read_cmd_addr) < 1008 then
|
|
s_dma_read_cmd_addr <= std_logic_vector(unsigned(s_dma_read_cmd_addr) + 16);
|
|
else
|
|
s_dma_read_cmd_valid <= '0';
|
|
end if;
|
|
end if;
|
|
if s_dma_read_data_valid = '1' then
|
|
s_reg_status.rcnt <= s_reg_status.rcnt + 1;
|
|
r_test_waddr <= std_logic_vector(unsigned(r_test_waddr) + 1);
|
|
if unsigned(r_test_waddr) = 1023 then
|
|
s_dma_write_cmd_valid <= '1';
|
|
r_test_prefetch <= '1';
|
|
end if;
|
|
end if;
|
|
if s_dma_write_cmd_ready = '1' and s_dma_write_cmd_valid = '1' then
|
|
if unsigned(s_dma_write_cmd_addr) < 1008 then
|
|
s_dma_write_cmd_addr <= std_logic_vector(unsigned(s_dma_write_cmd_addr) + 16);
|
|
else
|
|
s_dma_write_cmd_valid <= '0';
|
|
end if;
|
|
end if;
|
|
if (r_test_prefetch = '1') or (s_dma_write_data_ready = '1') then
|
|
r_test_raddr <= std_logic_vector(unsigned(r_test_raddr) + 1);
|
|
end if;
|
|
if s_dma_write_finished = '1' then
|
|
s_reg_status.wcnt <= s_reg_status.wcnt + 1;
|
|
end if;
|
|
if s_reg_trigger.start = '1' then
|
|
r_test_waddr <= (others => '0');
|
|
r_test_raddr <= (others => '0');
|
|
s_dma_read_cmd_addr <= (others => '0');
|
|
s_dma_write_cmd_addr <= (others => '0');
|
|
s_dma_read_cmd_valid <= '1';
|
|
s_dma_write_cmd_valid <= '0';
|
|
end if;
|
|
end if;
|
|
end process;
|
|
-- END test
|
|
|
|
process (clk_fclk) is
|
|
begin
|
|
if rising_edge(clk_fclk) then
|
|
r_fclk_cnt <= r_fclk_cnt + 1;
|
|
r_fclk_led <= r_fclk_cnt(r_fclk_cnt'high);
|
|
end if;
|
|
end process;
|
|
|
|
process (clk_adc) is
|
|
begin
|
|
if rising_edge(clk_adc) then
|
|
r_adcclk_cnt <= r_adcclk_cnt + 1;
|
|
r_adcclk_led <= r_adcclk_cnt(r_adcclk_cnt'high);
|
|
end if;
|
|
end process;
|
|
|
|
end architecture;
|