/*! * Module:debug_master * @file debug_master.v * @date 2015-09-03 * @author Andrey Filippov * * @brief Debug master module to send/receive serial debug data * * @copyright Copyright (c) 2015 Elphel, Inc . * * License: * * debug_master.v is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * debug_master.v is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Additional permission under GNU GPL version 3 section 7: * If you modify this Program, or any covered work, by linking or combining it * with independent modules provided by the FPGA vendor only (this permission * does not extend to any 3-rd party modules, "soft cores" or macros) under * different license terms solely for the purpose of generating binary "bitstream" * files and/or simulating the code, the copyright holders of this Program give * you the right to distribute the covered work without those independent modules * as long as the source code for them is available from the FPGA vendor free of * charge, and there is no dependence on any encrypted modules for simulating of * the combined code. This permission applies to you if the distributed code * contains all the components and scripts required to completely simulate it * with at least one of the Free Software programs. */ `timescale 1ns/1ps module debug_master #( parameter DEBUG_ADDR = 'h710, //..'h713 parameter DEBUG_MASK = 'h7fc, parameter DEBUG_STATUS_REG_ADDR = 'hfc, // address where status can be read out parameter DEBUG_READ_REG_ADDR = 'hfd, // read 32-bit received shifted data parameter DEBUG_SHIFT_DATA = 'h0, // shift i/o data by 32 bits parameter DEBUG_LOAD = 'h1, // parallel load of the distributed shift registe (both ways) parameter DEBUG_SET_STATUS = 'h2, // program status (mode 3?) parameter DEBUG_CMD_LATENCY = 2 // >0 extra registers in the debug_sl (distriburted in parallel) )( input mclk, input mrst, // @ posedge mclk - sync reset // programming interface input [7:0] cmd_ad, // byte-serial command address/data (up to 6 bytes: AL-AH-D0-D1-D2-D3 input cmd_stb, // strobe (with first byte) for the command a/d output [7:0] status_ad, // status address/data - up to 5 bytes: A - {seq,status[1:0]} - status[2:9] - status[10:17] - status[18:25] output status_rq, // input request to send status downstream input status_start, // Acknowledge of the first status packet byte (address) // debug ring output debug_do, // data out to the debug ring @posedge mclk, LSB first output debug_sl, // 0 - idle, (1,0) - shift, (1,1) - load input debug_di // input data from the debug ring, LSB first ); wire [1:0] cmd_a; wire [31:0] cmd_data; wire cmd_we; reg [31:0] data_sr; reg tgl; reg [ 6:0] cntr; reg ld_r; reg cmd; //command stae (0 - idle) reg [DEBUG_CMD_LATENCY : 0] cmd_reg; wire [3:0] debug_latency_plus1 = DEBUG_CMD_LATENCY+1; wire set_status_w = cmd_we && (cmd_a == DEBUG_SET_STATUS); wire shift32_w = cmd_we && (cmd_a == DEBUG_SHIFT_DATA); wire load_w = cmd_we && (cmd_a == DEBUG_LOAD); wire cmd_reg_dly = cmd_reg[DEBUG_CMD_LATENCY]; wire shift_done; assign debug_sl = cmd_reg[0]; assign debug_do = data_sr[0]; always @ (posedge mclk) begin if (mrst) ld_r <= 0; else ld_r <= load_w; if (mrst) cntr <= 0; else if (shift32_w) cntr <= 7'h41; else if (cntr[6]) cntr <= cntr + 1; if (mrst) cmd_reg <= 0; else cmd_reg <= {cmd_reg[DEBUG_CMD_LATENCY - 1 : 0], load_w | ld_r | cntr[0]}; if (mrst) cmd <= 0; else cmd <= cmd_reg_dly & ~cmd; if (shift32_w) data_sr <= cmd_data; else if (cmd && !cmd_reg_dly) data_sr <= {debug_di, data_sr[31:1]}; if (mrst) tgl <= 0; else tgl <= tgl ^ shift_done; // When counter == 127 - toggle tgl to initiate status send end dly_16 #( .WIDTH(1) ) dly_16_i ( .clk (mclk), // input .rst (1'b0), // input .dly (debug_latency_plus1), // DEBUG_CMD_LATENCY+1), // input[3:0] .din (&cntr), // input[0:0] .dout (shift_done) // output[0:0] ); cmd_deser #( .ADDR (DEBUG_ADDR), .ADDR_MASK (DEBUG_MASK), .NUM_CYCLES (6), .ADDR_WIDTH (2), .DATA_WIDTH (32) ) cmd_deser_32bit_i ( .rst (1'b0), //rst), // input .clk (mclk), // input .srst (mrst), // input .ad (cmd_ad), // input[7:0] .stb (cmd_stb), // input .addr (cmd_a), // output[3:0] .data (cmd_data), // output[31:0] .we (cmd_we) // output ); status_generate #( .STATUS_REG_ADDR (DEBUG_STATUS_REG_ADDR), .PAYLOAD_BITS (1), .REGISTER_STATUS (0), .EXTRA_WORDS (1), .EXTRA_REG_ADDR (DEBUG_READ_REG_ADDR) ) status_generate_i ( .rst (1'b0), // rst), // input .clk (mclk), // input .srst (mrst), // input .we (set_status_w), // input .wd (cmd_data[7:0]), // input[7:0] .status ({data_sr,tgl}), // input[14:0] .ad (status_ad), // output[7:0] .rq (status_rq), // output .start (status_start) // input ); endmodule