--- /dev/null
+/* ****************************************************************************\r
+-- (C) Copyright 2015 Kevin M. Hubbard @ Black Mesa Labs\r
+-- Source file: mesa_decode.v \r
+-- Date: October 4, 2015 \r
+-- Author: khubbard\r
+-- Language: Verilog-2001 \r
+-- Description: The Mesa Bus decoder. Mesa Bus is a byte-pipe much like a \r
+-- 8b10b SERDES pipe. It supports sending packetized streams of\r
+-- serialized bytes to multiple targets on a single serial bus.\r
+-- This implementation uses UART serial, but the protocol is \r
+-- portable and may be used over SERDES or a synchronous bit,\r
+-- nibble or byte wide streams. \r
+-- This block decodes packets and routes them to both\r
+-- dowstream slots and the internal sub-slots for this slot.\r
+-- License: This project is licensed with the CERN Open Hardware Licence\r
+-- v1.2. You may redistribute and modify this project under the\r
+-- terms of the CERN OHL v.1.2. (http://ohwr.org/cernohl).\r
+-- This project is distributed WITHOUT ANY EXPRESS OR IMPLIED\r
+-- WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY\r
+-- AND FITNESS FOR A PARTICULAR PURPOSE. Please see the CERN OHL\r
+-- v.1.2 for applicable Conditions.\r
+--\r
+--\r
+-- Example:\r
+-- .."FF".."FF"."F0123401[56]" : \r
+-- 0xFF = Bus Idle ( NULLs )\r
+-- B0 0xF0 = New Bus Cycle to begin ( Nibble and bit orientation )\r
+-- B1 0x12 = Slot Number, 0xFF = Broadcast all slots, 0xFE = NULL Dest\r
+-- B2 0x3 = Sub-Slot within the chip (0-0xF)\r
+-- 0x4 = Command Nibble for Sub-Slot ( Specific to that SubSlot )\r
+-- B3 0x01 = Number of Payload Bytes (0-255)\r
+-- 0x56 = The Payload ( 1 Byte in this example, up to 255 total )\r
+--\r
+-- Slot Numbering 0x00-0xFF:\r
+-- 0x00 - 0xFD : Physical Slots 0-253\r
+-- 0xF0 - 0xFD : Reserved\r
+-- 0xFE : Nobody slot ( NULL )\r
+-- 0xFF : Broadcast to 0x00-0xEF\r
+--\r
+-- SubSlot Numbering 0x0-0xF:\r
+-- 0x0 - 0x7 : User SubSlots ( 0x0 is nominally a 32bit PCI local bus )\r
+-- 0x0 = LB Bus Write\r
+-- 0x1 = LB Bus Read\r
+-- 0x2 = LB Bus Write Repeat ( same address )\r
+-- 0x3 = LB Bus Read Repeat ( same address )\r
+-- 0x8 - 0xB : Scope Probe CH1-CH4 Mux Selects\r
+-- 0x0 - 0xF : 1 of 16 signal sets to observe. 0x0 nom OFF\r
+-- 0xE : FPGA PROM Access\r
+-- Commands:\r
+-- 0x0 = LB Bus Write\r
+-- 0x1 = LB Bus Read\r
+-- 0x2 = LB Bus Write Repeat ( same address )\r
+-- 0x3 = LB Bus Read Repeat ( same address )\r
+-- 0xF : Mesa Control : Power and Pin Control\r
+-- Commands:\r
+--\r
+-- 0x0 = Ro pin is MesaBus Ro Readback ( Default )\r
+-- 0x1 = Ro pin is MesaBus Wi loopback\r
+-- 0x2 = Ro pin is MesaBus Interrupt\r
+-- 0x3 = Ro pin is user defined output function\r
+-- 0x4 = Ri pin is MesaBus Input ( Default )\r
+-- 0x5 = Ri pin is disabled\r
+-- 0x6 = Wo pin is MesaBus Output ( Default )\r
+-- 0x7 = Wo pin is disabled\r
+--\r
+-- 0x8 = RESERVED\r
+-- 0x9 = RESERVED\r
+-- 0xA = Report Device ID\r
+-- 0xB = Reset Core \r
+-- 0xC = Clear Baud Lock\r
+-- 0xD = Power Off - Clock Trees Disabled\r
+-- 0xE = Boot to Slot-1 Bootloader (Default)\r
+-- 0xF = Boot to Slot-2 User Image\r
+--\r
+-- Revision History:\r
+-- Ver# When Who What\r
+-- ---- -------- -------- ---------------------------------------------------\r
+-- 0.1 10.04.15 khubbard Creation\r
+-- ***************************************************************************/\r
+//`default_nettype none // Strictly enforce all nets to be declared\r
+ \r
+module mesa_decode\r
+(\r
+ input wire clk,\r
+ input wire reset,\r
+ input wire [3:0] rx_in_d,\r
+ input wire rx_in_rdy,\r
+ output wire [7:0] rx_out_d,\r
+ output wire rx_out_rdy,\r
+ output wire [7:0] rx_loc_d,\r
+ output wire rx_loc_rdy,\r
+ output wire rx_loc_start,\r
+ output wire rx_loc_stop\r
+); // module mesa_decode\r
+\r
+\r
+ reg lbracket_jk;\r
+ reg passthru_jk;\r
+ reg broadcst_jk;\r
+ reg payload_jk;\r
+ reg process_jk;\r
+\r
+ reg packet_jk;\r
+ reg packet_jk_p1;\r
+ reg [7:0] byte_sr;\r
+ reg byte_pingpong;\r
+ reg rx_in_rdy_p1;\r
+ reg byte_rdy;\r
+ reg byte_rdy_p1;\r
+ reg [3:0] byte_cnt;\r
+ reg [7:0] byte_loc;\r
+ reg [7:0] byte_out;\r
+ reg [7:0] payload_cnt;\r
+ reg packet_done;\r
+\r
+ reg loc_start;\r
+ reg [7:0] loc_slot;\r
+ reg [3:0] loc_subslot;\r
+ reg [3:0] loc_command;\r
+ reg [7:0] loc_payload;\r
+\r
+ assign rx_out_d = byte_out[7:0];\r
+ assign rx_out_rdy = byte_rdy_p1;\r
+ assign rx_loc_d = byte_loc[7:0];\r
+ assign rx_loc_rdy = byte_rdy_p1;\r
+ assign rx_loc_start = loc_start;\r
+ assign rx_loc_stop = packet_done;\r
+\r
+\r
+//-----------------------------------------------------------------------------\r
+// Shift a nibble into a byte shift register. The 1st 0xF0 received when NOT\r
+// currently in a packet determines the phasing for byte within nibble stream.\r
+//-----------------------------------------------------------------------------\r
+always @ ( posedge clk ) begin : proc_nib_in \r
+ rx_in_rdy_p1 <= rx_in_rdy;\r
+ if ( rx_in_rdy == 1 ) begin\r
+ byte_sr[7:4] <= byte_sr[3:0];\r
+ byte_sr[3:0] <= rx_in_d[3:0];\r
+ byte_pingpong <= ~ byte_pingpong;\r
+ end\r
+ if ( packet_jk == 0 ) begin\r
+ byte_pingpong <= 0;\r
+ end\r
+ if ( reset == 1 ) begin\r
+ byte_sr[7:0] <= 8'hFF;\r
+ end\r
+end\r
+\r
+\r
+//-----------------------------------------------------------------------------\r
+// Decode and direct : Packet begins on a 0xF0 byte - which provides for both \r
+// bit and nibble alignment as bus sits idle at 0xFF.\r
+//-----------------------------------------------------------------------------\r
+always @ ( posedge clk ) begin : proc_byte_in \r
+ byte_rdy <= 0;\r
+ packet_jk_p1 <= packet_jk;\r
+\r
+ if ( rx_in_rdy_p1 == 1 ) begin\r
+ if ( byte_sr == 8'hF0 && packet_jk == 0 ) begin\r
+ packet_jk <= 1;\r
+ byte_rdy <= 1;\r
+ end\r
+ if ( packet_jk == 1 && byte_pingpong == 0 ) begin\r
+ byte_rdy <= 1;\r
+ end\r
+ end\r
+\r
+ if ( reset == 1 || packet_done == 1 ) begin\r
+ packet_jk <= 0;\r
+ end\r
+end // proc_byte_in\r
+\r
+\r
+//-----------------------------------------------------------------------------\r
+// B0 B1 B2 B3\r
+// 0xFF,0xFF,0xF0,Slot,Sub-Slot+Command,Payload_Len,{ payload },\r
+//\r
+// A Packet is a 4-byte header followed by an optional n-Byte Payload.\r
+// The Byte after the 1st 0xF0 determines the destination slot.\r
+// slot 0xFF is broadcast and is forwarded untouched as 0xFF.\r
+// slot 0xFE is null and is forwarded untouched as 0xFE.\r
+// slot 0x00 is for this slot and is forwarded as 0xFE.\r
+// slot 0x01-0xFD is decremented by 1 and forwarded\r
+// The 4th Byte determines the length of the payload. If 0, the packet is done.\r
+// otherwise, packet continues for n-Bytes to deliver the payload. A 0xF0 \r
+// following a completed packet indicates start of next packet.\r
+//-----------------------------------------------------------------------------\r
+always @ ( posedge clk ) begin : proc_header\r
+ byte_rdy_p1 <= byte_rdy;\r
+ packet_done <= 0;\r
+ loc_start <= 0;\r
+ if ( byte_rdy == 1 ) begin\r
+ // Count the Packet Header Bytes from 1-4 and stop\r
+ if ( byte_cnt != 4'h4 ) begin\r
+ byte_cnt <= byte_cnt + 1;\r
+ end\r
+ if ( byte_cnt == 4'h3 ) begin\r
+ payload_cnt <= byte_sr[7:0];\r
+ if ( byte_sr == 8'd0 ) begin\r
+ packet_done <= 1;// No Payload - done immediately\r
+ end\r
+ end\r
+ if ( byte_cnt == 4'h4 ) begin\r
+ payload_cnt <= payload_cnt - 1;\r
+ end\r
+ if ( byte_cnt == 4'h4 && payload_cnt == 8'd1 ) begin\r
+ packet_done <= 1;\r
+ end\r
+\r
+ if ( byte_cnt == 4'h0 ) begin\r
+ loc_start <= 1;\r
+ end\r
+ if ( byte_cnt == 4'h1 ) begin\r
+ loc_slot <= byte_sr[7:0];\r
+ end\r
+ if ( byte_cnt == 4'h2 ) begin\r
+ loc_subslot <= byte_sr[7:4];\r
+ loc_command <= byte_sr[3:0];\r
+ end\r
+ if ( byte_cnt == 4'h3 ) begin\r
+ loc_payload <= byte_sr[7:0];\r
+ end\r
+\r
+ // Decode the Slot Number, Decrement when needed. Route to Local and Ext\r
+ if ( byte_cnt == 4'h1 ) begin\r
+ if ( byte_sr == 8'hFF ||\r
+ byte_sr == 8'hFE ) begin\r
+ byte_loc <= byte_sr[7:0];// 0xFF Broadcast and 0xFE null go to everybody\r
+ byte_out <= byte_sr[7:0];\r
+ end else if ( byte_sr != 8'h00 ) begin\r
+ byte_loc <= 8'hFE;\r
+ byte_out <= byte_sr[7:0] - 1;// Decrement the Slot Number as non-zero\r
+ end else begin\r
+ byte_loc <= byte_sr[7:0];// Slot Number is 0x00, so this slot gets it\r
+ byte_out <= 8'hFE; // Downstream slots get 0xFE instead\r
+ end\r
+ end else begin\r
+ byte_loc <= byte_sr[7:0];\r
+ byte_out <= byte_sr[7:0];\r
+ end\r
+ end // if ( byte_rdy == 1 ) begin\r
+\r
+ if ( packet_jk == 0 ) begin\r
+ byte_cnt <= 4'd0;\r
+ payload_cnt <= 8'd0;\r
+ end\r
+end // proc_header\r
+\r
+\r
+endmodule // mesa_decode\r