/*=================================================================*/ /*=== Digilent MEM1 Board LIBRARY ===============================*/ /*=================================================================*/ /* * FILE: MEM1.v * PROGRAMMER: William L. Bahn * * CONTENTS: */ //================================================================= //=== Digilent MEM1_C2 Board Interface =========================== //================================================================= /* The MEM1 C2 board has 1MB of SRAM organized into two banks sharing a common address, data, and control signals. MEM1 Pin Assignments -------------------------------------- Signal MEM1 D2 PORTA/E PORTC PORTD -------------------------------------- A[18] 5 35 22 136 82 A[17] 7 33 24 139 84 A[16] 8 34 23 138 86 A[15] 9 31 29 141 87 A[14] 10 32 27 140 88 A[13] 11 29 31 146 89 A[12] 12 30 30 142 90 A[11] 13 27 34 148 94 A[10] 14 28 33 147 95 A[09] 15 25 36 150 96 A[08] 16 26 35 149 97 A[07] 17 23 41 152 98 A[06] 18 24 37 151 99 A[05] 28 14 57 167 114 A[04] 30 12 59 172 119 A[03] 32 10 61 174 121 A[02] 34 8 63 176 123 A[01] 36 6 68 179 126 A[00] 38 4 70 181 127 -------------------------------------- D[07] 21 19 45 162 102 D[06] 23 17 47 164 109 D[05] 25 15 49 166 111 D[04] 27 13 58 168 113 D[03] 29 11 60 173 115 D[02] 31 9 62 175 120 D[01] 33 7 67 178 122 D[00] 35 5 69 180 125 -------------------------------------- CS[1] 20 22 42 154 101 CS[0] 22 20 44 161 108 OE 24 18 46 163 110 WE 26 16 48 165 112 -------------------------------------- Description: The MEM1_C2 module is the bare bones interface to the MEM1 memory board. To be compatible with byte-wide registers, the address in/out ports are 24 bits wide even though only 20 bits are used. The memory is partitioned into two banks. The MSB of the virtual address (A[19]) is used to choose which bank is selected. Write Procedure Verify that the Busy bit is clear in the Status Register. Place the address and data in the appropriate registers. Strobe the Write Start bit in the Control Register. Verify that the Write Complete bit asserts in the Status Register. Read Procedure Verify that the Busy bit is clear in the Status Register. Place the address and data in the appropriate registers. Strobe the Read Start bit in the Control Register. Verify that the Read Complete bit asserts in the Status Register. Read the address and data from the appropriate registers. It is the responsibility of the calling module to ensure that no transitions on the address/data lines are allowed before the operation is complete. Write Sequence The Address/Data/Start data can be applied to the module on the rising edge of the clock. The actual transfer will take place on the next falling edge. The Start Strobe can be removed on the next rising edge and must be removed prior to writing any more data (otherwise the write engine will never re-arm). | Generic Write Cycle | Minimum Time Write | _____ _____ _____ _____ _____ __ CLK __/ \_____/ \_____/ \_____/ \_____/ \_____/ ___ ___________________________________ _______________________ _ A ___X___________________________________X_______________________X_ ___ ___________________________________ _______________________ _ D ___X___________________________________X_______________________X_ _______________________ ____________ _ ST ___/ \___________/ \__________/ ___________ ____________ _ GO ___/ \_______________________/ \__________/ _________________________________________________________________ OEb _________ _______________________ _______ WEb \___________/ \___________/ _________________ _________________ BSY ___/ \_________________/ \_______ Read Sequence The Address/Data/Start data can be applied to the module on the rising edge of the clock. The actual transfer will take place on the next rising edge. The Start Strobe can be removed on the next rising edge. | Generic Read Cycle | Minimum Time Read | _____ _____ _____ _____ _____ __ CLK __/ \_____/ \_____/ \_____/ \_____/ \_____/ ___ ___________________________________ _______________________ _ A ___X___________________________________X_______________________X_ ___ ___________________________________ _______________________ _ D ___X___________________________________X_______________________X_ _______________________ ____________ _ ST ___/ \___________/ \__________/ ___________ ____________ _ GO ___/ \_______________________/ \__________/ _________ _______________________ _______ OEb \___________/ \___________/ _________________________________________________________________ REb _________________ _________________ BSY ___/ \_________________/ \_______ */ /* module MEM1_C2 ( Test, // Test output Control, Status, // Control and Status Registers WA, WD, // Input Address, Write Data RA, RD, // Output Address, Read Data A, D, OEb, WEb, CSb,// MEM1 Address, Data, OE, WE, CS rst, clk // Global reset and clock ); parameter HI = 1'b1, LO = 1'b0; output [7:0] Test; // Test output input [7:0] Control; // Control Register output [7:0] Status; // Status Register input [23:0] WA; // Write Address input [7:0] WD; // Write Data output [23:0] RA; // Read Address output [7:0] RD; // Read Data output [18:0] A; // MEM1 Address inout [7:0] D; // MEM1 Data (bi-directional) output OEb, WEb; // MEM1 Output Enable, Write Enable output [1:0] CSb; // MEM1 Chip Select input rst, clk; // Global reset and clock //----------------------------------------------------------------- // Internal Signals wire Start, Write, Read; // Control signals wire Busy, Capture; // Status signals // Internal to External Mapping assign Start = Control[0]; assign Write = Control[1]; assign Status[0] = Busy; assign Status[1] = Capture; // Address Parsing assign A = WA[18:0]; assign CSb[1] = ~WA[19]; assign CSb[0] = WA[19]; reg [7:0] RD_int; assign RD = RD_int; reg [23:0] RA_int; assign RA = RA_int; // FSM State Variables reg [1:0] State, Next_State; // FSM State Definitions parameter S_IDLE = 2'b00, S_WRITE = 2'b10, S_HOLD = 2'b11, S_READ = 2'b01; // FSM State Transition Process always @ (negedge clk) begin if (rst == HI) begin State <= S_IDLE; RA_int <= 20'd0; RD_int <= 8'd0; end else begin State <= Next_State; if (Capture == HI) begin RA_int <= {4'b0000,WA[19:0]}; RD_int <= D; end else begin RA_int <= RA_int; RD_int <= RD_int; end end end TriBuf8 ZBUF (.Q(D), .D(WD), .OE(~WEb)); reg WEb_int, OEb_int, Busy_int, Capture_int; assign WEb = WEb_int; assign OEb = OEb_int; assign Busy = Busy_int; assign Capture = Capture_int; // FSM State Transition Definitions always @ (State or Start or Write) begin case (State) S_IDLE: begin WEb_int = HI; OEb_int = HI; Busy_int = LO; Capture_int = LO; if (Start == HI) if (Write == HI) Next_State = S_WRITE; else Next_State = S_READ; else Next_State = S_IDLE; end S_WRITE: begin WEb_int = LO; OEb_int = HI; Busy_int = HI; Capture_int = LO; if (Start == HI) Next_State = S_HOLD; else Next_State = S_IDLE; end S_HOLD: begin WEb_int = HI; OEb_int = HI; Busy_int = HI; Capture_int = LO; if (Start == HI) Next_State = S_HOLD; else Next_State = S_IDLE; end S_READ: begin WEb_int = HI; OEb_int = LO; Busy_int = HI; Capture_int = HI; if (Start == HI) Next_State = S_READ; else Next_State = S_IDLE; end default: begin WEb_int = HI; OEb_int = HI; Busy_int = LO; Capture_int = LO; Next_State = S_IDLE; end endcase end // Test Signals assign Test[7] = Start; assign Test[6] = Write; assign Test[5] = Busy; assign Test[4] = Capture; assign Test[3] = WEb; assign Test[2] = OEb; assign Test[1] = State[1]; assign Test[0] = State[0]; endmodule */ /*=================================================================*/ /*=== SRAM Register Manager ======================================*/ /*=================================================================*/ /* This module monitors the Control register and executes a single thread of execution each time it senses a Start bit assertion. Which thread gets launched is dependent on the Write bit. To prevent multiple executions, the FSM dwells in a hold state until the Start bit is relaxed. */ module SRAM_REG_IO ( Test8, // Test Output Control, Status, // Control/Status Registers Ain, Aout, // Input/Output Addresses WD, RD, // Write/Read Data WP_DataIn, WP_Push, WP_FF, // Write Pipe Interface RP_DataIn, RP_Push, RP_FF, // Read Pipe Interface RB_DataOut, RB_Pop, RB_EF, // Readback Pipe Interface rst, clk ); output [7:0] Test8; // Test output input [7:0] Control; output [7:0] Status; input [23:0] Ain; output [23:0] Aout; input [7:0] WD; output [7:0] RD; output [31:0] WP_DataIn; output WP_Push; input WP_FF; output [23:0] RP_DataIn; output RP_Push; input RP_FF; input [31:0] RB_DataOut; output RB_Pop; input RB_EF; input rst, clk; //----------------------------------------------------------------- parameter HI = 1'b1, LO = 1'b0; assign WP_DataIn = {WD,Ain}; assign RP_DataIn = Ain; assign Aout = RB_DataOut[23:0]; assign RD = RB_DataOut[31:24]; // Internal Signals wire Start, Write, Read; // Control signals wire Busy, Capture; // Status signals // Internal to External Mapping assign Start = Control[0]; assign Write = Control[1]; assign Status[0] = Busy; assign Status[1] = Capture; reg WP_Push_int; reg RP_Push_int; reg RB_Pop_int; assign WP_Push = WP_Push_int; assign RP_Push = RP_Push_int; assign RB_Pop = RB_Pop_int; // FSM State Variables reg [3:0] State, Next_State; // FSM State Definitions parameter S_IDLE = 4'd0, S_ARMED = 4'd1, S_WRITE_0 = 4'd2, S_WRITE_1 = 4'd3, S_WRITE_2 = 4'd4, S_READ_0 = 4'd5, S_READ_1 = 4'd6, S_READ_2 = 4'd7, S_READ_3 = 4'd8; // FSM State Transition Process always @ (posedge clk) begin State <= ((rst == HI)? (S_IDLE):(Next_State)); end reg Busy_int, Capture_int; assign Busy = Busy_int; assign Capture = Capture_int; // FSM State Transition Definitions always @ (State or Start or Write or WP_FF or RP_FF or RB_EF) begin case (State) S_IDLE: begin WP_Push_int = LO; RP_Push_int = LO; RB_Pop_int = LO; Busy_int = LO; Capture_int = LO; if (Start == LO) Next_State = S_ARMED; else Next_State = State; end S_ARMED: begin WP_Push_int = LO; RP_Push_int = LO; RB_Pop_int = LO; Busy_int = LO; Capture_int = LO; if (Start == HI) Next_State = ((Write == HI)? (S_WRITE_0):(S_READ_0)); else Next_State = State; end S_WRITE_0: // Wait for Write Pipe to have space begin WP_Push_int = LO; RP_Push_int = LO; RB_Pop_int = LO; Busy_int = HI; Capture_int = LO; if (WP_FF == LO) Next_State = S_WRITE_1; else Next_State = State; end S_WRITE_1: // Push Write Address/Data into Write Pipe begin WP_Push_int = HI; RP_Push_int = LO; RB_Pop_int = LO; Busy_int = HI; Capture_int = LO; Next_State = S_IDLE; end S_READ_0: // Wait for Read Pipe to have space begin WP_Push_int = LO; RP_Push_int = LO; RB_Pop_int = LO; Busy_int = HI; Capture_int = LO; if (RP_FF == LO) Next_State = S_READ_1; else Next_State = State; end S_READ_1: // Push Read Address/Data into Read Pipe begin WP_Push_int = LO; RP_Push_int = HI; RB_Pop_int = HI; // Pop prior data out of Readback Pipe Busy_int = HI; Capture_int = LO; Next_State = S_READ_2; end S_READ_2: // Wait for Readback Pipe to have data begin WP_Push_int = LO; RP_Push_int = LO; RB_Pop_int = LO; Busy_int = HI; Capture_int = LO; if (RB_EF == LO) Next_State = S_READ_3; else Next_State = State; end S_READ_3: // Wait for Readback Pipe to have data begin WP_Push_int = LO; RP_Push_int = LO; RB_Pop_int = LO; Busy_int = HI; Capture_int = LO; if (RB_EF == LO) Next_State = S_IDLE; else Next_State = State; end default: begin WP_Push_int = LO; RP_Push_int = LO; RB_Pop_int = LO; Busy_int = LO; Capture_int = LO; Next_State = S_IDLE; end endcase end // Test Signals assign Test8[7] = Busy; assign Test8[6] = WP_Push; assign Test8[5] = RP_Push; assign Test8[4] = RB_Pop; assign Test8[3] = State[3]; assign Test8[2] = State[2]; assign Test8[1] = State[1]; assign Test8[0] = State[0]; endmodule /*=================================================================*/ /*=== SRAM Pipe Manager ==========================================*/ /*=================================================================*/ /* The SRAM Pipe Manager is an alternate SRAM I/O Controller that is based on FIFO I/O streams. First Cut: Ping Pong The FSM alternates between making attempts to read and attempts to write. Read Attempt: 1) Check to see if Read Pipe is not empty and Readback Pipe is not full 2) Parse and assert Address from Read Pipe and assert OE 3) Push Data and Address into Readback Pipe and deassert OE. 4) Pop Address from Read Pipe. Write Attempt: 1) Check to see if Write Pipe is not empty 2) Parse and assert Address and Data from Write Pipe 3) Strobe WE. 4) Pop Address and Data from Write Pipe */ module SRAM_PipeManager ( Test8, // Test Port WP_Data, WP_Pop, WP_EF, WP_AF, // Write Pipe RP_Data, RP_Pop, RP_EF, RP_AF, // Read Request Pipe RB_Data, RB_Push, RB_FF, // Readback Pipe A, CSb, DI, DO, OEb, WEb, // MEM1 Address, CS, Data, OE, WE rst, clk // Global Reset and Clock ); parameter HI = 1'b1, LO = 1'b0; output [7:0] Test8; // Test output input [31:0] WP_Data; // Write Pipe Data output WP_Pop; input WP_EF, WP_AF; input [23:0] RP_Data; // Read Pipe Data output RP_Pop; input RP_EF, RP_AF; output [31:0] RB_Data; // Readback Pipe Data output RB_Push; input RB_FF; output [18:0] A; // MEM1 Address output [7:0] DI; // MEM1 Data In input [7:0] DO; // MEM1 Data Out output OEb, WEb; // MEM1 Output Enable, Write Enable output [1:0] CSb; // MEM1 Chip Select input rst, clk; // Global reset and clock //----------------------------------------------------------------- // Internal Signals // Address Parsing assign DI = WP_Data[31:24]; assign RB_Data = {DO,RP_Data[23:0]}; //TriBuf8 ZBUF (.Q(D), .D(WP_Data[31:24]), .OE(~WEb)); reg [18:0] A_int; reg [1:0] CSb_int; reg WEb_int, OEb_int; assign A = A_int; assign CSb = CSb_int; assign WEb = WEb_int; assign OEb = OEb_int; reg WP_Pop_int, RP_Pop_int, RB_Push_int; assign WP_Pop = WP_Pop_int; assign RP_Pop = RP_Pop_int; assign RB_Push = RB_Push_int; // FSM State Variables reg [2:0] State, Next_State; // FSM State Definitions parameter S_READ_0 = 3'b000, S_READ_1 = 3'b001, S_READ_2 = 3'b010, S_READ_3 = 3'b011, S_WRITE_0 = 3'b100, S_WRITE_1 = 3'b101, S_WRITE_2 = 3'b110, S_WRITE_3 = 3'b111; // FSM State Transition Process always @ (posedge clk) begin State <= ((rst == HI)? (S_READ_0):(Next_State)); end // FSM State Transition Definitions always @ (State or WP_Data or WP_EF or RP_Data or RP_EF or RB_FF) begin case (State) S_READ_0: begin WP_Pop_int = LO; RP_Pop_int = LO; RB_Push_int = LO; A_int = RP_Data[18:0]; CSb_int[1] = ~RP_Data[19]; CSb_int[0] = RP_Data[19]; OEb_int = HI; WEb_int = HI; if ((RP_EF == LO)&&(RB_FF == LO)) Next_State = S_READ_1; else Next_State = S_WRITE_0; end S_READ_1: begin WP_Pop_int = LO; RP_Pop_int = LO; RB_Push_int = LO; A_int = RP_Data[18:0]; CSb_int[1] = ~RP_Data[19]; CSb_int[0] = RP_Data[19]; OEb_int = LO; WEb_int = HI; Next_State = S_READ_2; end S_READ_2: begin WP_Pop_int = LO; RP_Pop_int = LO; RB_Push_int = HI; A_int = RP_Data[18:0]; CSb_int[1] = ~RP_Data[19]; CSb_int[0] = RP_Data[19]; OEb_int = LO; WEb_int = HI; Next_State = S_READ_3; end S_READ_3: begin WP_Pop_int = LO; RP_Pop_int = HI; RB_Push_int = LO; A_int = WP_Data[18:0]; CSb_int[1] = ~WP_Data[19]; CSb_int[0] = WP_Data[19]; OEb_int = HI; WEb_int = HI; Next_State = S_WRITE_0; end S_WRITE_0: begin WP_Pop_int = LO; RP_Pop_int = LO; RB_Push_int = LO; A_int = WP_Data[18:0]; CSb_int[1] = ~WP_Data[19]; CSb_int[0] = WP_Data[19]; OEb_int = HI; WEb_int = HI; if (WP_EF == LO) Next_State = S_WRITE_1; else Next_State = S_READ_0; end S_WRITE_1: begin WP_Pop_int = LO; RP_Pop_int = LO; RB_Push_int = LO; A_int = WP_Data[18:0]; CSb_int[1] = ~WP_Data[19]; CSb_int[0] = WP_Data[19]; OEb_int = HI; WEb_int = LO; Next_State = S_WRITE_2; end S_WRITE_2: begin WP_Pop_int = LO; RP_Pop_int = LO; RB_Push_int = LO; A_int = WP_Data[18:0]; CSb_int[1] = ~WP_Data[19]; CSb_int[0] = WP_Data[19]; OEb_int = HI; WEb_int = HI; Next_State = S_WRITE_3; end S_WRITE_3: begin WP_Pop_int = HI; RP_Pop_int = LO; RB_Push_int = LO; A_int = RP_Data[18:0]; CSb_int[1] = ~RP_Data[19]; CSb_int[0] = RP_Data[19]; OEb_int = HI; WEb_int = HI; Next_State = S_READ_0; end default: begin WP_Pop_int = LO; RP_Pop_int = LO; RB_Push_int = LO; A_int = WP_Data[18:0]; CSb_int[1] = ~WP_Data[19]; CSb_int[0] = WP_Data[19]; OEb_int = HI; WEb_int = HI; Next_State = S_READ_0; end endcase end // Test Signals assign Test8[7] = WP_Pop; assign Test8[6] = RP_Pop; assign Test8[5] = RB_Push; assign Test8[4] = WEb; assign Test8[3] = OEb; assign Test8[2] = State[2]; assign Test8[1] = State[1]; assign Test8[0] = State[0]; endmodule module WRITE_PIPE_MUX ( Test, // Pipe A Signals Pipe0_DataOut, Pipe0_Pop, Pipe0_FF, Pipe0_AF, Pipe0_EF, // Pipe B Signals Pipe1_DataOut, Pipe1_Pop, Pipe1_FF, Pipe1_AF, Pipe1_EF, // Write Pipe WP_Data, WP_Pop, WP_EF, WP_AF, // Global Reset and Clock rst, clk ); // Test Signals output [ 7:0] Test; // Pipe 0 Signals input [31:0] Pipe0_DataOut; output Pipe0_Pop; input Pipe0_FF, Pipe0_AF, Pipe0_EF; // Pipe 1 Signals input [31:0] Pipe1_DataOut; output Pipe1_Pop; input Pipe1_FF, Pipe1_AF, Pipe1_EF; // Write Pipe output [31:0] WP_Data; input WP_Pop; output WP_EF, WP_AF; // Global Reset and Clock input rst, clk; parameter HI = 1'b1, LO = 1'b0; parameter Pipe0 = 1'b0, Pipe1 = 1'b1; // Event Pipeline // 1) Select a Pipe // 2) IF Pipe Has Data (EF is LO) // 2.1) Connect Pipe to Pipe Manager // 2.2) Wait for Pipe Manager to issue Pop // 2.3) Disconnect Pipe from Pipe Manager // 2.4) Issue Pop // 3) GOTO Step 1 wire Pipe; wire Connect; wire WP_AF_int, WP_EF_int; assign WP_AF = (Connect == HI)? WP_AF_int : LO; assign WP_EF = (Connect == HI)? WP_EF_int : HI; wire Pop; assign Pipe0_Pop = (Pipe == Pipe0)? Pop : LO; assign Pipe1_Pop = (Pipe == Pipe1)? Pop : LO; MUX2x8 WPMUX_D_B0 ( .Q(WP_Data[7:0]), .D1(Pipe1_DataOut[7:0]), .D0(Pipe0_DataOut[7:0]), .Sel(Pipe) ); MUX2x8 WPMUX_D_B1 ( .Q(WP_Data[15:8]), .D1(Pipe1_DataOut[15:8]), .D0(Pipe0_DataOut[15:8]), .Sel(Pipe) ); MUX2x8 WPMUX_D_B2 ( .Q(WP_Data[23:16]), .D1(Pipe1_DataOut[23:16]), .D0(Pipe0_DataOut[23:16]), .Sel(Pipe) ); MUX2x8 WPMUX_D_B3 ( .Q(WP_Data[31:24]), .D1(Pipe1_DataOut[31:24]), .D0(Pipe0_DataOut[31:24]), .Sel(Pipe) ); MUX2x2 WPMUX_FLAGS ( .Q ({WP_AF_int, WP_EF_int}), .D1({Pipe1_AF, Pipe1_EF}), .D0({Pipe0_AF, Pipe0_EF}), .Sel(Pipe) ); reg Pipe_int; reg Connect_int; reg Pop_int; assign Pipe = Pipe_int; assign Connect = Connect_int; assign Pop = Pop_int; reg [2:0] State, Next_State; parameter S_INI = 3'd0, S_P0_0 = 3'd1, S_P0_1 = 3'd2, S_P0_2 = 3'd3, S_P1_0 = 3'd4, S_P1_1 = 3'd5, S_P1_2 = 3'd6; always @ (posedge clk) begin if (rst == HI) State <= S_INI; else State <= Next_State; end always @ (State or WP_Pop or WP_EF_int) begin case (State) S_INI: begin Pipe_int <= Pipe0; Connect_int <= LO; Pop_int <= LO; Next_State <= S_P0_0; end S_P0_0: begin if (WP_EF_int == LO) begin Pipe_int <= Pipe0; Connect_int <= HI; Pop_int <= LO; Next_State <= S_P0_1; end else begin Pipe_int <= Pipe1; Connect_int <= LO; Pop_int <= LO; Next_State <= S_P1_0; end end S_P0_1: begin if (WP_Pop == LO) begin Pipe_int <= Pipe0; Connect_int <= HI; Pop_int <= LO; Next_State <= State; end else begin Pipe_int <= Pipe0; Connect_int <= LO; Pop_int <= HI; Next_State <= S_P0_2; end end S_P0_2: begin Pipe_int <= Pipe1; Connect_int <= LO; Pop_int <= LO; Next_State <= S_P1_0; end S_P1_0: begin if (WP_EF_int == LO) begin Pipe_int <= Pipe1; Connect_int <= HI; Pop_int <= LO; Next_State <= S_P1_1; end else begin Pipe_int <= Pipe0; Connect_int <= LO; Pop_int <= LO; Next_State <= S_P0_0; end end S_P1_1: begin if (WP_Pop == LO) begin Pipe_int <= Pipe1; Connect_int <= HI; Pop_int <= LO; Next_State <= State; end else begin Pipe_int <= Pipe1; Connect_int <= LO; Pop_int <= HI; Next_State <= S_P1_2; end end S_P1_2: begin Pipe_int <= Pipe0; Connect_int <= LO; Pop_int <= LO; Next_State <= S_P0_0; end default: begin Pipe_int <= Pipe0; Connect_int <= LO; Pop_int <= LO; Next_State <= S_INI; end endcase end assign Test[7] = Pop; assign Test[6] = WP_EF; assign Test[5] = Connect; assign Test[4] = Pipe0_EF; assign Test[3] = Pipe; assign Test[2:0] = State; endmodule module READ_PIPE_MUX ( Test, // Pipe A Signals Pipe0_DataOut, Pipe0_Pop, Pipe0_FF, Pipe0_AF, Pipe0_EF, // Pipe B Signals Pipe1_DataOut, Pipe1_Pop, Pipe1_FF, Pipe1_AF, Pipe1_EF, // Pipe C Signals Pipe2_DataOut, Pipe2_Pop, Pipe2_FF, Pipe2_AF, Pipe2_EF, // Read Request Pipe RP_Data, RP_Pop, RP_EF, RP_AF, // Global Reset and Clock rst, clk ); // Test Signals output [ 7:0] Test; // Pipe A Signals input [23:0] Pipe0_DataOut; output Pipe0_Pop; input Pipe0_FF, Pipe0_AF, Pipe0_EF; // Pipe B Signals input [23:0] Pipe1_DataOut; output Pipe1_Pop; input Pipe1_FF, Pipe1_AF, Pipe1_EF; // Pipe C Signals input [23:0] Pipe2_DataOut; output Pipe2_Pop; input Pipe2_FF, Pipe2_AF, Pipe2_EF; // Read Request Pipe output [23:0] RP_Data; input RP_Pop; output RP_EF, RP_AF; // Global Reset and Clock input rst, clk; parameter HI = 1'b1, LO = 1'b0; parameter Pipe0 = 2'd0, Pipe1 = 2'd1, Pipe2 = 2'd2; // Event Pipeline // 1) Select a Pipe // 2) IF Pipe Has Data (EF is LO) // 2.1) Connect Pipe to Pipe Manager // 2.2) Wait for Pipe Manager to issue Pop // 2.3) Disconnect Pipe from Pipe Manager // 2.4) Issue Pop // 3) GOTO Step 1 wire [1:0] Pipe; wire Connect; wire RP_AF_int, RP_EF_int; assign RP_AF = (Connect == HI)? RP_AF_int : LO; assign RP_EF = (Connect == HI)? RP_EF_int : HI; wire Pop; assign Pipe0_Pop = (Pipe == Pipe0)? Pop : LO; assign Pipe1_Pop = (Pipe == Pipe1)? Pop : LO; assign Pipe2_Pop = (Pipe == Pipe2)? Pop : LO; MUX4x8 RPMUX_D_B0 ( .Q(RP_Data[7:0]), .D3(8'd0), .D2(Pipe2_DataOut[7:0]), .D1(Pipe1_DataOut[7:0]), .D0(Pipe0_DataOut[7:0]), .Sel(Pipe) ); MUX4x8 RPMUX_D_B1 ( .Q(RP_Data[15:8]), .D3(8'd0), .D2(Pipe2_DataOut[15:8]), .D1(Pipe1_DataOut[15:8]), .D0(Pipe0_DataOut[15:8]), .Sel(Pipe) ); MUX4x8 RPMUX_D_B2 ( .Q(RP_Data[23:16]), .D3(8'd0), .D2({Pipe, Pipe2_DataOut[21:16]}), .D1({Pipe, Pipe1_DataOut[21:16]}), .D0({Pipe, Pipe0_DataOut[21:16]}), .Sel(Pipe) ); MUX4x2 WPMUX_FLAGS ( .Q ({WP_AF_int, WP_EF_int}), .D3({LO,HI}), .D2({Pipe2_AF, Pipe2_EF}), .D1({Pipe1_AF, Pipe1_EF}), .D0({Pipe0_AF, Pipe0_EF}), .Sel(Pipe) ); reg [1:0] Pipe_int; reg Connect_int; reg Pop_int; assign Pipe = Pipe_int; assign Connect = Connect_int; assign Pop = Pop_int; reg [3:0] State, Next_State; parameter S_INI = 4'd0, S_P0_0 = 4'd1, S_P0_1 = 4'd2, S_P0_2 = 4'd3, S_P1_0 = 4'd4, S_P1_1 = 4'd5, S_P1_2 = 4'd6, S_P2_0 = 4'd7, S_P2_1 = 4'd8, S_P2_2 = 4'd9; always @ (posedge clk) begin if (rst == HI) State <= S_INI; else State <= Next_State; end always @ (State or RP_EF_int or RP_Pop) begin case (State) S_INI: begin Pipe_int <= Pipe0; Connect_int <= LO; Pop_int <= LO; Next_State <= S_P0_0; end S_P0_0: begin if (RP_EF_int == LO) begin Pipe_int <= Pipe0; Connect_int <= HI; Pop_int <= LO; Next_State <= S_P0_1; end else begin Pipe_int <= Pipe1; Connect_int <= LO; Pop_int <= LO; Next_State <= S_P1_0; end end S_P0_1: begin if (RP_Pop == LO) begin Pipe_int <= Pipe0; Connect_int <= HI; Pop_int <= LO; Next_State <= State; end else begin Pipe_int <= Pipe0; Connect_int <= LO; Pop_int <= HI; Next_State <= S_P0_2; end end S_P0_2: begin Pipe_int <= Pipe1; Connect_int <= LO; Pop_int <= LO; Next_State <= S_P1_0; end S_P1_0: begin if (RP_EF_int == LO) begin Pipe_int <= Pipe1; Connect_int <= HI; Pop_int <= LO; Next_State <= S_P1_1; end else begin Pipe_int <= Pipe2; Connect_int <= LO; Pop_int <= LO; Next_State <= S_P2_0; end end S_P1_1: begin if (RP_Pop == LO) begin Pipe_int <= Pipe1; Connect_int <= HI; Pop_int <= LO; Next_State <= State; end else begin Pipe_int <= Pipe1; Connect_int <= LO; Pop_int <= HI; Next_State <= S_P1_2; end end S_P1_2: begin Pipe_int <= Pipe2; Connect_int <= LO; Pop_int <= LO; Next_State <= S_P2_0; end S_P2_0: begin if (RP_EF_int == LO) begin Pipe_int <= Pipe2; Connect_int <= HI; Pop_int <= LO; Next_State <= S_P2_1; end else begin Pipe_int <= Pipe0; Connect_int <= LO; Pop_int <= LO; Next_State <= S_P0_0; end end S_P2_1: begin if (RP_Pop == LO) begin Pipe_int <= Pipe2; Connect_int <= HI; Pop_int <= LO; Next_State <= State; end else begin Pipe_int <= Pipe2; Connect_int <= LO; Pop_int <= HI; Next_State <= S_P2_2; end end S_P2_2: begin Pipe_int <= Pipe0; Connect_int <= LO; Pop_int <= LO; Next_State <= S_P0_0; end default: begin Pipe_int <= Pipe0; Connect_int <= LO; Pop_int <= LO; Next_State <= S_INI; end endcase end assign Test[7] = Pop; assign Test[6] = RP_EF; assign Test[5] = Connect; assign Test[4] = Pipe0_EF; assign Test[3:0] = State; endmodule module READBACK_PIPE_MUX ( Test, // Pipe A Signals Pipe0_DataIn, Pipe0_Push, Pipe0_FF, Pipe0_EF, // Pipe B Signals Pipe1_DataIn, Pipe1_Push, Pipe1_FF, Pipe1_EF, // Pipe C Signals Pipe2_DataIn, Pipe2_Push, Pipe2_FF, Pipe2_EF, // Readback Pipe RB_Data, RB_Push, RB_FF, // Global Reset and Clock rst, clk ); // Test Signals output [ 7:0] Test; // Pipe A Signals output [31:0] Pipe0_DataIn; output Pipe0_Push; input Pipe0_FF, Pipe0_EF; // Pipe B Signals output [31:0] Pipe1_DataIn; output Pipe1_Push; input Pipe1_FF, Pipe1_EF; // Pipe C Signals output [31:0] Pipe2_DataIn; output Pipe2_Push; input Pipe2_FF, Pipe2_EF; // Readback Pipe input [31:0] RB_Data; input RB_Push; output RB_FF; // Global Reset and Clock input rst, clk; parameter HI = 1'b1, LO = 1'b0; parameter Pipe0 = 2'd0, Pipe1 = 2'd1, Pipe2 = 2'd2; // NOTE - THIS IS A TEMPORARY KLUDGE!!! assign RB_FF = LO; assign Pipe0_DataIn = {RB_Data[31:24], 2'd0, RB_Data[21:0]}; assign Pipe1_DataIn = {RB_Data[31:24], 2'd0, RB_Data[21:0]}; assign Pipe2_DataIn = {RB_Data[31:24], 2'd0, RB_Data[21:0]}; reg Pipe0_Push_int; reg Pipe1_Push_int; reg Pipe2_Push_int; assign Pipe0_Push = Pipe0_Push_int; assign Pipe1_Push = Pipe1_Push_int; assign Pipe2_Push = Pipe2_Push_int; always @ (RB_Push or RB_Data[23:22]) begin case (RB_Data[23:22]) Pipe0: begin Pipe0_Push_int <= RB_Push; Pipe1_Push_int <= LO; Pipe2_Push_int <= LO; end Pipe1: begin Pipe0_Push_int <= LO; Pipe1_Push_int <= RB_Push; Pipe2_Push_int <= LO; end Pipe2: begin Pipe0_Push_int <= LO; Pipe1_Push_int <= LO; Pipe2_Push_int <= RB_Push; end default: begin Pipe0_Push_int <= LO; Pipe1_Push_int <= LO; Pipe2_Push_int <= LO; end endcase end assign Test[7:6] = RB_Data[31:30]; assign Test[5:4] = RB_Data[23:22]; assign Test[3] = RB_Push; assign Test[2] = Pipe0_Push; assign Test[1] = Pipe1_Push; assign Test[0] = Pipe2_Push; endmodule