Commit f97c6e28 authored by Andrey Filippov's avatar Andrey Filippov

continue on status infrastructure

parent 2ec40de8
......@@ -5,4 +5,5 @@ simulation/*
ise_*
attic/*
IVERILOG_INCLUDE.v
eddr3.prj
\ No newline at end of file
x393.prj
*DEBUG_VDT*
/*******************************************************************************
* Module: status_generate
* Date:2015-01-14
* Author: andrey
* Description: generate byte-serial status data
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* status_generate.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.
*
* status_generate.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 <http://www.gnu.org/licenses/> .
*******************************************************************************/
`timescale 1ns/1ps
// mode bits: 0 disable status generation, 1 single status request, 2 - auto status, keep specified seq number, 3 - auto, inc sequence number
module status_generate #(
parameter STATUS_REG_ADDR=7, // status register address to direct data to
parameter PAYLOAD_BITS=26 //6 // >=2! (2..26)
)(
input rst,
input clk,
input we, // command strobe
input [7:0] wd, // command data - 6 bits of sequence and 2 mode bits
input [PAYLOAD_BITS-1:0] status, // parallel status data to be sent out
output [7:0] ad, // byte-wide address/data
output rq, // request to send downstream (last byte with rq==0)
input start // acknowledge of address (first byte) from downsteram
);
/*
Some tools may not like {0{}}, and currently VEditor makes it UNDEFINED->32 bits
assigning to constant?a:b now works if constant has defined value, i.e. if constant=1 b is ignored
*/
localparam NUM_BYTES=(PAYLOAD_BITS+21)>>3;
localparam ALIGNED_STATUS_WIDTH=((NUM_BYTES-2)<<3)+2; // 2 ->2,
// ugly solution to avoid warnings in unused branch
localparam ALIGNED_STATUS_BIT_2=(ALIGNED_STATUS_WIDTH>2)?2:0;
reg [1:0] mode;
reg [5:0] seq;
reg [PAYLOAD_BITS-1:0] status_r; // "frozen" status to be sent;
reg status_changed_r; // not reset if status changes back to original
reg cmd_pend;
reg [((NUM_BYTES-1)<<3)-1:0] data;
wire snd_rest;
wire need_to_send;
wire [ALIGNED_STATUS_WIDTH-1:0] aligned_status;
reg [NUM_BYTES-2:0] rq_r;
assign aligned_status=(ALIGNED_STATUS_WIDTH==PAYLOAD_BITS)?status:{{(ALIGNED_STATUS_WIDTH-PAYLOAD_BITS){1'b0}},status};
assign ad=data[7:0];
assign need_to_send=cmd_pend || (mode[1] && status_changed_r); // latency
assign rq=rq_r[0]; // NUM_BYTES-2];
assign snd_rest=rq_r[0] && !rq_r[NUM_BYTES-2];
always @ (posedge rst or posedge clk) begin
if (rst) status_changed_r <= 0;
else status_changed_r <= (status_changed_r && !start) || (status_r != status);
if (rst) mode <= 0;
else if (we) mode <= wd[7:6];
if (rst) seq <= 0;
else if (we) seq <= wd[5:0];
else if ((mode==3) && start) seq <= seq+1;
if (rst) cmd_pend <= 0;
else if (we) cmd_pend <= 1;
else if (start) cmd_pend <= 0;
if (rst) status_r<=0;
else if (start) status_r<=status;
if (rst) data <= STATUS_REG_ADDR;
else if (start) data <= (NUM_BYTES>2)?
{aligned_status[ALIGNED_STATUS_WIDTH-1:ALIGNED_STATUS_BIT_2],seq,status[1:0]}:
{seq,status[1:0]};
else if ((NUM_BYTES>2) && snd_rest) data <= data >> 8; // never happens with 2-byte packet
else data <= STATUS_REG_ADDR;
if (rst) rq_r <= 0;
else if (need_to_send && !rq_r[0]) rq_r <= {NUM_BYTES-1{1'b1}};
else if (start || ((NUM_BYTES>2) && !rq_r[NUM_BYTES-2])) rq_r <= rq_r >> 1;
end
endmodule
/*******************************************************************************
* Module: status_read
* Date:2015-01-14
* Author: andrey
* Description: Receives status read data (low bandwidth) from multiple
* subsystems byte-serial, stores in axi-addressable memory
* 8-bita ddress is received from the source module,
* as well as another (optional) byte of sequence number (set in write command)
* Sequence number (received first afther the address) is stored as a high byte,
* lower bytes are the actual payload, starting from lower byte (not all 3 are
* required. Single-bit responsen can be combined in the same byte with the
* sequence number to use just 2-byte packets?
* TODO: add interrupt capabilities
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* status_read.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.
*
* status_read.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 <http://www.gnu.org/licenses/> .
*******************************************************************************/
`timescale 1ns/1ps
module status_read#(
parameter STATUS_ADDR = 'h1400, // AXI write address of status read registers
parameter STATUS_ADDR_MASK = 'h1400, // AXI write address of status registers
parameter AXI_RD_ADDR_BITS = 13,
parameter integer DATA_DEPTH= 8 // 256 cells, maybe just 16..64 are enough?
)(
input rst,
input clk,
input [AXI_RD_ADDR_BITS-1:0] axi_pre_addr, // status read address, 1 cycle ahead of read data
input pre_stb, // read data request, with axi_pre_addr
output reg [31:0] axi_status_rdata, // read data, 1 cycle latency from the address/stb
output reg data_valid, // read data valid, 1 cycle latency from pre_stb, decoded address
input [7:0] ad, // byte-serial status data from the sources
input rq, // request from sources to transfer status data
output start // acknowledge receiving of first byte (address), currently always ready
);
localparam integer DATA_2DEPTH=(1<<DATA_DEPTH)-1;
reg [31:0] ram [0:DATA_2DEPTH];
reg [DATA_DEPTH-1:0] waddr;
wire [DATA_DEPTH-1:0] raddr;
reg we;
wire re;
reg [31: 0] wdata;
reg rq_r;
reg [3:0] dstb;
assign re= pre_stb && (((axi_pre_addr ^ STATUS_ADDR) & STATUS_ADDR_MASK) == 0);
assign raddr=axi_pre_addr[DATA_DEPTH-1:0];
assign start=rq && !rq_r;
always @ (posedge rst or posedge clk) begin
if (rst) data_valid <= 0;
else data_valid <= re;
if (rst) rq_r <= 0;
else rq_r <= rq;
if (rst) dstb <= 0;
else if (!rq) dstb <= 0;
else dstb <= {dstb[2:0],~rq_r};
// byte 0 - address
if (rst) waddr <= 0;
else if (start) waddr <= ad[DATA_DEPTH-1:0];
// byte 1 - 2 payload bits and sequence number
// 6 bits of the sequence number will go to bits 26.. 31
// 2 bits (24,25) are payload status
if (rst) wdata[31:24] <= 0;
else if (start) wdata[31:24] <= 0;
else if (dstb[0]) wdata[31:24] <= ad;
// byte 2 - payload bits 0..7
if (rst) wdata[ 7: 0] <= 0;
else if (start) wdata[ 7: 0] <= 0;
else if (dstb[1]) wdata[ 7: 0] <= ad;
// byte 3 - payload bits 8..15
if (rst) wdata[15: 8] <= 0;
else if (start) wdata[15: 8] <= 0;
else if (dstb[2]) wdata[15: 8] <= ad;
// byte 4 - payload bits 16..23
if (rst) wdata[23:16] <= 0;
else if (start) wdata[23:16] <= 0;
else if (dstb[3]) wdata[23:16] <= ad;
if (rst) we <= 0;
else we <= !rq && rq_r;
end
always @ (posedge clk) begin
if (we) ram[waddr] <= wdata; // shifted data here
if (re) axi_status_rdata<= ram[raddr];
end
endmodule
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment