diff --git a/cores_for_synthesis/BootRomWbMaster.sv b/cores_for_synthesis/BootRomWbMaster.sv new file mode 100644 index 0000000000000000000000000000000000000000..3b9fb267333d7537507addaf7f6e0bfd56144c86 --- /dev/null +++ b/cores_for_synthesis/BootRomWbMaster.sv @@ -0,0 +1,307 @@ +/* + +WB initial configuration master. The module acts as Wishbone master after reset. It plays +commands pre-programmed into a ROM after the release of reset signal. After the reset, +the sequence pre-programmed into a ROM is executed. + +The maximum time for which the BOOT ROM master waits for slave ack is configurable via p_MaxAckWaitTimeMicrosec +and can be significantly larger than the one on the VME bus. This allows to wait for chip resets, etc. +There is h1000 clocks delay between commands, also before the first command. + +The maximum time for which the BOOT ROM can request the bus is configured via p_MaxBootTimeMilisec. + +Default p_MaxBootTimeMilisec is 3s, given in milisecond +Default p_MaxAckWaitTimeMicrosec is 10ms, given in microseconds + +The ROM data is composed as follows: +[2'h flag, 8'h not used, 22'h Wishbone address, 32'h0 Wishbone data] + +The flag is either: +2'h0 for commands to be passed to WB +2'h2 marking a pause. The 32 LSB in the line are used as the delay value in microseconds. +2'h3 marking end of configuration. This flag must be the last active line of MIF, other bits in the line +are neglected. + +For the currenct version of the VfcHD-System, set the MSB of the 22-bit Wb address to 1 to send commands to +application part; to 0 to send commands to system part. + +Relation between the Wishbone and VME address is defined by the VME module. Currently it is: Wishbone = VME >> 2. + +Last change: 17/01/2019 + +Author: Jiri Kral +jiri.kral@cern.ch + +MIF example: ----------------------------------------------------- +WIDTH=64; +DEPTH=256; + +ADDRESS_RADIX=HEX; +DATA_RADIX=HEX; + +CONTENT BEGIN + 00 : 0000000100000002; -- write 0x2 to address 0x1 of system part + 01 : 0000000200000007; -- write 0x7 to address 0x2 of system part + 02 : 0020000500000003; -- write 0x3 to address 0x5 of application part + 03 : 0020000600000010; -- write 0x10 to address 0x6 of application part + 04 : 80000000000003E8; -- delay 1000 us + 05 : 002000070000001A; -- write 0x1A to address 0x7 of application part + 06 : 002000080000001B; -- write 0x1B to address 0x8 of application part + 07 : 002000090000001C; -- write 0x1C to address 0x9 of application part + 08 : 0020000A0000001D; -- write 0x1D to address 0xA of application part + 09 : 0020000B0000001E; -- write 0x1E to address 0xB of application part + 0A : C000000000000000; -- end flag + [0B..FF] : C000000000000000; +END; +end of MIF example ----------------------------------------------- + +*/ + +`timescale 1ns/100ps + +module BootRomWbMaster #( + parameter g_ClkFrequency, + parameter g_InitFile, + parameter p_MaxBootTimeMicrosec = 3000000, // 3s + parameter p_MaxAckWaitTimeMicrosec = 10000 ) // 10ms +( + // Clock, reset + input Clk_ik, + input Rst_irq, + + output reg SelBoot_oq, // bus takeover flag + // Wishbone interface + output reg Cyc_oq, + output reg Stb_oq, + output reg We_oq, + output reg [21:0] Adr_oqb22, + output reg [31:0] Dat_oqb32, + input Ack_i +); + +localparam int p_MicrosecCnt = ( g_ClkFrequency / 1e6 ) - 1; + +// neg reset +wire rst_rn; + +// rom signals +reg [7:0] RomAddress_qb8; +wire [63:0] RomData_b64; + +// state machine +reg [1:0] ConfigState = 2'h0; +reg [31:0] Counter_qb32; +reg MemOverrun_q; + +localparam s_wait = 2'h0; +localparam s_write = 2'h1; +localparam s_waitack = 2'h2; +localparam s_done = 2'h3; + +// Total boot timeout +reg [$clog2( p_MaxBootTimeMicrosec + 1 ) - 1:0] BootTimeoutCounter_c; +// Ack timeout +reg [$clog2( p_MaxAckWaitTimeMicrosec + 1 ) - 1:0] TimeoutCounter_c; +// Boot master select +reg SelBoot_q; + +// Microsecond counter and flag +reg [$clog2( p_MicrosecCnt + 1 ) - 1:0] MicrosecCounter_c; +reg MicrosecFlag_q; + +// initial reset +assign rst_rn = ~Rst_irq; + +// config ROM +altsyncram #( + .address_aclr_a("NONE"), + .clock_enable_input_a("BYPASS"), + .clock_enable_output_a("BYPASS"), + .init_file(g_InitFile), + .intended_device_family("Arria V"), + .lpm_hint("ENABLE_RUNTIME_MOD=NO"), + .lpm_type("altsyncram"), + .numwords_a(256), + .operation_mode("ROM"), + .outdata_aclr_a("NONE"), + .outdata_reg_a("CLOCK0"), + .widthad_a(8), + .width_a(64), + .width_byteena_a(1)) +i_boot_rom ( + .address_a (RomAddress_qb8), + .clock0 (Clk_ik), + .q_a (RomData_b64), + .aclr0 (1'b0), + .aclr1 (1'b0), + .address_b (1'b1), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_a (1'b1), + .byteena_b (1'b1), + .clock1 (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .data_a ({64{1'b1}}), + .data_b (1'b1), + .eccstatus (), + .q_b (), + .rden_a (1'b1), + .rden_b (1'b1), + .wren_a (1'b0), + .wren_b (1'b0)); + +// microsecond flag generator +// generates 1 clock lasting flag every microsecond +always @(posedge Clk_ik or negedge rst_rn ) +begin + if( rst_rn == 1'b0 ) + begin + MicrosecFlag_q <= 1'b0; + MicrosecCounter_c <= 0; + end + else begin + // generate microsecond flag + if( MicrosecCounter_c == p_MicrosecCnt ) + begin + MicrosecCounter_c <= 0; + MicrosecFlag_q <= 1'b1; + end + else begin + MicrosecCounter_c <= MicrosecCounter_c + 1'b1; + MicrosecFlag_q <= 1'b0; + end + end +end + +// total boot time guard +always @(posedge Clk_ik or negedge rst_rn ) +begin + if( rst_rn == 1'b0 ) + begin + SelBoot_oq <= 1'b0; + BootTimeoutCounter_c <= 0; + end + else begin + // do not request to be master after total timeout + if( BootTimeoutCounter_c == p_MaxBootTimeMicrosec ) + SelBoot_oq <= 1'b0; + else begin + // timeout counter + if( MicrosecFlag_q == 1'b1 ) + BootTimeoutCounter_c <= BootTimeoutCounter_c + 1'b1; + // forward master request + SelBoot_oq <= SelBoot_q; + end + end +end + + +// initial config state machine +always @(posedge Clk_ik or negedge rst_rn ) +begin + + if( rst_rn == 1'b0 ) + begin + RomAddress_qb8 <= 8'h0; + Cyc_oq <= 1'b0; + Stb_oq <= 1'b0; + We_oq <= 1'b0; + Adr_oqb22 <= 22'h0; + Dat_oqb32 <= 32'h0; + ConfigState <= s_wait; + Counter_qb32 <= 32'h20; // give 20us initial wait + SelBoot_q <= 1'b0; + TimeoutCounter_c <= 0; + MemOverrun_q <= 1'b0; + end + else begin + + case( ConfigState ) + // wait, release last commands + s_wait: + begin + Cyc_oq <= 1'b0; + Stb_oq <= 1'b0; + We_oq <= 1'b0; + SelBoot_q <= 1'b1; + TimeoutCounter_c <= 0; + + // protection against running the memory content multiple times + if( MemOverrun_q == 1'b1 ) + ConfigState <= s_done; + // some slaves may keep the ack up for quite long + // wait until it goes down before proceeding + else if( Ack_i == 1'b0 ) + begin + // wait specified time + // decrement counter on every microsecond + if( MicrosecFlag_q == 1'b1 ) + Counter_qb32 <= Counter_qb32 - 32'h1; + + // done waiting + if( Counter_qb32 == 32'h0 ) + ConfigState <= s_write; + end + end + + // one WB write command + s_write: + begin + // increment ROM address + RomAddress_qb8 <= RomAddress_qb8 + 8'h1; + + // reached end of ROM + if( RomAddress_qb8 == 8'hFF ) + MemOverrun_q <= 1'b1; + + // check if end of init mark + // go to done if yes + if( RomData_b64[63:62] == 2'b11 ) + ConfigState <= s_done; + // Pause command + else if ( RomData_b64[63:62] == 2'b10 ) + begin + Counter_qb32 <= RomData_b64[31:0]; + ConfigState <= s_wait; + end + // write command otherwise + else begin + Cyc_oq <= 1'b1; + Stb_oq <= 1'b1; + We_oq <= 1'b1; + Adr_oqb22 <= RomData_b64[53:32]; + Dat_oqb32 <= RomData_b64[31:0]; + ConfigState <= s_waitack; + end + end + + // wait for slave ack + s_waitack: + begin + // prepare 20us delay before next write + Counter_qb32 <= 32'h20; + if( MicrosecFlag_q == 1'b1 ) + TimeoutCounter_c <= TimeoutCounter_c + 1'b1; + + // wait for slave ack or timeout (prevention of wrong addresses or dead slaves) + if( Ack_i == 1'b1 || TimeoutCounter_c == p_MaxAckWaitTimeMicrosec ) + ConfigState <= s_wait; + else + ConfigState <= s_waitack; + end + + // done state, stay here` + s_done: + begin + ConfigState <= s_done; + SelBoot_q <= 1'b0; + end + + endcase + end +end + +endmodule diff --git a/cores_for_synthesis/DS18B20Emu.sv b/cores_for_synthesis/DS18B20Emu.sv new file mode 100644 index 0000000000000000000000000000000000000000..1233c1ba9c8d2cac6fda30578dae52ad6a310e79 --- /dev/null +++ b/cores_for_synthesis/DS18B20Emu.sv @@ -0,0 +1,427 @@ +//---------------------------------------------------------------------- +// Title : DS18B20 Emulator +// Project : VFC-HD_System (https://gitlab.cern.ch/bi/VFC/VFC-HD_System) +//---------------------------------------------------------------------- +// File : DS18B20Emu.sv +// Author : T. Levens +// Company : CERN BE-BI +//---------------------------------------------------------------------- +// Description: +// +// Implements an emulated Maxim DS18B20 OneWire serial number and +// temperature sensor. +//---------------------------------------------------------------------- + +`timescale 1ns/100ps + +module DS18B20Emu #(parameter g_ClkFrequency) ( + input Clk_ik, + input Rst_irq, + + input [63:0] UniqueId_ib64, + input [15:0] Temp_ib16, + + input OneWireBus_i, + output OneWireBus_oe +); + +//---------------------------------------------------------------------- +// Constants +//---------------------------------------------------------------------- + +// Timing +localparam int c_DlyCntBits = $clog2(int'((400 * g_ClkFrequency) / 1e6) + 1); +localparam c_Trstl = (c_DlyCntBits)'(int'((400 * g_ClkFrequency) / 1e6)); +localparam c_Tpdh = (c_DlyCntBits)'(int'(( 50 * g_ClkFrequency) / 1e6)); +localparam c_Tpdl = (c_DlyCntBits)'(int'((200 * g_ClkFrequency) / 1e6)); +localparam c_Tsamp = (c_DlyCntBits)'(int'(( 30 * g_ClkFrequency) / 1e6)); +localparam c_Trel = (c_DlyCntBits)'(int'(( 30 * g_ClkFrequency) / 1e6)); + +// ROM commands +localparam c_ReadRom = 8'h33; +localparam c_MatchRom = 8'h55; +localparam c_SearchRom = 8'hF0; +localparam c_AlarmSearch = 8'hEC; +localparam c_SkipRom = 8'hCC; + +// Function commands +localparam c_ConvTemp = 8'h44; +localparam c_ReadSP = 8'hBE; +localparam c_WriteSP = 8'h4E; +localparam c_CopySP = 8'h48; +localparam c_RecallE2 = 8'hB8; +localparam c_ReadPS = 8'hB4; + +//---------------------------------------------------------------------- +// Commands +//---------------------------------------------------------------------- + +// Synchronisation of bus input +reg [2:0] OneWireBus_xb2; +always @(posedge Clk_ik) OneWireBus_xb2 <= #1 {OneWireBus_xb2[1:0], OneWireBus_i}; +wire OneWireBus_q = OneWireBus_xb2[1]; + +// Bus edge detection +wire BusPosEdge_p = OneWireBus_xb2[1] && !OneWireBus_xb2[2]; +wire BusNegEdge_p = !OneWireBus_xb2[1] && OneWireBus_xb2[2]; + +// Bus reset detection (bus low for >=480us) +reg [c_DlyCntBits-1:0] RstCounter_c; +reg BusRst_p; + +always @(posedge Clk_ik) begin + BusRst_p <= #1 1'b0; + if (BusNegEdge_p) begin + RstCounter_c <= #1 'b1; + end else if (BusPosEdge_p) begin + RstCounter_c <= #1 'b0; + end else if (RstCounter_c == c_Trstl) begin + BusRst_p <= #1 1'b1; + RstCounter_c <= #1 'b0; + end else if (RstCounter_c) begin + RstCounter_c <= #1 RstCounter_c + 1'b1; + end +end + +//---------------------------------------------------------------------- +// State machine +//---------------------------------------------------------------------- + +// State encoding +enum { + s_Idle, + s_Reset, + s_WaiPrsnt, + s_Prsnt, + s_PreRomCmd, + s_WaiRomCmd, + s_RomCmd, + s_DecRomCmd, + s_WaiTxRomBit, + s_TxRomBit, + s_WaiTxNRomBit, + s_TxNRomBit, + s_WaiRxRomBit, + s_RxRomBit, + s_PreFncCmd, + s_WaiFncCmd, + s_FncCmd, + s_DecFncCmd, + s_WaiTxFncBit, + s_TxFncBit, + s_WaiRxSPBit, + s_RxSPBit +} State_l; + +reg [c_DlyCntBits-1:0] DlyCnt_c; +reg [ 7:0] BitCnt_c8; +reg [ 7:0] Command_b8; +reg [63:0] SR_b64; +reg [23:0] E2_b24; +reg [ 7:0] CRC_b8; +reg BusOut, SearchRom, SendCRC; + +always @(posedge Clk_ik) begin + if (Rst_irq) begin + State_l <= #1 s_Idle; + BusOut <= #1 1'b1; + DlyCnt_c <= #1 'h0; + BitCnt_c8 <= #1 8'h0; + Command_b8 <= #1 8'h0; + SR_b64 <= #1 64'h0; + SearchRom <= #1 1'b0; + SendCRC <= #1 1'b0; + E2_b24 <= #1 24'h7F7F80; + CRC_b8 <= #1 8'h0; + end else if (BusRst_p) begin + State_l <= #1 s_Reset; + BusOut <= #1 1'b1; + end else begin + case (State_l) + //---------------------------------------------------------- + // Bus reset & present generation + //---------------------------------------------------------- + s_Reset: begin + if (BusPosEdge_p) begin + State_l <= #1 s_WaiPrsnt; + DlyCnt_c <= #1 c_Tpdh; + end + end + s_WaiPrsnt: begin + if (!DlyCnt_c) begin + State_l <= #1 s_Prsnt; + DlyCnt_c <= #1 c_Tpdl; + BusOut <= #1 1'b0; + end else begin + DlyCnt_c <= #1 DlyCnt_c - 1'b1; + end + end + s_Prsnt: begin + if (!DlyCnt_c) begin + BusOut <= #1 1'b1; + State_l <= #1 s_PreRomCmd; + end else begin + DlyCnt_c <= #1 DlyCnt_c - 1'b1; + end + end + //---------------------------------------------------------- + // Read ROM command + //---------------------------------------------------------- + s_PreRomCmd: begin + State_l <= #1 s_WaiRomCmd; + BitCnt_c8 <= #1 8'h7; + Command_b8 <= #1 8'h0; + end + s_WaiRomCmd: begin + if (BusNegEdge_p) begin + State_l <= #1 s_RomCmd; + DlyCnt_c <= #1 c_Tsamp; + end + end + s_RomCmd: begin + if (!DlyCnt_c) begin + Command_b8 <= #1 {OneWireBus_q, Command_b8[7:1]}; + if (!BitCnt_c8) begin + State_l <= #1 s_DecRomCmd; + end else begin + State_l <= #1 s_WaiRomCmd; + BitCnt_c8 <= #1 BitCnt_c8 - 8'h1; + end + end else begin + DlyCnt_c <= #1 DlyCnt_c - 1'b1; + end + end + s_DecRomCmd: begin + case (Command_b8) + c_ReadRom: begin + State_l <= #1 s_WaiTxRomBit; + SearchRom <= #1 1'b0; + BitCnt_c8 <= #1 8'd63; + SR_b64 <= #1 UniqueId_ib64; + end + c_MatchRom: begin + State_l <= #1 s_WaiRxRomBit; + SearchRom <= #1 1'b0; + BitCnt_c8 <= #1 8'd63; + SR_b64 <= #1 UniqueId_ib64; + end + c_SearchRom, c_AlarmSearch: begin + State_l <= #1 s_WaiTxRomBit; + SearchRom <= #1 1'b1; + BitCnt_c8 <= #1 8'd63; + SR_b64 <= #1 UniqueId_ib64; + end + c_SkipRom: begin + State_l <= #1 s_PreFncCmd; + end + default: begin + State_l <= #1 s_Idle; + end + endcase + end + //---------------------------------------------------------- + // Excecute ROM command + //---------------------------------------------------------- + // + // Depending on the command, the following sequence is + // followed: + // + // SearchRom: 64x[TX, TXN, RX] + // ReadRom: 64x[TX] + // MatchRom: 64x[RX] + // + // TX: + s_WaiTxRomBit: begin + if (BusNegEdge_p) begin + State_l <= #1 s_TxRomBit; + DlyCnt_c <= #1 c_Trel; + BusOut <= #1 SR_b64[0]; + end + end + s_TxRomBit: begin + if (!DlyCnt_c) begin + BusOut <= #1 1'b1; + if (SearchRom) begin + State_l <= #1 s_WaiTxNRomBit; + end else if (!BitCnt_c8) begin + State_l <= #1 s_PreFncCmd; + end else begin + State_l <= #1 s_WaiTxRomBit; + SR_b64 <= #1 {1'b0, SR_b64[63:1]}; + BitCnt_c8 <= #1 BitCnt_c8 - 1'b1; + end + end else begin + DlyCnt_c <= #1 DlyCnt_c - 1'b1; + end + end + // TXN: + s_WaiTxNRomBit: begin + if (BusNegEdge_p) begin + State_l <= #1 s_TxNRomBit; + DlyCnt_c <= #1 c_Trel; + BusOut <= #1 !SR_b64[0]; + end + end + s_TxNRomBit: begin + if (!DlyCnt_c) begin + BusOut <= #1 1'b1; + State_l <= #1 s_WaiRxRomBit; + end else begin + DlyCnt_c <= #1 DlyCnt_c - 1'b1; + end + end + // RX: + s_WaiRxRomBit: begin + if (BusNegEdge_p) begin + State_l <= #1 s_RxRomBit; + DlyCnt_c <= #1 c_Tsamp; + end + end + s_RxRomBit: begin + if (!DlyCnt_c) begin + if (SR_b64[0] != OneWireBus_q) begin + State_l <= #1 s_Idle; + BitCnt_c8 <= #1 8'd0; + end else begin + if (!BitCnt_c8) begin + State_l <= #1 (SearchRom) ? s_Idle : s_PreFncCmd; + end else begin + State_l <= #1 (SearchRom) ? s_WaiTxRomBit : s_WaiRxRomBit; + SR_b64 <= #1 {1'b0, SR_b64[63:1]}; + BitCnt_c8 <= #1 BitCnt_c8 - 1'b1; + end + end + end else begin + DlyCnt_c <= #1 DlyCnt_c - 1'b1; + end + end + //---------------------------------------------------------- + // Read function command + //---------------------------------------------------------- + s_PreFncCmd: begin + State_l <= #1 s_WaiFncCmd; + BitCnt_c8 <= #1 8'h7; + Command_b8 <= #1 8'h0; + BusOut <= #1 1'b1; + SearchRom <= #1 1'b0; + end + s_WaiFncCmd: begin + if (BusNegEdge_p) begin + State_l <= #1 s_FncCmd; + DlyCnt_c <= #1 c_Tsamp; + end + end + s_FncCmd: begin + if (!DlyCnt_c) begin + Command_b8 <= #1 {OneWireBus_q, Command_b8[7:1]}; + if (!BitCnt_c8) begin + State_l <= #1 s_DecFncCmd; + end else begin + State_l <= #1 s_WaiFncCmd; + BitCnt_c8 <= #1 BitCnt_c8 - 8'h1; + end + end else begin + DlyCnt_c <= #1 DlyCnt_c - 1'b1; + end + end + s_DecFncCmd: begin + case (Command_b8) + c_ConvTemp, c_RecallE2: begin + State_l <= #1 s_WaiTxFncBit; + CRC_b8 <= #1 8'h0; + BitCnt_c8 <= #1 8'd3; + SR_b64 <= #1 63'b1000; + SendCRC <= #1 1'b0; + end + c_ReadPS: begin + State_l <= #1 s_WaiTxFncBit; + CRC_b8 <= #1 8'h0; + BitCnt_c8 <= #1 8'd0; + SR_b64 <= #1 63'b1; + SendCRC <= #1 1'b0; + end + c_CopySP: begin + State_l <= #1 s_Idle; + end + c_ReadSP: begin + State_l <= #1 s_WaiTxFncBit; + CRC_b8 <= #1 8'h0; + BitCnt_c8 <= #1 8'd63; + SR_b64 <= #1 {8'h10, 8'h00, 8'hFF, E2_b24, Temp_ib16}; + SendCRC <= #1 1'b1; + end + c_WriteSP: begin + State_l <= #1 s_WaiRxSPBit; + BitCnt_c8 <= #1 8'd23; + end + default: begin + State_l <= #1 s_Idle; + end + endcase + end + //---------------------------------------------------------- + // Excecute function command + //---------------------------------------------------------- + s_WaiTxFncBit: begin + if (BusNegEdge_p) begin + State_l <= #1 s_TxFncBit; + DlyCnt_c <= #1 c_Trel; + BusOut <= #1 SR_b64[0]; + CRC_b8[7] <= #1 SR_b64[0] ^ CRC_b8[0]; + CRC_b8[6:4] <= #1 CRC_b8[7:5]; + CRC_b8[3] <= #1 SR_b64[0] ^ CRC_b8[0] ^ CRC_b8[4]; + CRC_b8[2] <= #1 SR_b64[0] ^ CRC_b8[0] ^ CRC_b8[3]; + CRC_b8[1:0] <= #1 CRC_b8[2:1]; + end + end + s_TxFncBit: begin + if (!DlyCnt_c) begin + BusOut <= #1 1'b1; + if (!BitCnt_c8) begin + if (SendCRC) begin + State_l <= #1 s_WaiTxFncBit; + BitCnt_c8 <= #1 8'd7; + SR_b64 <= #1 {56'h0, CRC_b8}; + SendCRC <= #1 1'b0; + end else begin + State_l <= #1 s_Idle; + end + end else begin + State_l <= #1 s_WaiTxFncBit; + SR_b64 <= #1 {1'b0, SR_b64[63:1]}; + BitCnt_c8 <= #1 BitCnt_c8 - 1'b1; + end + end else begin + DlyCnt_c <= #1 DlyCnt_c - 1'b1; + end + end + s_WaiRxSPBit: begin + if (BusNegEdge_p) begin + State_l <= #1 s_RxSPBit; + DlyCnt_c <= #1 c_Tsamp; + end + end + s_RxSPBit: begin + if (!DlyCnt_c) begin + E2_b24 <= #1 {OneWireBus_q, E2_b24[23:1]}; + if (!BitCnt_c8) begin + State_l <= #1 s_Idle; + end else begin + State_l <= #1 s_WaiRxSPBit; + BitCnt_c8 <= #1 BitCnt_c8 - 1'b1; + end + end else begin + DlyCnt_c <= #1 DlyCnt_c - 1'b1; + end + end + //---------------------------------------------------------- + default: begin + // Do nothing... + end + endcase + end +end + +assign OneWireBus_oe = !BusOut; + +endmodule diff --git a/cores_for_synthesis/SfpIdReader.sv b/cores_for_synthesis/SfpIdReader.sv new file mode 100644 index 0000000000000000000000000000000000000000..3970115bc53f9bc78254ad53aa1bc61427fd213e --- /dev/null +++ b/cores_for_synthesis/SfpIdReader.sv @@ -0,0 +1,85 @@ +//---------------------------------------------------------------------- +// Title : SFP ID Reader +// Project : VFC-HD_System (https://gitlab.cern.ch/bi/VFC/VFC-HD_System) +//---------------------------------------------------------------------- +// File : SfpIdReader.sv +// Author : A. Boccardi +// Company : CERN BE-BI +//---------------------------------------------------------------------- +// Description: +// +// Readback of the White Rabbit SFP ID. +//---------------------------------------------------------------------- + +`timescale 1ns/100ps + +module SfpIdReader #( + parameter g_SfpWbBaseAddress = 0, + g_WbAddrWidth = 32) +( + input Clk_ik, + input SfpPlugged_i, + output reg SfpIdValid_o, + output reg [127 : 0] SfpPN_ob128, + output reg WbCyc_o, + output reg WbStb_o, + output reg [g_WbAddrWidth-1 : 0] WbAddr_ob, + input [7 : 0] WbData_ib8, + input WbAck_i); + +localparam s_NoSfp = 0, + s_WbStart = 1, + s_WbClose = 2, + s_Done = 3; + +reg [1:0] State_q = s_NoSfp, + NextState_a; + +reg [3:0] ByteRead_c4; + +always @(posedge Clk_ik) State_q <= NextState_a; + +always @* + if (!SfpPlugged_i) NextState_a = s_NoSfp; + else begin + NextState_a = State_q; + case (State_q) + s_NoSfp: if (SfpPlugged_i) NextState_a = s_WbStart; + s_WbStart: if ( WbAck_i) NextState_a = s_WbClose; + s_WbClose: if (!WbAck_i) NextState_a = &ByteRead_c4 ? s_Done : s_WbStart; + s_Done: ; + default: NextState_a = s_NoSfp; + endcase + end + +always @(posedge Clk_ik) + case (State_q) + s_NoSfp: begin + SfpIdValid_o <= 1'b0; + ByteRead_c4 <= 4'd0; + WbCyc_o <= 1'b0; + WbStb_o <= 1'b0; + WbAddr_ob <= g_SfpWbBaseAddress + 40; + SfpPN_ob128 <= 128'd0; + end + s_WbStart: begin + WbCyc_o <= 1'b1; + WbStb_o <= 1'b1; + if (NextState_a==s_WbClose) SfpPN_ob128 <= {SfpPN_ob128[119:0], WbData_ib8}; + end + s_WbClose: begin + WbCyc_o <= 1'b1; + WbStb_o <= 1'b0; + if (NextState_a==s_WbStart) begin + WbAddr_ob <= WbAddr_ob + 1'b1; + ByteRead_c4 <= ByteRead_c4 + 1'b1; + end + end + s_Done: begin + SfpIdValid_o <= 1'b1; + WbCyc_o <= 1'b0; + WbStb_o <= 1'b0; + end + endcase + +endmodule