TWiki
>
P1076 Web
>
Vhdl2019MeetingMinutes
>
2016_MeetingSeptember15
(revision 2) (raw view)
Edit
Attach
<!-- Set ALLOWTOPICCHANGE = P1076AdminGroup --> ---+!! P1076 September 15, 2016 Meeting Minutes ---++!! Attendees: * Brent Hayhoe, Patrick Lehmann, Rob Gaddi, Jim Lewis, Lieven Lemiengre, Kevin Jennings, Peter Flake, Jing Pang ---++!! Agenda: %TOC% ---++ Meeting Discussion * Interfaces - continue. * Reviewed ahb lite example with space ship operators from Rob * Reviewed spi example from Lieven with map functions * Actions / Next Steps * Test more syntax using popular editor <verbatim> ------------------------------------------- -- Support Package for AHB-Lite Protocol -- ------------------------------------------- library ieee; use ieee.std_logic_1164.all; package amba_ahbl_pkg subtype HADDR_vst is std_logic_vector(31 downto 0); subtype HBURST_vst is std_logic_vector(3 downto 0); subtype HPROT_vst is std_logic_vector(3 downto 0); subtype HSIZE_vst is std_logic_vector(2 downto 0); subtype HTRANS_vst is std_logic_vector(1 downto 0); constant HTRANS_IDLE : HTRANS_vst := "00"; constant HTRANS_BUSY : HTRANS_vst := "01"; constant HTRANS_NONSEQ : HTRANS_vst := "10"; constant HTRANS_SEQ : HTRANS_vst := "11"; constant HBURST_SINGLE : HBURST_vst := "000"; -- Single burst constant HBURST_INCR : HBURST_vst := "001"; -- Incrementing burst of undefined length constant HBURST_WRAP4 : HBURST_vst := "010"; -- 4-beat wrapping burst constant HBURST_INCR4 : HBURST_vst := "011"; -- 4-beat incrementing burst constant HBURST_WRAP8 : HBURST_vst := "100"; -- 8-beat wrapping burst constant HBURST_INCR8 : HBURST_vst := "101"; -- 8-beat incrementing burst constant HBURST_WRAP16 : HBURST_vst := "110"; -- 16-beat wrapping burst constant HBURST_INCR16 : HBURST_vst := "111"; -- 16-beat incrementing burst ----------------------------------------------------- -- Record & Array Types for AMBA AHB-Lite Protocol -- ----------------------------------------------------- -- The read/write data vectors are of undefined size. type ahbl_globals is record HCLK : std_logic; HRESET : std_logic; end record ahbl_globals; type ahbl_mosi_data is record HADDR_vst : HADDR_vst; -- AHBL address bus (32b) HBURST : HBURST_vst; -- AHBL burst type HMASTLOCK : std_logic; -- AHBL locked transfer control HPROT : HPROT_vst; -- AHBL access protection control HSIZE : HSIZE_vst; -- AHBL transfer size control HTRANS : HTRANS_vst; -- AHBL transfer type control HWDATA : std_logic_vector; -- AHBL write data bus (min 32 bits) HWRITE : std_logic -- AHBL transfer write/read control end record ahbl_mosi_data; type ahbl_miso_data is record HRDATA : std_logic_vector; -- AHBL read data bus (min 32 bits) HREADY : std_logic; -- AHBL transfer complete HRESP : std_logic -- AHBL transfer response end record ahbl_miso_data; type ahbl_master is port record mosi : out ahbl_mosi_data; miso : in ahbl_miso_data; gbl : in ahbl_globals end port record ahbl_master; type ahbl_slave is port record mosi : in ahbl_mosi_data; miso : out ahbl_miso_data; HSEL : in std_logic; gbl : in ahbl_globals end port record ahbl_master; type ahbl_miso_arr is array(natural range <>) of ahbl_miso_data; subtype ahbl_mosi_data32 is ahbl_mosi_data(HWDATA(31 downto 0)); subtype ahbl_miso_data32 is ahbl_miso_data(HRDATA(31 downto 0)); subtype ahbl_miso_arr32 is array(natural range <>) of ahbl_miso_data32; -- The proper syntax is one of these things here ----------------\ subtype ahbl_master32 is ahbl_master( mosi(ahbl_mosi_data32), miso(ahbl_miso_data32) -- * ); subtype ahbl_master32 is ahbl_master( mosi(HWDATA(31 downto 0)), miso(HWDATA(31 downto 0)) -- * ); -- Constraining record elements LRM p.52(66) -- signal sig : record_t(elem1(0 to 7), elem2(0 to 3)); subtype ahbl_slave32 is ahbl_master( mosi(ahbl_mosi_data32), miso(ahbl_miso_data32) ); -------------------------------- -- Context Clause for Package -- -------------------------------- context amba_ahbl_context; library ieee; use ieee.std_logic.1164.all; use work.amba_ahbl_pkg.all; end context amba_ahbl_context; end package amba_ahbl_pkg; package body amba_ahbl_pkg; end package body amba_ahbl_pkg; ----------------------------------------------------------------------- -- Declare entities for the master, slave and interconnect ----------------------------------------------------------------------- -- Wrap the decoder and multiplexer into a single interconnect block. context amba_ahbl_context; entity ahbl_interconnect is generic ( NSLAVES : positive ); port ( HADDR : in std_logic_vector; HSEL : out std_logic_vector(NSLAVES-1 downto 0); slv : in ahbl_miso_arr(NSLAVES-1 downto 0); mst : out ahbl_miso_data ); end entity ahbl_interconnect; context amba_ahbl_context; entity ahbl_cpu_haahvahd is port ( inst : port record ahbl_master32; data : port record ahbl_master32 ); end entity ahbl_cpu_haahvahd; context amba_ahbl_context; entity ahbl_ram is generic ( ADDR_BITS : positive ); port ( iface : port record ahbl_slave32; ); end entity ahbl_ram; ----------------------------------------------------------------------- -- Top Level ----------------------------------------------------------------------- context work.amba_ahbl_context; entity ahbl_block_ent is( end entity ahbl_block_ent; architecture rtl_arch of ahbl_block_ent is signal m_amba_ahb_rs : m_amba_ahb_rt; signal HSEL_vs : HSEL_vst; signal s_amba_ahb_rs : s_amba_ahb_rt; signal s_amba_ahb_as : s_amba_ahb_at; signal gbl : ahbl_globals; signal inst_bus : ahbl_master32'record; signal data_bus : ahbl_master32'record; signal slave_responses : ahbl_miso_arr32(2 downto 0); signal HSEL : std_logic_vector(2 downto 0); begin -- Clock and Reset Control for AHB-Lite Block clk_and_rst_inst : entity clk_and_rst_ent(rtl_arch) port map( rst_o => gbl.HRESET clk_o => gbl.HCLK ); gbl <=> inst_bus.gbl; gbl <=> data_bus.gbl; CPU: entity work.ahbl_cpu_haahvahd port map ( inst => inst_bus, data => data_bus ); RAM_SLAVES: for i in 0 to 2 generate signal slv : ahbl_slave32'record; begin slv.mosi <=> data_bus.mosi; slv.gbl <=> gbl; slv.miso <=> slave_responses(i); slv.HSEL <=> HSEL(i); RAM: entity work.entity ahbl_ram is generic map ( ADDR_BITS => 12 ) port map ( iface => slv ); end generate; IC: entity work.ahbl_interconnect generic map ( NSLAVES => 2 ) port map ( HADDR => data_bus.mosi.HADDR, HSEL => HSEL, slv => slave_responses, mst => data_bus.miso ); end architecture rtl_arch; type handshake_r is record rdy : std_logic; ack : std_logic; end type; port view handshake_mst of handshake_r is rdy : out ack : in end port view; -- handshake_mst'subtype refers to handshake_r type write_address_channel is port record addr : out std_logic vector; lock : out std_logic; hs : port record handshake; end type; type write_data_channel is port record dout : out std_logic_vector; hs : port record handshake end type; type handshake is port record rdy : out std_logic; ack : in std_logic; end type; type write_address_channel is port record addr : out std_logic vector; lock : out std_logic; hs : port record handshake; end type; type write_data_channel is port record dout : out std_logic_vector; hs : port record handshake end type; type read_address_channel is port record -- ... end type; type read_data_channel is port record -- ... end type; type axi is port record write_adr : port record write_address_channel; write_data : port record write_data_channel; read_adr : port record read_address_channel; read_data : port record read_data_channel; end type;</verbatim> From Lieven's Kobra.io page: <verbatim> package spi_bus_pkg is -- Underlying types. Masters use an unconstrained vector for -- chip selects; actual instantiations of the master interface -- will have to deal with making these concrete. type spi_master_r is record mosi : std_logic; -- Data from master to slave miso : std_logic; -- Data from slave to master sclk : std_logic; -- Serial clock ssel : std_logic_vector -- Chip selects (active-low) end record spi_master_r; type spi_slave_r is record mosi : std_logic; -- Data from master to slave miso : std_logic; -- Data from slave to master sclk : std_logic; -- Serial clock ssel : std_logic; -- Chip select (active-low) end record spi_slave_r; port view master of spi_master_r is mosi => out; miso => in; sclk => out; ssel => out; end port view master; -- automatically generated? map function master_constructor(signal mst : spi_master_r) to bus master spi_slave_r is begin map ( mosi => mst.mosi, miso => mst.miso, sclk => mst.sclk, ssel => mst.ssel ); end map function; alias reverse_master is master'reversed; port view slave of spi_slave_r is mosi => in; miso => out; sclk => in; ssel => in; end port view slave; alias reverse_slave is slave'reversed; -- map functions are structural functions, regular functions are behavioural map function slave_select(mst : bus reverse_master spi_master_r; chip_select : natural) to bus reverse_slave spi_slave_r is -- constant foo : integer := chip_select * 2; -- alias xys is mst.foo(2).bar; begin return map ( mosi => mst.mosi, miso => mst.miso, sclk => mst.sclk, ssel => mst.ssel(chip_select) ); end map function; map function clk_extractor(signal WB_SYS : in t_wb_sys; signal o : out std_logic) to (signal a : std_logic) is begin return WB_SYS.CLK_I; -- ?? map WB_SYS.CLK_I; -- ?? end map function; -- entity clk_extractor is -- port ( WB_SYS : in t_wb_sys; o : out std_logic); -- end entity clk_extractor; -- architecture Behavioral of clk_extractor is -- begin -- o <=> WB_SYS.CLK_I; -- end architecture Behavioral; end package spi_bus_pkg; package body spi_bus_pkg is end package body spi_bus_pkg; ------------------------------------------------------------------------ -- Using entities rather than mapfunctions to connect masters/slaves -- to the physical wiring on the PCB, since they exist right now and -- mapfunctions don't. -- -- The use of the spaceship operator (<=>) below is intended to make -- these connections without introducing delta cycles. ------------------------------------------------------------------------ -- Connect an SPI slave to an SPI bus. Since the bus is of type -- spi_master_r, but drives into us, we need to use the reverse of a -- master interface (or an anti-master) on this entity, and an -- anti-slave on the other side to connect to the slave. -- -- FPGA spi_slave_link ADC -- ---------- -------------------- --------- -- Master |-------| Anti- Anti- |----| Slave | -- | | Master Slave | | | -- ---------- -------------------- --------- -- use work.spi_bus_pkg.all; -- entity spi_slave_link is -- generic ( -- CHIP_SELECT : natural -- ); -- port ( -- mst : bus spi_master_r(master)'reversed; -- slv : bus spi_slave_r(slave)'reversed; -- ); -- end entity spi_slave_link; -- -- architecture Behavioral of spi_slave_link is -- begin -- slv.mosi <=> mst.mosi; -- <---- -- slv.miso <=> mst.miso; -- ----> -- slv.sclk <=> mst.sclk; -- <---- -- slv.ssel <=> mst.ssel(CHIP_SELECT); -- <---- -- end architecture Behavioral; -- This can be used to create our synthesizable code: -- Read 16 bits at a time from 3 ADCs, present them broadside. -- Write 16 bits to 1 DAC. -- The spi port declaration below is the only place that the number -- of chip selects is ever defined; everything else inherits that from -- this single point. SSEL(2 downto 0) are ADCs, SSEL(3) is the DAC. -- use work.spi_bus_pkg.all; entity spi_communicator is port ( spi : bus master spi_master_r(ssel(3 downto 0)); dac : in std_logic_vector(15 downto 0); adc0 : out std_logic_vector(15 downto 0); adc1 : out std_logic_vector(15 downto 0); adc2 : out std_logic_vector(15 downto 0); clk : in std_logic; rst : in std_logic ); end entity spi_communicator; architecture Behavioral of spi_communicator is begin MACHINE: process variable data : std_logic_vector(15 downto 0); variable bitn : integer range data'range; variable dev : integer range spi_ssel'range; type state is (RESET, SSEL_GO, SCLK_FALL, SCLK_RISE, SSEL_STOP); begin wait until rising_edge(clk); case state is when RESET => spi.mosi <= 'U'; spi.ssel <= (others => '1'); spi.sclk <= '1'; adc0 <= (others => 'U'); adc1 <= (others => 'U'); adc2 <= (others => 'U'); state := SSEL_GO; dev := 0; when SSEL_GO => spi.ssel(dev) <= '0'; state := SCLK_FALL; bitn := data'high; when SCLK_FALL => spi.sclk <= '0'; state := SCLK_RISE; when SCLK_RISE => spi.sclk <= '1'; spi.mosi <= dac(bitn); data(bitn) := spi.miso; if bitn = 0 then state := SSEL_STOP; else state := SCLK_FALL; bitn := bitn - 1; end if; when SSEL_STOP => spi.ssel <= (others => '1'); case adc is when 0 => adc0 <= data; when 1 => adc1 <= data; when 2 => adc2 <= data; when 3 => null; end case; adc := 0 when adc = 3 else (adc + 1); state := SSEL_GO; end case; if rst then state := RESET; end if; end process MACHINE; end architecture spi_communicator; ---------------------------------------------------------------------- -- Wrap it in an FPGA that does, presumably, other things as well. use work.spi_bus_pkg.all; entity FPGA is port( -- Number of chip selects here is undefined; the spi_communicator is -- sufficient to provide a definite size. spi : bus master spi_master_r; -- ... clk : in std_logic; rst : in std_logic ); end entity FPGA architecture Structural of FPGA is -- ... begin SPIMST: entity work.spi_communicator port map ( spi => spi, adc0 => intl_adc0, adc1 => intl_adc1, adc2 => intl_adc2, dac => dac, clk => clk, rst => rst ); -- ... end architecture Structural; And a testbench around it: ---------------------------------------------------------------------- -- Simulation models of ADC/DAC use ieee.numeric_std.all; use work.spi_bus_pkg.all; entity adc is port ( spi : bus slave spi_slave_r; vin : in real; ); end entity adc; architecture Behavioral of adc is signal intl_miso : std_logic_vector := 'Z'; begin FAKEIT: process variable data : unsigned(15 downto 0); variable bitn : integer range data'high downto -1; begin intl_miso <= 'Z'; wait until falling_edge(spi.ssel); data := TO_UNSIGNED(vin / 5.0 * 65536, data'length); bitn := data'high; loop if bitn = -1 then intl_miso <= 'U'; else intl_miso <= data(bitn); bitn := bitn - 1; end if; wait until rising_edge(spi.sclk) or rising_edge(spi.ssel); exit when spi.ssel'event; end loop; end process FAKEIT; spi.miso <= intl_miso after 10 ns; end architecture Behavioral; use ieee.numeric_std.all; use work.spi_bus_pkg.all; entity dac is port ( spi : bus spi_slave_r(slave); vout : out real := 0.0; ); end entity dac; architecture Behavioral of dac is begin FAKEIT: process variable data : unsigned(15 downto 0); variable bitn : integer range data'high downto -1; begin spi.miso <= 'Z'; wait until falling_edge(spi.ssel); data := (others => '0'); loop wait until rising_edge(spi.sclk) or rising_edge(spi.ssel); exit when spi.ssel'event; data := data(14 downto 0) & spi.mosi; end loop; vout <= REAL(TO_INTEGER(data)) * 5.0 / 65536.0 after 10 ns; end process FAKEIT; end architecture Behavioral; ---------------------------------------------------------------------- -- And the complete testbench use work.spi_bus_pkg.all; entity Testbench end entity Testbench; architecture TB of Testbench is signal clk : std_logic; signal rst : std_logic; -- Notice that SPI is just a normal signal here; the top level has no -- interest in the whole interfaces concept. Size is defined by the FPGA, -- which gets it from the spi_communicator. signal spi : spi_master_r; port spi_bus : bus master spi_master_r => master_constructor(spi); -- alternative port spi_bus : bus master spi_master_r => ( mosi => mst.mosi, miso => mst.miso, sclk => mst.sclk, ssel => mst.ssel ); port clk2 : std_logic => clk; -- behaves like an alias port daclnk : spi_slave_r => slave_select(spi_bus, 3); begin DUT: entity work.FPGA port map ( clk => clk, rst => rst, spi => master_constructor(spi) ); ADCS: for i in 0 to 2 generate begin -- And hook the ADC to that slave bus. ADC: entity work.adc port map ( spi => slave_select(spi, i), vin => analog_voltage(i) ); end generate ADCs; DAC: entity work.dac port map ( spi => slave_select(spi, 3), vout => driven_voltage ); -- And a resistive pullup for the tri-state MISO line. spi.miso <= 'H'; end architecture TB; </verbatim> ---++ Review and Approve Meeting Minutes and Decisions by Attendees ---++ Review and Approve Meeting Minutes and Decisions by non-attendees <Add your name below. Indicate if you agree or disagree> <If you disagree, add a list of items you disagree with and initiate a reflector discussion> TBD ---++ Next Meeting: Thursday [[2016_MeetingSeptember22][September 22, 2016]], 11 am Pacific ---+++ Previous Meeting: Wednesday [[2016_MeetingSeptember7][September 7, 2016]]
Edit
|
Attach
|
P
rint version
|
H
istory
:
r5
<
r4
<
r3
<
r2
<
r1
|
B
acklinks
|
V
iew topic
|
Raw edit
|
More topic actions...
Topic revision: r1 - 2020-02-17 - 15:36:18 -
TWikiGuest
P1076
Log In
or
Register
P1076 Web
Create New Topic
Index
Search
Changes
Notifications
RSS Feed
Statistics
Preferences
Webs
Main
P1076
Ballots
LCS2016_080
P10761
P1647
P16661
P1685
P1734
P1735
P1778
P1800
P1801
Sandbox
TWiki
VIP
VerilogAMS
Copyright © 2008-2026 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki?
Send feedback