diff --git a/cores_for_synthesis/WbWithFetchAndAvlStrToAvlMmb.sv b/cores_for_synthesis/WbWithFetchAndAvlStrToAvlMmb.sv new file mode 100644 index 0000000000000000000000000000000000000000..eca5ae97ec22decb483e325b8504e37cb4ba827c --- /dev/null +++ b/cores_for_synthesis/WbWithFetchAndAvlStrToAvlMmb.sv @@ -0,0 +1,319 @@ +/* +The DDR3 memory on the VFC-HD is 4Gb (per chip). +On the wishbone this is arranged as 128M Long Words (32 bits) +To address all the space 28 (27 for the prototype) bits of address are needed +The address bits are split between a page address (PageSelector input) +and a pointer to the LW in the page that we want to access via WishBone +*/ +module WbWithFetchAndAvlStrToAvlMmb +#( + parameter g_Log2PageSize = 6, // Comment: in 32bit words. Min is 2 as it must be 128bits alligned. Max is 12 as the longest burst is 1024 + parameter g_Log2BurstSize = 10 // Determines the lenght of the data (128b) FIFO (2*2**g_Log2BurstSize) +) +( + t_WbInterface WbSlave_iot, // Only g_Log2PageSize bits of address are used + input [28-g_Log2PageSize-1:0] PageSelector_ib, + output WriteFifoEmpty_o, + input FetchPage_ip, + output reg PageFetched_o + t_AvalonSt_tt AvlStD128_ts, + input LoadStreamerBaseAddress_ip, + input [25:0] StreamerBaseAddress_ib26, //The address in the DDR3 from which we start the streaming 'dump' + output [25:0] StreamerWriteAddress_ob26, + t_AvalonMMb_tt AvlMmBA26D128_tm +); + +parameter [10:0] c_PageMemDepth = 2**(g_Log2PageSize-2); +parameter [10:0] c_WriteBurstLenght = 2**(g_Log2BurstSize); + +typedef enum { + s_AvlIdle, + s_AvlPageRead, + s_AvlSingleWrite, + s_AvlPacketWrite +} t_AvlState; + +logic [127:0] PageMem_mb128 [c_PageMemDepth-1:0]; +logic WriteFifoFull, WeWriteFifo; +t_AvlState AvlState_l = s_AvlIdle, AvlNextState_l, AvlState_ld; +logic FetchPage_x = 0; +logic [2:0] FetchPage_xd3 = 0; +logic FetchPage_p = 0; +logic FetchDone_x = 0; +logic [2:0] FetchDone_xd3 = 0; +logic FetchRequest; +logic [28-g_Log2PageSize-1:0] PageToFetch_b; +logic [(g_Log2PageSize-2)-1:0] MemWrPointer_c; +logic [25:0] MemoryWriteAddress_b26; +logic [1:0] MemoryWriteLwSelect_b2; +logic [31:0] MemoryWriteLw_b32; +logic ReWriteFifo; +logic FetchDone_p = 0; +logic StreamerDataFifoFull, StreamerDataFifoEmpty; +logic StreamerDataFifoRe, StreamerDataFifoWe; +logic [127:0] StreamerDataFifoOut_b128; +logic StreamerPacketInfoFifoFull, StreamerPacketInfoFifoEmpty; +logic StreamerPacketInfoFifoRe, StreamerPacketInfoFifoWe; +logic [25:0] PacketBaseAddressWr_b26, PacketBaseAddressRd_b26; +logic [10:0] PacketSizeWr_b11, PacketSizeRd_b11; +logic [10:0] StoredStremerWords_b11; +logic ClosePacket; +logic LoadStreamerBaseAddress_d; +logic [10:0] WordsInPacketSent_c11; + +wire a_WbClk_k = WbSlave_iot.Clk_k; +wire a_AvlMMbClk_k = AvlMmBA26D128_tm.Clk_k; +wire a_AvlStClk_k = AvlStD128_ts.Clk_k; + +//=== WishBone interface +always @(posedge a_WbClk_k) + if (WbSlave_iot.Cyc && WbSlave_iot.Stb) begin //Wishbone access + if (WbSlave_iot.We) begin //write access + if (~WriteFifoFull && ~WbSlave_iot.Ack) begin + WeWriteFifo <= 1'b1; + WbSlave_iot.Ack <= 1'b1; + end else begin + WeWriteFifo <= 1'b0; + end + end else begin //read access + case (WbSlave_iot.Adr_b[1:0]) + 2'd0: WbSlave_iot.DatMiSo_b <= PageMem_mb128[WbSlave_iot.Adr_b[g_Log2PageSize-1:2]][ 31: 0]; + 2'd1: WbSlave_iot.DatMiSo_b <= PageMem_mb128[WbSlave_iot.Adr_b[g_Log2PageSize-1:2]][ 63:32]; + 2'd2: WbSlave_iot.DatMiSo_b <= PageMem_mb128[WbSlave_iot.Adr_b[g_Log2PageSize-1:2]][ 95:64]; + 2'd3: WbSlave_iot.DatMiSo_b <= PageMem_mb128[WbSlave_iot.Adr_b[g_Log2PageSize-1:2]][127:96]; + endcase + WbSlave_iot.Ack <= 1'b1; + end + end else begin + WbSlave_iot.Ack <= 1'b0; + WeWriteFifo <= 1'b0; + end//Wb access closed or simply no access + +generic_fifo_dc_gray_mod #(.dw(60), .aw(4)) + i_WriteFifo( + .rd_clk(a_AvlMMbClk_k), + .wr_clk(a_WbClk_k), + .rst(1'b1), + .clr(1'b0), + .din({PageSelector_ib, WbSlave_iot.Adr_b[g_Log2PageSize-1:0], WbSlave_iot.DatMoSi_b}), + .we(WeWriteFifo), + .dout({MemoryWriteAddress_b26, MemoryWriteLwSelect_b2, MemoryWriteLw_b32}), + .re(ReWriteFifo), + .full(WriteFifoFull), + .empty(WriteFifoEmpty_o), + .wr_level(/* Not Connected */), + .rd_level(/* Not Connected */) + ); + +//=== Synchronization logic + +always_ff @(posedge a_WbClk_k) + if (FetchPage_ip) begin + FetchPage_x <= ~FetchPage_x; + PageToFetch_b <= PageSelector_ib; + end + +always_ff @(posedge a_AvlMMbClk_k) + FetchPage_xd3 <= {FetchPage_xd3[1:0], FetchPage_x}; + +wire FetchPageAvl_p = ^FetchPage_xd3[2:1]; + +always_ff @(posedge a_AvlMMbClk_k) + if (FetchDone_p) + FetchDone_x <= ~FetchDone_x; + +always_ff @(posedge a_WbClk_k) + FetchDone_xd3 <= {FetchDone_xd3[1:0], FetchDone_x}; + +wire FetchDoneWb_p = ^FetchDone_xd3[2:1]; + +always_ff @(posedge a_WbClk_k) + if (FetchPage_ip) + PageFetched_o <= 1'b0; + else if (FetchDoneWb_p) + PageFetched_o <= 1'b1; + +//=== Avalon Streaming Interface +alias a_AvlStrClock_ik = AvlStD128_ts.Clk_k; +alias a_AvlStrData_ib128 = AvlStD128_ts.DataMoSi_b; +alias a_AvlStrValid_i = AvlStD128_ts.ValidMoSi; +alias a_AvlStrReady_o = AvlStD128_ts.ReadyMiSo; + +assign a_AvlStrReady_o = ~StreamerDataFifoFull && ~StreamerPacketInfoFifoFull; +assign StreamerDataFifoWe = a_AvlStrValid_i&&a_AvlStrReady_o; + +generic_fifo_dc_gray_mod #(.dw(128), .aw(g_Log2BurstSize+1)) + i_StreamerDataFifo( + .rd_clk(a_AvlMMbClk_k), + .wr_clk(a_AvlStrClock_ik), + .rst(1'b1), + .clr(1'b0), + .din(a_AvlStrData_ib128), + .we(StreamerDataFifoWe), + .dout(StreamerDataFifoOut_b128), + .re(StreamerDataFifoRe), + .full(StreamerDataFifoFull), + .empty(StreamerDataFifoEmpty), + .wr_level(/* Not Connected */), + .rd_level(/* Not Connected */) + ); + +always_ff @ (posedge a_AvlStrClock_ik) + LoadStreamerBaseAddress_d <= LoadStreamerBaseAddress_ip; + +assign ClosePacket = (StoredStremerWords_b11==c_WriteBurstLenght) || + (LoadStreamerBaseAddress_d && |StoredStremerWords_b11) || + (~a_AvlStrValid_i && |StoredStremerWords_b11); + +always_ff @ (posedge a_AvlStrClock_ik) + if (LoadStreamerBaseAddress_ip) + StreamerWriteAddress_ob26 <= StreamerBaseAddress_ib26; + else if (a_AvlStrValid_i && a_AvlStrReady_o) + StreamerWriteAddress_ob26 <= StreamerWriteAddress_ob26 + 1'b1; + +always_ff @ (posedge a_AvlStrClock_ik) begin + StreamerPacketInfoFifoWe <= 1'b0; + if (ClosePacket) begin + PacketSizeWr_b11 <= StoredStremerWords_b11; + StreamerPacketInfoFifoWe <= 1'b1; + StoredStremerWords_b11 <= {10'b0, StreamerDataFifoWe}; + if (StreamerDataFifoWe) + PacketBaseAddressWr_b26 <= StreamerWriteAddress_ob26; + end else if (StreamerDataFifoWe && ~|StoredStremerWords_b11) + PacketBaseAddressWr_b26 <= StreamerWriteAddress_ob26; +end + +generic_fifo_dc_gray_mod #(.dw(37), .aw(5)) // Up to 32 packet queue + i_StreamerPacketInfoFifo( + .rd_clk(a_AvlMMbClk_k), + .wr_clk(a_AvlStrClock_ik), + .rst(1'b1), + .clr(1'b0), + .din({PacketSizeWr_b11, PacketBaseAddressWr_b26}), + .we(StreamerPacketInfoFifoWe), + .dout({PacketSizeRd_b11, PacketBaseAddressRd_b26}), + .re(StreamerPacketInfoFifoRe), + .full(StreamerPacketInfoFifoFull), + .empty(StreamerPacketInfoFifoEmpty), + .wr_level(/* Not Connected */), + .rd_level(/* Not Connected */) + ); + +//=== Avalon Burst MM interface +always_ff @(posedge a_AvlMMbClk_k) + AvlState_l <= AvlNextState_l; + +always_comb begin + AvlNextState_l = AvlState_l; + case (AvlState_l) + s_AvlIdle: + if (~WriteFifoEmpty_o && ~ReWriteFifo) AvlNextState_l = s_AvlSingleWrite; + else if (FetchRequest) AvlNextState_l = s_AvlPageRead; + else if (~StreamerPacketInfoFifoRe) AvlNextState_l = s_AvlPacketWrite; + s_AvlSingleWrite: + if (~AvlMmBA26D128_tm.WaitRequestMiSo) + AvlNextState_l = s_AvlIdle; + s_AvlPageRead: + if (&MemWrPointer_c && ~AvlMmBA26D128_tm.WaitRequestMiSo) + AvlNextState_l = s_AvlIdle; + s_AvlPacketWrite: + if (WordsInPacketSent_c11!=AvlMmBA26D128_tm.BurstCountMoSi_b + && AvlMmBA26D128_tm.WriteMoSi + && ~AvlMmBA26D128_tm.WaitRequestMiSo) + AvlNextState_l = s_AvlIdle; + default: + AvlNextState_l = s_AvlIdle; + endcase +end + +always_ff @(posedge a_AvlMMbClk_k) begin + FetchRequest <= FetchPageAvl_p; + ReWriteFifo <= 1'b0; + AvlState_ld <= AvlState_l; + FetchDone_p <= 1'b0; + case (AvlState_l) + s_AvlIdle: begin + MemWrPointer_c <= 'h0; + AvlMmBA26D128_tm.ReadMoSi <= 1'b0; + AvlMmBA26D128_tm.WriteMoSi <= 1'b0; + StreamerDataFifoRe <= 1'b0; + StreamerPacketInfoFifoRe <= 1'b0; + WordsInPacketSent_c11 <= 11'd1; + end + s_AvlPageRead: begin + FetchRequest <= 1'b0; + AvlMmBA26D128_tm.BurstCountMoSi_b <= c_PageMemDepth; + AvlMmBA26D128_tm.ByteEnableMoSi <= 16'hFFFF; + AvlMmBA26D128_tm.AddressMoSi_b[26-1:(g_Log2PageSize-2)] <= PageToFetch_b; + AvlMmBA26D128_tm.AddressMoSi_b[(g_Log2PageSize-2)-1:0] <= 'b0; + if (AvlState_ld==s_AvlIdle) //first cycle in state + AvlMmBA26D128_tm.ReadMoSi <= 1'b1; + else if (~AvlMmBA26D128_tm.WaitRequestMiSo) //Request accepted + AvlMmBA26D128_tm.ReadMoSi <= 1'b0; + if (AvlNextState_l == s_AvlIdle) + FetchDone_p <= 1'b1; + if (AvlMmBA26D128_tm.ReadDataValidMiSo) begin + PageMem_mb128[MemWrPointer_c] <= AvlMmBA26D128_tm.DataReadMiSo_b; + MemWrPointer_c <= MemWrPointer_c + 1'b1; + end + end + s_AvlSingleWrite: begin + if (AvlState_ld==s_AvlIdle) begin//first cycle in state + ReWriteFifo <= 1'b1; + AvlMmBA26D128_tm.WriteMoSi <= 1'b1; + AvlMmBA26D128_tm.BurstCountMoSi_b <= 11'd1; + AvlMmBA26D128_tm.AddressMoSi_b <= MemoryWriteAddress_b26; + case (MemoryWriteLwSelect_b2) + 2'd0: begin + AvlMmBA26D128_tm.DataWriteMoSi_b <= {96'h0, MemoryWriteLw_b32}; + AvlMmBA26D128_tm.ByteEnableMoSi <= 16'h000F; + end + 2'd1: begin + AvlMmBA26D128_tm.DataWriteMoSi_b <= {64'h0, MemoryWriteLw_b32, 32'h0}; + AvlMmBA26D128_tm.ByteEnableMoSi <= 16'h00F0; + end + 2'd2: begin + AvlMmBA26D128_tm.DataWriteMoSi_b <= {32'h0, MemoryWriteLw_b32, 64'h0}; + AvlMmBA26D128_tm.ByteEnableMoSi <= 16'h0F00; + end + 2'd3: begin + AvlMmBA26D128_tm.DataWriteMoSi_b <= {MemoryWriteLw_b32, 96'h0}; + AvlMmBA26D128_tm.ByteEnableMoSi <= 16'hF000; + end + endcase + end else begin + ReWriteFifo <= 1'b0; + if (~AvlMmBA26D128_tm.WaitRequestMiSo) AvlMmBA26D128_tm.WriteMoSi <= 1'b0; + end + end + s_AvlPacketWrite: begin + if (AvlState_ld==s_AvlIdle) begin//first cycle in state + StreamerPacketInfoFifoRe <= 1'b1; + StreamerDataFifoRe <= 1'b1; + AvlMmBA26D128_tm.WriteMoSi <= 1'b1; + AvlMmBA26D128_tm.BurstCountMoSi_b <= PacketSizeRd_b11; + AvlMmBA26D128_tm.AddressMoSi_b <= PacketBaseAddressRd_b26; + AvlMmBA26D128_tm.DataWriteMoSi_b <= StreamerDataFifoOut_b128; + AvlMmBA26D128_tm.ByteEnableMoSi <= 16'hFFFF; + end else begin + StreamerPacketInfoFifoRe <= 1'b0; + StreamerDataFifoRe <= 1'b0; + if (AvlMmBA26D128_tm.WriteMoSi&&~AvlMmBA26D128_tm.WaitRequestMiSo) begin + WordsInPacketSent_c11 <= WordsInPacketSent_c11 + 1'b1; + AvlMmBA26D128_tm.DataWriteMoSi_b <= StreamerDataFifoOut_b128; + if (WordsInPacketSent_c11!=AvlMmBA26D128_tm.BurstCountMoSi_b) + StreamerDataFifoRe <= 1'b1; + else + AvlMmBA26D128_tm.WriteMoSi <= 1'b0; + end + end + end + default: begin + MemWrPointer_c <= 'h0; + AvlMmBA26D128_tm.ReadMoSi <= 1'b0; + AvlMmBA26D128_tm.WriteMoSi <= 1'b0; + end + endcase +end + +endmodule diff --git a/cores_for_synthesis/spi_dac_osc/cmb_to_wishbone.vhd b/cores_for_synthesis/spi_dac_osc/cmb_to_wishbone.vhd new file mode 100644 index 0000000000000000000000000000000000000000..4959ea81dc66810ad45e350b7029a43a79f512c0 --- /dev/null +++ b/cores_for_synthesis/spi_dac_osc/cmb_to_wishbone.vhd @@ -0,0 +1,186 @@ +--============================================================================================ +--################################## Module Information ################################## +--============================================================================================ +-- +-- Company: CERN (BE-BI-BL) +-- +-- Language: VHDL 2008 +-- +-- Description: +-- +-- CMB to Wishbone bridge +-- +--============================================================================================ + + +------------------------------------------------------------------------------- +-- Libraries +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +----------------------------------------------------------------------- +-- Entity +----------------------------------------------------------------------- +entity cmb_to_wishbone is + port ( + -- Clock and reset + clk_ik : in std_logic; + rst_ir : in std_logic; + cen_ie : in std_logic; + -- CMB input + cmb_frame_i : in std_logic; + cmb_addr_ib : in std_logic_vector(32-1 downto 0); + cmb_enable_ib : in std_logic_vector(32-1 downto 0); + cmb_wr_i : in std_logic; + cmb_wr_data_ib : in std_logic_vector(32-1 downto 0); + cmb_rd_i : in std_logic; + cmb_rd_data_ob : out std_logic_vector(32-1 downto 0); + cmb_rd_valid_o : out std_logic; + cmb_busy_o : out std_logic; + -- WB output + wb_cyc_o : out std_logic; + wb_stb_o : out std_logic; + wb_addr_ob : out std_logic_vector(32-1 downto 0); + wb_we_o : out std_logic; + wb_data_mosi_ob : out std_logic_vector(32-1 downto 0); + wb_data_miso_ib : in std_logic_vector(32-1 downto 0); + wb_ack_i : in std_logic + ); +end entity; + + + + +----------------------------------------------------------------------- +-- Architecture +----------------------------------------------------------------------- +architecture rtl of cmb_to_wishbone is + + -- CMB + signal cmb_rd_data : std_logic_vector(32-1 downto 0); + signal cmb_rd_valid : std_logic; + signal cmb_busy : std_logic; + + -- WB + signal wb_cyc : std_logic; + signal wb_stb : std_logic; + signal wb_addr : std_logic_vector(32-1 downto 0); + signal wb_we : std_logic; + signal wb_data_mosi : std_logic_vector(32-1 downto 0); + + -- Status + signal ongoing_access : std_logic; + +begin + + +--============================================================================= +-- CMB <-> Wishbone +--============================================================================= +p_bridge: process(clk_ik, rst_ir) + begin + if rst_ir = '1'then + --CMB + cmb_rd_data <= (others=>'0'); + cmb_rd_valid <= '0'; + cmb_busy <= '0'; + --WB + wb_cyc <= '0'; + wb_stb <= '0'; + wb_addr <= (others=>'0'); + wb_we <= '0'; + wb_data_mosi <= (others=>'0'); + --status + ongoing_access <= '0'; + + elsif rising_edge(clk_ik) then + if cen_ie='1' then + --======================== + --read request + if cmb_rd_i='1' and cmb_busy='0' then + --CMB + cmb_rd_data <= (others=>'0'); + cmb_rd_valid <= '0'; + cmb_busy <= '1'; + --WB + wb_cyc <= '1'; + wb_stb <= '1'; + wb_addr <= cmb_addr_ib; + wb_we <= '0'; + wb_data_mosi <= (others=>'0'); + --status + ongoing_access <= '1'; + --======================== + --write request + elsif cmb_wr_i='1' and cmb_busy='0' then + --CMB + cmb_rd_data <= (others=>'0'); + cmb_rd_valid <= '0'; + cmb_busy <= '1'; + --WB + wb_cyc <= '1'; + wb_stb <= '1'; + wb_addr <= cmb_addr_ib; + wb_we <= '1'; + wb_data_mosi <= cmb_wr_data_ib; + --status + ongoing_access <= '1'; + --======================== + --access ongoing + elsif ongoing_access='1' and cmb_busy='1' then + if wb_ack_i='1' then + --CMB + cmb_rd_data <= wb_data_miso_ib; + cmb_rd_valid <= wb_cyc and wb_stb and not(wb_we); + cmb_busy <= '1'; --access not released + --WB + wb_cyc <= '0'; + wb_stb <= '0'; + wb_addr <= (others=>'0'); + wb_we <= '0'; + wb_data_mosi <= (others=>'0'); + --status + ongoing_access <= '0'; + end if; + --======================== + --no access + else + --CMB + cmb_rd_data <= (others=>'0'); + cmb_rd_valid <= '0'; + --end of the access + if wb_ack_i='0' then + cmb_busy <= '0'; + end if; + --WB + wb_cyc <= '0'; + wb_stb <= '0'; + wb_addr <= (others=>'0'); + wb_we <= '0'; + wb_data_mosi <= (others=>'0'); + end if; + end if; + end if; + end process; + + + +--============================================================================= +-- Output assignments +--============================================================================= + + --CMB + cmb_rd_data_ob <= cmb_rd_data; + cmb_rd_valid_o <= cmb_rd_valid; + cmb_busy_o <= cmb_busy ; + --WB + wb_cyc_o <= wb_cyc ; + wb_stb_o <= wb_stb ; + wb_addr_ob <= wb_addr ; + wb_we_o <= wb_we ; + wb_data_mosi_ob <= wb_data_mosi; + + +end architecture; diff --git a/cores_for_synthesis/spi_dac_osc/spi_dac_fsm.vhd b/cores_for_synthesis/spi_dac_osc/spi_dac_fsm.vhd new file mode 100644 index 0000000000000000000000000000000000000000..8d59a4f0fa42510631fc4090c63d1478753e5e6a --- /dev/null +++ b/cores_for_synthesis/spi_dac_osc/spi_dac_fsm.vhd @@ -0,0 +1,185 @@ +--============================================================================================ +--################################## Module Information ################################## +--============================================================================================ +-- +-- Company: CERN (BE-BI-BL) +-- +-- Language: VHDL 2008 +-- +-- Description: +-- +-- FSM to program oscillator through SPI +-- +--============================================================================================ + + + +------------------------------------------------------------------------------- +-- Libraries definition +------------------------------------------------------------------------------- +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + + +--============================================================================= +-- Entity declaration +--============================================================================= +entity spi_dac_fsm is + port ( + clk_ik : in std_logic; + rst_ir : in std_logic; + cen_ie : in std_logic; + + new_val_i : in std_logic; + --0V0 is the midscale ( 20.000MHz) for the OSC3 + dac20_val_i : in std_logic_vector(15 downto 0); --0x0000=0d00000=0V0 for midrange + --1V6 is the midscale (125.000MHz) for the OSC2 + dac25_val_i : in std_logic_vector(15 downto 0); --0x51eb=0d20971=1V6 for midrange + + -- CMB sequence to SPI protocol + cmb_frame_o : out std_logic; + cmb_addr_ob : out std_logic_vector(32-1 downto 0); + cmb_enable_ob : out std_logic_vector(32-1 downto 0); + cmb_wr_o : out std_logic; + cmb_wr_data_ob : out std_logic_vector(32-1 downto 0); + cmb_rd_o : out std_logic; + cmb_rd_data_ib : in std_logic_vector(32-1 downto 0); + cmb_rd_valid_i : in std_logic; + cmb_busy_i : in std_logic + ); +end entity; + + + + +--============================================================================= +-- Architecture declaration +--============================================================================= +architecture rtl of spi_dac_fsm is + +----------------------------------------------------------------------- +-- Type declaration +----------------------------------------------------------------------- +type vadc_array is array(7 downto 0) of std_logic_vector(11 downto 0); + + +----------------------------------------------------------------------- +-- Constant declaration +----------------------------------------------------------------------- + +----------------------------------------------------------------------- +-- Signals declaration +----------------------------------------------------------------------- + --wait + signal first_prog : std_logic; + + --cmb + signal cmb_frame : std_logic; + signal cmb_addr : std_logic_vector(32-1 downto 0); + signal cmb_enable : std_logic_vector(32-1 downto 0); + signal cmb_wr : std_logic; + signal cmb_wr_data : std_logic_vector(32-1 downto 0); + signal cmb_rd : std_logic; + + -- Fsm + Type t_state is ( + s_IDLE, + s_SET_DAC25, --1V6 is the midscale (125.000MHz) for the OSC2 + s_SET_DAC20 --0V0 is the midscale ( 20.000MHz) for the OSC3 + ); + attribute SYN_ENCODING : STRING; + attribute SYN_ENCODING of t_state : type is "one-hot, safe"; + signal curr_state: t_state; + + +begin + + +--============================================================================= +-- FSM +--============================================================================= + --state flow process (synchronous) + p_protocol_fsm_flow: process (rst_ir, clk_ik) + begin + if rst_ir = '1' then + curr_state <= s_IDLE; + + first_prog <='1'; + + --CMB + cmb_frame <= '0'; + cmb_addr <= (others=>'0'); + cmb_enable <= (others=>'1'); + cmb_wr <= '0'; + cmb_wr_data <= (others=>'0'); + cmb_rd <= '0'; + + elsif rising_edge(clk_ik) then + if cen_ie = '1' then + + --default + cmb_frame <= '0'; + cmb_enable <= (others=>'1'); + + case curr_state is + + -- START or STOP the programming sequence + when s_IDLE => + if new_val_i='1' or first_prog='1' then + curr_state <= s_SET_DAC25; + first_prog <='0'; + end if; + + -- set DAC25 to 1V6 + when s_SET_DAC25 => + if cmb_busy_i='0' then --bus is free + if cmb_wr='0' and cmb_rd='0' then --no command on-going + cmb_addr <= x"00000000"; --DAC25 + cmb_wr <= '1'; + cmb_wr_data <= x"0000"& dac25_val_i; + cmb_rd <= '0'; + elsif cmb_wr='1' then --write is acknowledged + cmb_addr <= (others=>'0'); + cmb_wr <= '0'; + cmb_wr_data <= (others=>'0'); + cmb_rd <= '0'; + curr_state <= s_SET_DAC20; + end if; + end if; + + -- set DAC20 to 0V + when s_SET_DAC20 => + if cmb_busy_i='0' then --bus is free + if cmb_wr='0' and cmb_rd='0' then --no command on-going + cmb_addr <= x"00000001"; --DAC20 + cmb_wr <= '1'; + cmb_wr_data <= x"0000"& dac20_val_i; + cmb_rd <= '0'; + elsif cmb_wr='1' then --write is acknowledged + cmb_addr <= (others=>'0'); + cmb_wr <= '0'; + cmb_wr_data <= (others=>'0'); + cmb_rd <= '0'; + curr_state <= s_IDLE; + end if; + end if; + + -- OTHERS + when others => + curr_state <= s_IDLE; + + end case; + end if; + end if; + end process; + +--cmb +cmb_frame_o <= cmb_frame ; +cmb_addr_ob <= cmb_addr ; +cmb_enable_ob <= cmb_enable ; +cmb_wr_o <= cmb_wr ; +cmb_wr_data_ob <= cmb_wr_data ; +cmb_rd_o <= cmb_rd ; + +end architecture; diff --git a/cores_for_synthesis/spi_dac_osc/spi_dac_osc.qip b/cores_for_synthesis/spi_dac_osc/spi_dac_osc.qip new file mode 100644 index 0000000000000000000000000000000000000000..4524545fc9d65568ddc03b8490036260574ee15d --- /dev/null +++ b/cores_for_synthesis/spi_dac_osc/spi_dac_osc.qip @@ -0,0 +1,5 @@ +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "spi_dac_fsm.vhd"] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "spi_dac_osc.vhd"] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "spi_protocol.vhd"] +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "cmb_to_wishbone.vhd"] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "../SpiMasterWb.v"] diff --git a/cores_for_synthesis/spi_dac_osc/spi_dac_osc.vhd b/cores_for_synthesis/spi_dac_osc/spi_dac_osc.vhd new file mode 100644 index 0000000000000000000000000000000000000000..9b48d4224ce3cc87da9835ee07ea2759bbb0a2ef --- /dev/null +++ b/cores_for_synthesis/spi_dac_osc/spi_dac_osc.vhd @@ -0,0 +1,243 @@ +--============================================================================================ +--################################## Module Information ################################## +--============================================================================================ +-- +-- Company: CERN +-- +-- Language: VHDL 2008 +-- +-- Description: +-- +-- +---------------------------------------------------------------------------------------------- + + +------------------------------------------------------------------------------- +-- Libraries definition +------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library altera_mf; +use altera_mf.all; +use altera_mf.altera_mf_components.all; + +----------------------------------------------------------------------- +-- Entity +----------------------------------------------------------------------- +entity spi_dac_osc is +generic( + g_CLOCK_FREQ : integer := 100000000 --MHz +); +port ( + -- Clock: + clk_ik : in std_logic; + rst_ir : in std_logic; + cen_ie : in std_logic; + --input val + new_val_i : in std_logic; + --0V0 is the midscale ( 20.000MHz) for the OSC3 + dac20_val_i : in std_logic_vector(15 downto 0); --0x0000=0d00000=0V0 for midrange + --1V6 is the midscale (125.000MHz) for the OSC2 + dac25_val_i : in std_logic_vector(15 downto 0); --0x51eb=0d20971=1V6 for midrange + --SPI IO + PllDacSclk_ok : out std_logic; + PllDacDin_o : out std_logic; + PllDac25Sync_o : out std_logic; + PllDac20Sync_o : out std_logic +); +end entity; + + +--============================================================================= +-- Architecture declaration +--============================================================================= +architecture rtl of spi_dac_osc is + + + --CMB sequence from FSM to protocol + signal cmb_seq_frame : std_logic; + signal cmb_seq_addr : std_logic_vector(32-1 downto 0); + + signal cmb_seq_enable : std_logic_vector(32-1 downto 0); + signal cmb_seq_wr : std_logic; + signal cmb_seq_wr_data : std_logic_vector(32-1 downto 0); + signal cmb_seq_rd : std_logic; + signal cmb_seq_rd_data : std_logic_vector(32-1 downto 0); + signal cmb_seq_rd_valid : std_logic; + signal cmb_seq_busy : std_logic; + + --CMB command from protocol to SPI master + signal cmb_cmd_frame : std_logic; + signal cmb_cmd_addr : std_logic_vector(32-1 downto 0); + signal cmb_cmd_enable : std_logic_vector(32-1 downto 0); + signal cmb_cmd_wr : std_logic; + signal cmb_cmd_wr_data : std_logic_vector(32-1 downto 0); + signal cmb_cmd_rd : std_logic; + signal cmb_cmd_rd_data : std_logic_vector(32-1 downto 0); + signal cmb_cmd_rd_valid : std_logic; + signal cmb_cmd_busy : std_logic; + + -- SPI DAC OSC + signal WbLocSpiDacCtrlCyc : std_logic; + signal WbLocSpiDacCtrlStb : std_logic; + signal WbLocSpiDacCtrlAdr_b32 : std_logic_vector(32-1 downto 0); + signal WbLocSpiDacCtrlWr : std_logic; + signal WbLocSpiDacCtrlDatmosi_b32 : std_logic_vector(32-1 downto 0); + signal WbLocSpiDacCtrlDatmiso_b32 : std_logic_vector(32-1 downto 0); + signal WbLocSpiDacCtrlAck : std_logic; + + --internal Sleave select (32 available, but only 2 are mapped) + signal PllDacSs_nb32 : std_logic_vector(31 downto 0); + + --SPI Master WB + component SpiMasterWb is + port ( + Clk_ik : in std_logic; + Rst_irq : in std_logic; + Cyc_i : in std_logic; + Stb_i : in std_logic; + We_i : in std_logic; + Adr_ib3 : in std_logic_vector(2 downto 0); + Dat_ib32 : in std_logic_vector(31 downto 0); + Dat_oab32 : out std_logic_vector(31 downto 0); + Ack_oa : out std_logic; + WaitingNewData_o : out std_logic; + ModuleIdle_o : out std_logic; + SClk_o : out std_logic; + MoSi_o : out std_logic; + MiSo_ib32 : in std_logic_vector(31 downto 0); + SS_onb32 : out std_logic_vector(31 downto 0) + ); + end component; + + +begin + + --============================================================================= + -- Sequencing FSM + --============================================================================= + i_dac_fsm : entity work.spi_dac_fsm + port map( + clk_ik => clk_ik, -- in std_logic; + rst_ir => rst_ir, -- in std_logic; + cen_ie => cen_ie, -- in std_logic; + + new_val_i => new_val_i, -- in std_logic; + --0V0 is the midscale ( 20.000MHz) for the OSC3 + dac20_val_i => dac20_val_i, -- in std_logic_vector(15 downto 0); --0x0000=0d00000=0V0 for midrange + --1V6 is the midscale (125.000MHz) for the OSC2 + dac25_val_i => dac25_val_i, -- in std_logic_vector(15 downto 0); --0x51eb=0d20971=1V6 for midrange + + -- CMB sequence to SPI protocol + cmb_frame_o => cmb_seq_frame , -- out std_logic; + cmb_addr_ob => cmb_seq_addr , -- out std_logic_vector(g_RAM_ADDRSIZE-1 downto 0); + cmb_enable_ob => cmb_seq_enable , -- out std_logic_vector(g_RAM_DATASIZE-1 downto 0); + cmb_wr_o => cmb_seq_wr , -- out std_logic; + cmb_wr_data_ob => cmb_seq_wr_data , -- out std_logic_vector(g_RAM_DATASIZE-1 downto 0); + cmb_rd_o => cmb_seq_rd , -- out std_logic; + cmb_rd_data_ib => cmb_seq_rd_data , -- in std_logic_vector(g_RAM_DATASIZE-1 downto 0); + cmb_rd_valid_i => cmb_seq_rd_valid , -- in std_logic; + cmb_busy_i => cmb_seq_busy -- in std_logic + ); + + + + + --============================================================================= + -- SPI Protocol + --============================================================================= + i_dac_protocol : entity work.spi_protocol + generic map( + g_CLOCK_FREQ => g_CLOCK_FREQ --Hz + ) + port map( + -- Clock and reset + clk_ik => clk_ik, -- in std_logic; + rst_ir => rst_ir, -- in std_logic; + cen_ie => cen_ie, -- in std_logic; + -- CMB sequence input + cmb_in_frame_i => cmb_seq_frame , -- in std_logic; + cmb_in_addr_ib => cmb_seq_addr , -- in std_logic_vector(g_ADDR_LENGTH-1 downto 0); + cmb_in_enable_ib => cmb_seq_enable , -- in std_logic_vector(g_DATA_LENGTH-1 downto 0); + cmb_in_wr_i => cmb_seq_wr , -- in std_logic; + cmb_in_wr_data_ib => cmb_seq_wr_data , -- in std_logic_vector(g_DATA_LENGTH-1 downto 0); + cmb_in_rd_i => cmb_seq_rd , -- in std_logic; + cmb_in_rd_data_ob => cmb_seq_rd_data , -- out std_logic_vector(g_DATA_LENGTH-1 downto 0); + cmb_in_rd_valid_o => cmb_seq_rd_valid, -- out std_logic; + cmb_in_busy_o => cmb_seq_busy , -- out std_logic; + -- CMB commands output + cmb_out_frame_o => cmb_cmd_frame , -- out std_logic; + cmb_out_addr_ob => cmb_cmd_addr , -- out std_logic_vector(g_ADDR_LENGTH-1 downto 0); + cmb_out_enable_ob => cmb_cmd_enable , -- out std_logic_vector(g_DATA_LENGTH-1 downto 0); + cmb_out_wr_o => cmb_cmd_wr , -- out std_logic; + cmb_out_wr_data_ob => cmb_cmd_wr_data , -- out std_logic_vector(g_DATA_LENGTH-1 downto 0); + cmb_out_rd_o => cmb_cmd_rd , -- out std_logic; + cmb_out_rd_data_ib => cmb_cmd_rd_data , -- in std_logic_vector(g_DATA_LENGTH-1 downto 0); + cmb_out_rd_valid_i => cmb_cmd_rd_valid, -- in std_logic; + cmb_out_busy_i => cmb_cmd_busy -- in std_logic; + ); + + + --============================================================================= + -- CMB to WB bridge + --============================================================================= + i_cmb_to_wb: entity work.cmb_to_wishbone + port map( + -- Clock and reset + clk_ik => clk_ik, -- in std_logic; + rst_ir => rst_ir, -- in std_logic; + cen_ie => cen_ie, -- in std_logic; + -- CMB input + cmb_frame_i => cmb_cmd_frame , -- in std_logic; + cmb_addr_ib => cmb_cmd_addr , -- in std_logic_vector(g_ADDR_LENGTH-1 downto 0); + cmb_enable_ib => cmb_cmd_enable , -- in std_logic_vector(g_DATA_LENGTH-1 downto 0); + cmb_wr_i => cmb_cmd_wr , -- in std_logic; + cmb_wr_data_ib => cmb_cmd_wr_data , -- in std_logic_vector(g_DATA_LENGTH-1 downto 0); + cmb_rd_i => cmb_cmd_rd , -- in std_logic; + cmb_rd_data_ob => cmb_cmd_rd_data , -- out std_logic_vector(g_DATA_LENGTH-1 downto 0); + cmb_rd_valid_o => cmb_cmd_rd_valid, -- out std_logic; + cmb_busy_o => cmb_cmd_busy , -- out std_logic; + -- WB output + wb_cyc_o => WbLocSpiDacCtrlCyc, -- out std_logic; + wb_stb_o => WbLocSpiDacCtrlStb, -- out std_logic; + wb_addr_ob => WbLocSpiDacCtrlAdr_b32, -- out std_logic_vector(g_ADDR_LENGTH-1 downto 0); + wb_we_o => WbLocSpiDacCtrlWr, -- out std_logic; + wb_data_mosi_ob => WbLocSpiDacCtrlDatmosi_b32, -- out std_logic_vector(g_DATA_LENGTH-1 downto 0); + wb_data_miso_ib => WbLocSpiDacCtrlDatmiso_b32, -- in std_logic_vector(g_DATA_LENGTH-1 downto 0); + wb_ack_i => WbLocSpiDacCtrlAck -- in std_logic + ); + + + + --============================================================================= + -- SPI Master Wb + --============================================================================= + i_DacSpiMaster : SpiMasterWb + port map( + Rst_irq => rst_ir, + Clk_ik => clk_ik, + --WB + Cyc_i => WbLocSpiDacCtrlCyc, + Stb_i => WbLocSpiDacCtrlStb, + Adr_ib3 => WbLocSpiDacCtrlAdr_b32(2 downto 0), + We_i => WbLocSpiDacCtrlWr, + Dat_ib32 => WbLocSpiDacCtrlDatmosi_b32, + Dat_oab32 => WbLocSpiDacCtrlDatmiso_b32, + Ack_oa => WbLocSpiDacCtrlAck, + --SPI + SClk_o => PllDacSclk_ok, + MoSi_o => PllDacDin_o, + MiSo_ib32 => (others=>'0'), + SS_onb32 => PllDacSs_nb32, + WaitingNewData_o => open, + ModuleIdle_o => open + ); + + --Slave select outputs + PllDac25Sync_o <= PllDacSs_nb32(0); + PllDac20Sync_o <= PllDacSs_nb32(1); + +end architecture; + diff --git a/cores_for_synthesis/spi_dac_osc/spi_protocol.vhd b/cores_for_synthesis/spi_dac_osc/spi_protocol.vhd new file mode 100644 index 0000000000000000000000000000000000000000..2f7863cfc1ba33222ebbbe2b01ef19bc9f722588 --- /dev/null +++ b/cores_for_synthesis/spi_dac_osc/spi_protocol.vhd @@ -0,0 +1,361 @@ +--============================================================================================ +--################################## Module Information ################################## +--============================================================================================ +-- +-- Company: CERN (BE-BI-BL) +-- +-- Language: VHDL 2008 +-- +-- Description: +-- +-- Simple SPI protocol +-- +--============================================================================================ + + +------------------------------------------------------------------------------- +-- Libraries definition +------------------------------------------------------------------------------- +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +--============================================================================= +-- Entity declaration +--============================================================================= +entity spi_protocol is + generic ( + g_CLOCK_FREQ : integer := 100000000 + ); + port ( + -- Clock and reset + clk_ik : in std_logic; + rst_ir : in std_logic; + cen_ie : in std_logic; + -- CMB sequence input + cmb_in_frame_i : in std_logic; + cmb_in_addr_ib : in std_logic_vector(32-1 downto 0); + cmb_in_enable_ib : in std_logic_vector(32-1 downto 0); + cmb_in_wr_i : in std_logic; + cmb_in_wr_data_ib : in std_logic_vector(32-1 downto 0); + cmb_in_rd_i : in std_logic; + cmb_in_rd_data_ob : out std_logic_vector(32-1 downto 0); + cmb_in_rd_valid_o : out std_logic; + cmb_in_busy_o : out std_logic; + -- CMB commands output + cmb_out_frame_o : out std_logic; + cmb_out_addr_ob : out std_logic_vector(32-1 downto 0); + cmb_out_enable_ob : out std_logic_vector(32-1 downto 0); + cmb_out_wr_o : out std_logic; + cmb_out_wr_data_ob : out std_logic_vector(32-1 downto 0); + cmb_out_rd_o : out std_logic; + cmb_out_rd_data_ib : in std_logic_vector(32-1 downto 0); + cmb_out_rd_valid_i : in std_logic; + cmb_out_busy_i : in std_logic + ); +end entity; + + + + +--============================================================================= +-- Architecture declaration +--============================================================================= +architecture rtl of spi_protocol is + +-------------------------- +--CONSTANT +constant c_DAC_HALFPER : integer := g_CLOCK_FREQ/(1000000*20*2); --DAC SPI 20MHz (30MHz max) + +-------------------------- +--SIGNALS +signal wait_valid : std_logic; + +--CMB in +signal cmb_in_rd_data : std_logic_vector(32-1 downto 0); +signal cmb_in_rd_valid : std_logic; +signal cmb_in_busy : std_logic; +signal cmb_in_addr : std_logic_vector(32-1 downto 0); +signal cmb_in_wr : std_logic; +signal cmb_in_wr_data : std_logic_vector(32-1 downto 0); + +--CMB output +signal cmb_out_frame : std_logic; +signal cmb_out_addr : std_logic_vector(32-1 downto 0); +signal cmb_out_enable : std_logic_vector(32-1 downto 0); +signal cmb_out_wr : std_logic; +signal cmb_out_wr_data : std_logic_vector(32-1 downto 0); +signal cmb_out_rd : std_logic; + +--PSI parameters +signal conf1 : std_logic_vector(31 downto 0); +signal spi_pol : std_logic; +signal spi_pha : std_logic; +signal spi_lsb1st : std_logic; +signal spi_cs : std_logic_vector(4 downto 0); +signal spi_length : std_logic_vector(11 downto 0); +signal conf2 : std_logic_vector(31 downto 0); +signal spi_halfper : std_logic_vector(15 downto 0); +signal spi_waittime : std_logic_vector(15 downto 0); +signal spi_shout : std_logic_vector(31 downto 0); + +-- Fsm + Type t_state is ( + s_IDLE, + s_WAIT_SPI_FREE, + s_WR_CONF1, + s_WR_CONF2, + s_WR_SHOUT, + s_WAIT_SPI_FREE_2, + s_RD_SHIN + ); + attribute SYN_ENCODING : STRING; + attribute SYN_ENCODING of t_state : type is "one-hot, safe"; + signal curr_state: t_state; + +begin + + +--============================================================================= +-- FSM +--============================================================================= + --state flow process (synchronous) + p_protocol_fsm_flow: process (rst_ir, clk_ik) + begin + if rst_ir = '1' then + curr_state <= s_IDLE; + + wait_valid <= '0'; + + --CMB input + cmb_in_rd_data <= (others=>'0'); + cmb_in_rd_valid <= '0'; + cmb_in_busy <= '0'; + cmb_in_wr <= '0'; + cmb_in_wr_data <= (others=>'0'); + cmb_in_addr <= (others=>'0'); + + --CMB output + cmb_out_frame <= '0'; + cmb_out_addr <= (others=>'0'); + cmb_out_enable <= (others=>'1'); + cmb_out_wr <= '0'; + cmb_out_wr_data <= (others=>'0'); + cmb_out_rd <= '0'; + + elsif rising_edge(clk_ik) then + if cen_ie = '1' then + + --CMB input + cmb_in_rd_data <= (others=>'0'); + cmb_in_rd_valid <= '0'; + + --CMB output + cmb_out_frame <= '0'; + cmb_out_addr <= (others=>'0'); + cmb_out_enable <= (others=>'1'); + cmb_out_wr <= '0'; + cmb_out_wr_data <= (others=>'0'); + cmb_out_rd <= '0'; + + case curr_state is + + --============================= + when s_IDLE => + --============================= + if cmb_in_busy='0' then + if cmb_in_wr_i='1' or cmb_in_rd_i='1' then + curr_state <= s_WAIT_SPI_FREE; + --latch address and data + cmb_in_wr <= cmb_in_wr_i; + cmb_in_wr_data <= cmb_in_wr_data_ib; + cmb_in_addr <= cmb_in_addr_ib; + cmb_in_busy <= '1'; + end if; + end if; + + --============================= + when s_WAIT_SPI_FREE => + --============================= + if cmb_out_busy_i = '0' and wait_valid = '0' then + if cmb_out_wr='0' and cmb_out_rd='0' then + --read status: @xC0 SPI free data(17..16)='00' + cmb_out_addr <= x"00000000"; --STATUS REG + cmb_out_wr <= '0'; + cmb_out_wr_data <= x"00000000"; + cmb_out_rd <= '1'; + elsif cmb_out_rd = '1' then + wait_valid <='1'; + cmb_out_addr <= (others=>'0'); + cmb_out_wr <= '0'; + cmb_out_wr_data <= (others=>'0'); + cmb_out_rd <= '0'; + end if; + end if; + + if cmb_out_rd_valid_i = '1' then + wait_valid <='0'; + if cmb_out_rd_data_ib(17 downto 16)="00" then --SPI bus is not busy + curr_state <= s_WR_CONF1; + end if; + end if; + + + --============================= + when s_WR_CONF1 => + --============================= + if cmb_out_busy_i = '0' then + if cmb_out_wr='0' and cmb_out_rd='0' then + cmb_out_addr <= x"00000001"; --CONF1 REG + cmb_out_wr <= '1'; + cmb_out_wr_data <= conf1; + cmb_out_rd <= '0'; + elsif cmb_out_wr = '1' then + cmb_out_addr <= (others=>'0'); + cmb_out_wr <= '0'; + cmb_out_wr_data <= (others=>'0'); + cmb_out_rd <= '0'; + curr_state <= s_WR_CONF2; + end if; + end if; + + --============================= + when s_WR_CONF2 => + --============================= + if cmb_out_busy_i = '0' then + if cmb_out_wr='0' and cmb_out_rd='0' then + cmb_out_addr <= x"00000002"; --CONF2 REG + cmb_out_wr <= '1'; + cmb_out_wr_data <= conf2; + cmb_out_rd <= '0'; + elsif cmb_out_wr = '1' then + cmb_out_addr <= (others=>'0'); + cmb_out_wr <= '0'; + cmb_out_wr_data <= (others=>'0'); + cmb_out_rd <= '0'; + curr_state <= s_WR_SHOUT; + end if; + end if; + + --============================= + when s_WR_SHOUT => + --============================= + if cmb_out_busy_i = '0' then + if cmb_out_wr='0' and cmb_out_rd='0' then + cmb_out_addr <= x"00000003"; --SHIFT OUT REG + cmb_out_wr <= '1'; + cmb_out_wr_data <= spi_shout; + cmb_out_rd <= '0'; + elsif cmb_out_wr = '1' then + cmb_out_addr <= (others=>'0'); + cmb_out_wr <= '0'; + cmb_out_wr_data <= (others=>'0'); + cmb_out_rd <= '0'; + curr_state <= s_WAIT_SPI_FREE_2; --read access + end if; + end if; + + --============================= + when s_WAIT_SPI_FREE_2 => + --============================= + if cmb_out_busy_i = '0' and wait_valid = '0' then + if cmb_out_wr='0' and cmb_out_rd='0' then + --read status: @xC0 SPI free data(17..16)='00' + cmb_out_addr <= x"00000000"; --STATUS REG + cmb_out_wr <= '0'; + cmb_out_wr_data <= x"00000000"; + cmb_out_rd <= '1'; + elsif cmb_out_rd = '1' then + wait_valid <='1'; + cmb_out_addr <= (others=>'0'); + cmb_out_wr <= '0'; + cmb_out_wr_data <= (others=>'0'); + cmb_out_rd <= '0'; + end if; + end if; + + if cmb_out_rd_valid_i = '1' then + wait_valid <='0'; + if cmb_out_rd_data_ib(17 downto 16)="00" then --SPI bus is not busy + if cmb_in_wr='1' then + curr_state <= s_IDLE; --end of write access + cmb_in_busy <= '0'; + else + curr_state <= s_RD_SHIN; --read access + end if; + end if; + end if; + + + --============================= + when s_RD_SHIN => + --============================= + if cmb_out_busy_i='0' and wait_valid ='0' then + if cmb_out_wr='0' and cmb_out_rd='0' then + cmb_out_addr <= x"00000004"; --SHIFT IN REG + cmb_out_wr <= '0'; + cmb_out_wr_data <= x"00000000"; + cmb_out_rd <= '1'; + elsif cmb_out_rd='1' then + wait_valid <='1'; + cmb_out_addr <= (others=>'0'); + cmb_out_wr <= '0'; + cmb_out_wr_data <= (others=>'0'); + cmb_out_rd <= '0'; + end if; + end if; + + if cmb_out_rd_valid_i='1' then + curr_state <= s_IDLE; + cmb_in_busy <= '0'; + cmb_in_rd_data <= cmb_out_rd_data_ib; --12 lsb useful only + cmb_in_rd_valid <= '1'; + wait_valid <= '0'; + end if; + + --============================= + when others => + --============================= + curr_state <= s_IDLE; + + end case; + end if; + end if; + end process; + +--------------------------------------- +--SPI parameters +--------------------------------------- +--@xC4 (CPol_1b, CPha_1b, LSB1st_1b, 8b=00000000, CS_5b, 4b=0000, len_12b) +conf1 <= spi_pol & spi_pha & spi_lsb1st & x"00" & spi_cs & x"0" & spi_length; +spi_pol <= '1'; +spi_pha <= '0'; +spi_lsb1st <= '0'; +spi_cs <= "00000" when cmb_in_addr(3 downto 0)=x"0" --DAC25 (IC29 OSC1 125MHz) + else "00001" ;-- cmb_in_addr(3 downto 0)=x"1" --DAC20 (IC30 OSC2 20MHz) +spi_length <= x"018" when cmb_in_addr(3 downto 0)=x"0"; --24bits +--@xC8 (HalfPeriod_16b, WaitTime_16b) +conf2 <= spi_halfper & spi_waittime; +spi_halfper <= std_logic_vector(to_unsigned(c_DAC_HALFPER,16));-- when cmb_in_addr(3 downto 0)=x"0"; --DAC (30MHz max) +spi_waittime <= x"0002" ; --2 cycles +--@xCC (Value_24b= x"00" & dac_data_16b) +spi_shout <= x"00" & cmb_in_wr_data(15 downto 0) & x"00"; --unsused 8 LSB + + +--------------------------------------- +--output assignment +--------------------------------------- +--in +cmb_in_rd_data_ob <= cmb_in_rd_data ; +cmb_in_rd_valid_o <= cmb_in_rd_valid; +cmb_in_busy_o <= cmb_in_busy ; +--out +cmb_out_frame_o <= cmb_out_frame ; +cmb_out_addr_ob <= cmb_out_addr ; +cmb_out_enable_ob <= cmb_out_enable ; +cmb_out_wr_o <= cmb_out_wr ; +cmb_out_wr_data_ob <= cmb_out_wr_data; +cmb_out_rd_o <= cmb_out_rd ; + + +end architecture; diff --git a/cores_for_synthesis/vme_reset_sync_and_filter.vhd b/cores_for_synthesis/vme_reset_sync_and_filter.vhd new file mode 100644 index 0000000000000000000000000000000000000000..eb539236dd7244da948daed99ceba40206842d00 --- /dev/null +++ b/cores_for_synthesis/vme_reset_sync_and_filter.vhd @@ -0,0 +1,182 @@ +--============================================================================================ +--################################## Module Information ################################## +--============================================================================================ +-- +-- Company: CERN (BE-BI-BL) +-- +-- Language: VHDL 2008 +-- +-- Description: +-- +-- +-- The input reset is resynchronized in the input clock domain. +-- It is then resynchronized twice in the output clock domain. +-- +-- Asynchronous | Output clock domain +-- | +-- | +-- | +-- | ___ ___ +-- | | R | Q | R | +-- reset IN -------------------------|___|-----|___|---- reset OUT +-- | | | +-- | clock OUT -------------- +-- | cen OUT +-- +-- +-- ________ +-- reset IN \___________________________ +-- ___ ___ ___ ___ +-- clock IN __| |___| |___| |___| |____ +-- _________ +-- signal Q \\\\____________________ +-- __________________________ +-- reset OUT \________ +-- +-- +-- Glitch filter consisting of a set of chained flip-flops followed by a comparator. +-- The comparator toggles to '1' when all FFs in the chain are '1' and respectively to '0' +-- when all the FFS in the chain are '0'. +-- A latency of filter_length+1 is added on the output +-- +-- with a filter_length=2 : +-- ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ +-- clock IN __| |___| |___| |___| |___| |___| |___| |___| |___| |___| |___| |___| |___ +-- _______________ _______________________ _______ +-- data IN ___| |_______| |_______| |________________________________ +-- +-- 1 Filtered 1 NOT filtered 0 filtered 1 filtered 0 NOT filtered +-- _______________________________________ +-- data OUT ___________________________________________________| |_______ +-- +--============================================================================================ +--############################################################################################ +--============================================================================================ + + +---------------------------------------------------------------------------------------------------- +-- Libraries +---------------------------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +---------------------------------------------------------------------------------------------------- +-- Entity +---------------------------------------------------------------------------------------------------- +entity vme_reset_sync_and_filter is + port( + rst_ir : in std_logic; -- reset input + clk_ik : in std_logic; -- clock input + cen_ie : in std_logic; -- clock enable input + -- Data input + data_i : in std_logic; -- Data input + -- Data output + data_o : out std_logic -- Data output + ); +end entity; + + + + + +---------------------------------------------------------------------------------------------------- +-- Architecture +---------------------------------------------------------------------------------------------------- +architecture rtl of vme_reset_sync_and_filter is + + --Function definitions + function and_reduced(vector : std_logic_vector) return std_logic is + variable o : std_logic; + begin + o := '1'; + for k in vector'range loop + o := o and vector(k); + end loop; + return o; + end function and_reduced; + + function or_reduced(vector : std_logic_vector) return std_logic is + variable o : std_logic; + begin + o := '0'; + for k in vector'range loop + o := o or vector(k); + end loop; + return o; + end function or_reduced; + + -- Synthesis Attributes + attribute syn_preserve : boolean; -- Do not remove those signals and registers + attribute syn_replicate : boolean; -- Do not replicate those register + attribute syn_allow_retiming : boolean; -- Do not optimize timing by changing registers + + -- Resynchronization + constant c_NB_RESYNC_FF_MSR : natural := 2; -- Number of resynchronization flip-flops + signal reset_msr : std_logic_vector(c_NB_RESYNC_FF_MSR-1 downto 0) := (others=>'0'); -- Metastability registers + attribute syn_preserve of reset_msr : signal is true; + attribute syn_replicate of reset_msr : signal is false; + attribute syn_allow_retiming of reset_msr : signal is false; + + -- Glitch filter + constant g_FILTER_LENGTH : positive := 4; + signal glitch_filter_pipe : std_logic_vector(g_FILTER_LENGTH downto 0) := (others=>'0'); --default value for simu + signal data_int : std_logic := '0'; --default value for simu + +begin + + -------------------------------------------------------------------------------------------------- + -- 2 stages of resynchronization in the output clock domain + -------------------------------------------------------------------------------------------------- + + p_resync_on_out_clock : process(clk_ik) + begin + if rising_edge(clk_ik) then + if ( cen_ie = '1' ) then + reset_msr <= reset_msr(reset_msr'left-1 downto 0) & data_i; --synchronous deassertion + end if; + end if; + end process; + + -------------------------------------------------------------------------------------------------- + -- Glitch filter + -------------------------------------------------------------------------------------------------- + + -- Glitch filtering logic + glitch_filter_pipe(0) <= reset_msr(reset_msr'left); + + -- Generate glitch filter FFs + p_filter_pipe: process (rst_ir, clk_ik) + begin + if (rst_ir = '1') then + glitch_filter_pipe(g_FILTER_LENGTH downto 1) <= (others=>'0'); + elsif rising_edge(clk_ik) then + if (cen_ie = '1') then + glitch_filter_pipe(g_FILTER_LENGTH downto 1) <= glitch_filter_pipe(g_FILTER_LENGTH-1 downto 0); --shift register + end if; + -- end if; + end if; + end process; + + -- Set the data output based on the state of the glitch filter + p_output: process(rst_ir, clk_ik) + begin + if (rst_ir = '1') then + data_int <= '0'; + elsif rising_edge(clk_ik) then + if (cen_ie = '1') then + if (and_reduced(glitch_filter_pipe) = '1') then + data_int <= '1'; + elsif (or_reduced(glitch_filter_pipe) = '0') then + data_int <= '0'; + else + data_int <= data_int; + end if; + end if; + end if; + end process; + + --output assignment + data_o <= data_int; + +end architecture;