Commit 18addecb authored by Andrey Filippov's avatar Andrey Filippov

added status generation module for cmprs_afi_mux

parent d2699ad8
...@@ -21,6 +21,17 @@ ...@@ -21,6 +21,17 @@
`timescale 1ns/1ps `timescale 1ns/1ps
module cmprs_afi_mux#( module cmprs_afi_mux#(
parameter CMPRS_AFIMUX_ADDR= 'h140, //TODO: assign valid adderss
parameter CMPRS_AFIMUX_MASK= 'h3f0,
parameter CMPRS_AFIMUX_EN= 'h0, // enables (gl;obal and per-channel)
parameter CMPRS_AFIMUX_RST= 'h1, // per-channel resets
parameter CMPRS_AFIMUX_MODE= 'h2, // per-channel select - which register to return as status
parameter CMPRS_AFIMUX_STATUS_CNTRL= 'h4, // .. 'h7
parameter CMPRS_AFIMUX_SA_LEN= 'h8, // .. 'hf
parameter CMPRS_AFIMUX_STATUS_REG_ADDR= 'h20, //Uses 4 locations TODO: assign valid adderss
parameter CMPRS_AFIMUX_WIDTH = 26, // maximal for status: currently only works with 26)
parameter CMPRS_AFIMUX_CYCBITS = 3,
parameter AFI_MUX_BUF_LATENCY = 2 // buffers read latency from fifo_ren* to fifo_rdata* valid : 2 if no register layers are used parameter AFI_MUX_BUF_LATENCY = 2 // buffers read latency from fifo_ren* to fifo_rdata* valid : 2 if no register layers are used
)( )(
input rst, input rst,
...@@ -100,12 +111,33 @@ module cmprs_afi_mux#( ...@@ -100,12 +111,33 @@ module cmprs_afi_mux#(
output afi_wrissuecap1en output afi_wrissuecap1en
); );
reg en; // enable mux reg en; // enable mux
reg en_d; reg en_d; // or use it to reset all channels?
reg [3:0] en_chn; // per-channel enable reg [3:0] en_chn; // per-channel enable
wire [31:0] cmd_data; wire [31:0] cmd_data;
wire [ 3:0] cmd_a; wire [ 3:0] cmd_a;
wire cmd_we_sa_len; wire cmd_we;
wire cmd_we_status_w;
wire cmd_we_mode_w;
wire cmd_we_sa_len_w;
wire cmd_we_en_w;
wire cmd_we_rst_w;
reg [26:0] sa_len_d;
reg [2:0] sa_len_wa;
reg [3:0] rst_mclk;
reg [9:0] en_mclk;
// hclk domain
// reg [26:0] sa_len_d;
// reg [2:0] sa_len_wa;
wire sa_len_we;
wire en_we;
wire en_rst;
// reg [2:0] cur_chn; // 'b0xx - none, 'b1** - ** - channel number (should match fifo_ren*) // reg [2:0] cur_chn; // 'b0xx - none, 'b1** - ** - channel number (should match fifo_ren*)
reg [1:0] cur_chn; // 'b0xx - none, 'b1** - ** - channel number (should match fifo_ren*) reg [1:0] cur_chn; // 'b0xx - none, 'b1** - ** - channel number (should match fifo_ren*)
...@@ -138,7 +170,7 @@ module cmprs_afi_mux#( ...@@ -138,7 +170,7 @@ module cmprs_afi_mux#(
reg [3:0] wleft; // number of 64-bit words left to be sent - also used as awlen (valid @ awvalid) reg [3:0] wleft; // number of 64-bit words left to be sent - also used as awlen (valid @ awvalid)
reg [2:0] chunk_inc; // how much to increment chunk pointer (1..4) reg [2:0] chunk_inc; // how much to increment chunk pointer (1..4)
wire [ 3:0] reset_pointers; // per-channel - after chunk_start_hclk or chunk_len_hclk were written or explicit fifo_rst* reg [ 3:0] reset_pointers; // per-channel - after chunk_start_hclk or chunk_len_hclk were written or explicit fifo_rst*
wire ptr_resetting; // pointers are being reset in cmprs_afi_mux_ptr module wire ptr_resetting; // pointers are being reset in cmprs_afi_mux_ptr module
...@@ -157,6 +189,16 @@ module cmprs_afi_mux#( ...@@ -157,6 +189,16 @@ module cmprs_afi_mux#(
assign cmd_we_status_w = cmd_we && ((cmd_a & 'hc) == CMPRS_AFIMUX_STATUS_CNTRL);
assign cmd_we_mode_w = cmd_we && (cmd_a == CMPRS_AFIMUX_MODE);
assign cmd_we_sa_len_w = cmd_we && ((cmd_a & 'h8) == CMPRS_AFIMUX_SA_LEN);
assign cmd_we_en_w = cmd_we && (cmd_a == CMPRS_AFIMUX_EN);
assign cmd_we_rst_w = cmd_we && (cmd_a == CMPRS_AFIMUX_RST);
// use last_chunk_w to apply a special id to waddr and wdata and watch for it during readout // use last_chunk_w to apply a special id to waddr and wdata and watch for it during readout
// compose ID of channel number, frame bumber LSBs and last/not last chunk // compose ID of channel number, frame bumber LSBs and last/not last chunk
assign last_chunk_w[3:0] = {(left_to_eof[3]==1)?1'b1:1'b0, assign last_chunk_w[3:0] = {(left_to_eof[3]==1)?1'b1:1'b0,
...@@ -186,6 +228,24 @@ module cmprs_afi_mux#( ...@@ -186,6 +228,24 @@ module cmprs_afi_mux#(
assign afi_wstrb = 8'hff; assign afi_wstrb = 8'hff;
assign afi_wrissuecap1en = 1'b0; assign afi_wrissuecap1en = 1'b0;
always @ (posedge mclk) begin
if (cmd_we_sa_len_w) begin
sa_len_d <= cmd_data[26:0];
sa_len_wa <= cmd_a[2:0];
end
if (cmd_we_en_w) en_mclk <= cmd_data[9:0];
if (cmd_we_rst_w) rst_mclk <= cmd_data[3:0];
end
always @ (posedge hclk) begin
reset_pointers <= (en && !en_d)? 4'hf : (en_rst ? rst_mclk : 4'h0);
if (en_we && en_mclk[1]) en_chn[0] <= en_mclk[0];
if (en_we && en_mclk[3]) en_chn[1] <= en_mclk[2];
if (en_we && en_mclk[5]) en_chn[2] <= en_mclk[4];
if (en_we && en_mclk[7]) en_chn[3] <= en_mclk[6];
if (en_we && en_mclk[9]) en <= en_mclk[8];
end
always @ (posedge hclk) begin always @ (posedge hclk) begin
en_d <= en; en_d <= en;
...@@ -319,13 +379,30 @@ module cmprs_afi_mux#( ...@@ -319,13 +379,30 @@ module cmprs_afi_mux#(
.dout ({wdata_en,wdata_sel}) // output[0:0] .dout ({wdata_en,wdata_sel}) // output[0:0]
); );
cmd_deser #(
.ADDR (CMPRS_AFIMUX_ADDR),
.ADDR_MASK (CMPRS_AFIMUX_MASK),
.NUM_CYCLES (6),
.ADDR_WIDTH (4),
.DATA_WIDTH (32)
) cmd_deser_32bit_i (
.rst (rst), // input
.clk (mclk), // 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
);
wire [26:0] chunk_ptr_rd01[0:1]; wire [26:0] chunk_ptr_rd01[0:1];
cmprs_afi_mux_ptr cmprs_afi_mux_ptr_i ( cmprs_afi_mux_ptr cmprs_afi_mux_ptr_i (
.hclk (hclk), // input .hclk (hclk), // input
.sa_len_di (cmd_data[26:0]), // input[26:0] .sa_len_di (sa_len_d[26:0]), // input[26:0]
.sa_len_wa (cmd_a[2:0]), // input[2:0] .sa_len_wa (sa_len_wa[2:0]), // input[2:0]
.sa_len_we (cmd_we_sa_len), // input .sa_len_we (sa_len_we), // input
.en (en), // input .en (en), // input
.reset_pointers (reset_pointers), // input[3:0] .reset_pointers (reset_pointers), // input[3:0]
.pre_busy_w (pre_busy_w), // input .pre_busy_w (pre_busy_w), // input
...@@ -342,9 +419,9 @@ module cmprs_afi_mux#( ...@@ -342,9 +419,9 @@ module cmprs_afi_mux#(
assign chunk_ptr_rd=chunk_ptr_ra[3]?chunk_ptr_rd01[1]:chunk_ptr_rd01[0]; assign chunk_ptr_rd=chunk_ptr_ra[3]?chunk_ptr_rd01[1]:chunk_ptr_rd01[0];
cmprs_afi_mux_ptr_wresp cmprs_afi_mux_ptr_wresp_i ( cmprs_afi_mux_ptr_wresp cmprs_afi_mux_ptr_wresp_i (
.hclk (hclk), // input .hclk (hclk), // input
.length_di (cmd_data[26:0]), // input[26:0] .length_di (sa_len_d[26:0]), // input[26:0]
.length_wa (cmd_a[1:0]), // input[1:0] .length_wa (sa_len_wa[1:0]), // input[1:0]
.length_we (cmd_we_sa_len & cmd_a[2]), // input .length_we (sa_len_we & sa_len_wa[2]), // input
.en (en), // input .en (en), // input
.reset_pointers (reset_pointers), // input[3:0] .reset_pointers (reset_pointers), // input[3:0]
.chunk_ptr_ra (chunk_ptr_ra[2:0]), // input[2:0] .chunk_ptr_ra (chunk_ptr_ra[2:0]), // input[2:0]
...@@ -355,6 +432,28 @@ module cmprs_afi_mux#( ...@@ -355,6 +432,28 @@ module cmprs_afi_mux#(
.afi_bid (afi_bid) // input[5:0] .afi_bid (afi_bid) // input[5:0]
); );
/* Instance template for module cmprs_afi_mux_status */
cmprs_afi_mux_status #(
.CMPRS_AFIMUX_STATUS_REG_ADDR (CMPRS_AFIMUX_STATUS_REG_ADDR),
.CMPRS_AFIMUX_WIDTH(CMPRS_AFIMUX_WIDTH),
.CMPRS_AFIMUX_CYCBITS(CMPRS_AFIMUX_CYCBITS)
) cmprs_afi_mux_status_i (
.rst (rst), // input
.hclk (hclk), // input
.mclk (mclk), // input
.cmd_data (cmd_data[15:0]), // input[15:0]
.cmd_a (cmd_a[1:0]), // input[1:0]
.status_we (cmd_we_status_w), // input
.mode_we (cmd_we_mode_w), // input
.status_ad (status_ad), // output[7:0]
.status_rq (status_rq), // output
.status_start (status_start), // input
.en (en), // input
.chunk_ptr_ra (chunk_ptr_ra), // output[3:0] reg
.chunk_ptr_rd (chunk_ptr_rd[CMPRS_AFIMUX_WIDTH-1:0]) // input[25:0]
);
pulse_cross_clock sa_len_we_i (.rst(rst), .src_clk(mclk), .dst_clk(hclk), .in_pulse(cmd_we_sa_len_w), .out_pulse(sa_len_we),.busy());
pulse_cross_clock en_we_i (.rst(rst), .src_clk(mclk), .dst_clk(hclk), .in_pulse(cmd_we_en_w), .out_pulse(en_we), .busy());
pulse_cross_clock en_rst_i (.rst(rst), .src_clk(mclk), .dst_clk(hclk), .in_pulse(cmd_we_rst_w), .out_pulse(en_rst),.busy());
endmodule endmodule
/*******************************************************************************
* Module: cmprs_afi_mux_status
* Date:2015-06-28
* Author: andrey
* Description: prepare and send per-channel chunk pointer information as status
* Using 4 consecutive locations. Each channel can provide one of the 4 pointers:
* frame pointer in the write channel, current chunk pointer in the write channel
* and the same for the write response channel (confirmed written to the system
* memory
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* cmprs_afi_mux_status.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.
*
* cmprs_afi_mux_status.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 cmprs_afi_mux_status #(
parameter CMPRS_AFIMUX_STATUS_REG_ADDR= 'h20, //Uses 4 locations TODO: assign valid adderss
parameter CMPRS_AFIMUX_WIDTH = 26, // maximal for status: currently only works with 26)
parameter CMPRS_AFIMUX_CYCBITS = 3
) (
input rst,
input hclk, // global clock to run axi_hp @ 150MHz, shared by all compressor channels
input mclk, // for command/status
// mclk domain
input [15:0] cmd_data, //
input [ 1:0] cmd_a, //
input status_we, //
input mode_we, //
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)
// hclk domain
input en, // 1- enable, 0 - reset
output reg [3:0] chunk_ptr_ra, // full pointer address - {eof,wresp,chn[1:0]}
input [CMPRS_AFIMUX_WIDTH-1:0] chunk_ptr_rd // pointer data
);
reg [15:0] mode_data_mclk; // some bits unused
wire mode_we_hclk;
reg [7:0] mode_hclk;
// wire [1:0] sel[0:3]={mode_hclk[7:6],mode_hclk[5:4],mode_hclk[3:2],mode_hclk[1:0]};
reg [1:0] index;
reg [CMPRS_AFIMUX_CYCBITS-1:0] cntr;
reg [CMPRS_AFIMUX_WIDTH-1:0] chunk_ptr_hclk; // pointer data
reg [1:0] chunk_chn_hclk; // pointer channel
reg [CMPRS_AFIMUX_WIDTH-1:0] status_data[0:3];
wire stb_w;
reg stb_r;
wire stb_mclk;
wire [7:0] ad[0:3];
wire [3:0] rq;
wire [3:0] start;
assign stb_w = en && (cntr==0);
always @ (posedge mclk) begin
if (mode_we) mode_data_mclk <= cmd_data[15:0];
end
always @ (posedge hclk) begin
if (mode_we_hclk) begin
if (mode_data_mclk[ 2]) mode_hclk[1:0] <= mode_data_mclk[ 1: 0];
if (mode_data_mclk[ 6]) mode_hclk[3:2] <= mode_data_mclk[ 5: 4];
if (mode_data_mclk[10]) mode_hclk[5:4] <= mode_data_mclk[ 9: 8];
if (mode_data_mclk[14]) mode_hclk[7:6] <= mode_data_mclk[13:12];
if (stb_mclk) status_data[chunk_chn_hclk] <= chunk_ptr_hclk;
end
if (!en) {index,cntr} <= 0;
else {index,cntr} <= {index,cntr} + 1;
if (stb_w) begin
chunk_ptr_ra[1:0] <= index;
case (index)
2'h0: chunk_ptr_ra[3:2] <= mode_hclk[1:0] ^ 1; // so 0 will be eof, internal
2'h1: chunk_ptr_ra[3:2] <= mode_hclk[3:2] ^ 1;
2'h2: chunk_ptr_ra[3:2] <= mode_hclk[5:4] ^ 1;
2'h3: chunk_ptr_ra[3:2] <= mode_hclk[7:6] ^ 1;
endcase
end
stb_r <= stb_w;
if (stb_r) begin
chunk_ptr_hclk <= {chunk_ptr_rd[23:0],chunk_ptr_rd[25:24]}; // bits 0,1 are sent to 25:24
chunk_chn_hclk <= index;
end
end
pulse_cross_clock mode_we_hclk_i (.rst(rst), .src_clk(mclk), .dst_clk(hclk), .in_pulse(mode_we), .out_pulse(mode_we_hclk),.busy());
pulse_cross_clock stb_mclk_i (.rst(rst), .src_clk(hclk), .dst_clk(mclk), .in_pulse(stb_r), .out_pulse(stb_mclk), .busy());
status_router4 status_router4_i (
.rst (rst), // input
.clk (mclk), // input
.db_in0 (ad[0]), // input[7:0]
.rq_in0 (rq[0]), // input
.start_in0 (start[0]), // output
.db_in1 (ad[1]), // input[7:0]
.rq_in1 (rq[1]), // input
.start_in1 (start[1]), // output
.db_in2 (ad[2]), // input[7:0]
.rq_in2 (rq[2]), // input
.start_in2 (start[2]), // output
.db_in3 (ad[3]), // input[7:0]
.rq_in3 (rq[3]), // input
.start_in3 (start[3]), // output
.db_out (status_ad), // output[7:0]
.rq_out (status_rq), // output
.start_out (status_start) // input
);
status_generate #(
.STATUS_REG_ADDR (CMPRS_AFIMUX_STATUS_REG_ADDR+0),
.PAYLOAD_BITS (CMPRS_AFIMUX_WIDTH)
) status_generate0_i (
.rst (rst), // input
.clk (mclk), // input
.we (status_we && (cmd_a==0)), // input
.wd (cmd_data[7:0]), // input[7:0]
.status (status_data[0]), // input[25:0]
.ad (ad[0]), // output[7:0]
.rq (rq[0]), // output
.start (start[0]) // input
);
status_generate #(
.STATUS_REG_ADDR (CMPRS_AFIMUX_STATUS_REG_ADDR+0),
.PAYLOAD_BITS (CMPRS_AFIMUX_WIDTH)
) status_generate1_i (
.rst (rst), // input
.clk (mclk), // input
.we (status_we && (cmd_a==1)), // input
.wd (cmd_data[7:0]), // input[7:0]
.status (status_data[1]), // input[25:0]
.ad (ad[1]), // output[7:0]
.rq (rq[1]), // output
.start (start[1]) // input
);
status_generate #(
.STATUS_REG_ADDR (CMPRS_AFIMUX_STATUS_REG_ADDR+0),
.PAYLOAD_BITS (CMPRS_AFIMUX_WIDTH)
) status_generate2_i (
.rst (rst), // input
.clk (mclk), // input
.we (status_we && (cmd_a==2)), // input
.wd (cmd_data[7:0]), // input[7:0]
.status (status_data[2]), // input[25:0]
.ad (ad[2]), // output[7:0]
.rq (rq[2]), // output
.start (start[2]) // input
);
status_generate #(
.STATUS_REG_ADDR (CMPRS_AFIMUX_STATUS_REG_ADDR+0),
.PAYLOAD_BITS (CMPRS_AFIMUX_WIDTH)
) status_generate3_i (
.rst (rst), // input
.clk (mclk), // input
.we (status_we && (cmd_a==3)), // input
.wd (cmd_data[7:0]), // input[7:0]
.status (status_data[3]), // input[25:0]
.ad (ad[3]), // output[7:0]
.rq (rq[3]), // output
.start (start[3]) // input
);
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