Commit 2ec40de8 authored by Andrey Filippov's avatar Andrey Filippov

started status read infrastucture

parent 10e88af6
...@@ -24,14 +24,25 @@ module cmd_mux #( ...@@ -24,14 +24,25 @@ module cmd_mux #(
parameter AXI_WR_ADDR_BITS= 13, parameter AXI_WR_ADDR_BITS= 13,
parameter CONTROL_ADDR = 'h1000, // AXI write address of control write registers parameter CONTROL_ADDR = 'h1000, // AXI write address of control write registers
parameter CONTROL_ADDR_MASK = 'h1400, // AXI write address of control registers parameter CONTROL_ADDR_MASK = 'h1400, // AXI write address of control registers
// parameter CONTROL_SS_ADDR= 'h0200, // single-cycle command (2-6 cycles decoded by ROM form some address bits) parameter NUM_CYCLES_LOW_BIT= 6, // decode addresses [NUM_CYCLES_LOW_BIT+:4] into command a/d length
// parameter CONTROL_SS_MASK= 'h0200, parameter NUM_CYCLES_00 = 9, // single-cycle
parameter NUM_CYCLES_LOW_BIT= 6 // decode addresses [NUM_CYCLES_LOW_BIT+:4] into command a/d length parameter NUM_CYCLES_01 = 2, // 2-cycle
// now all control addresses may generate busy, but only for command sequencer and multy-byte commands parameter NUM_CYCLES_02 = 3, // 3-cycle
// parameter BUSY_WR_ADDR = 'h1800, // AXI write address to generate busy parameter NUM_CYCLES_03 = 4, // 4-cycle
// parameter BUSY_WR_ADDR_MASK = 'h1c00 // AXI write address mask to generate busy parameter NUM_CYCLES_04 = 5, // 5-cycle
parameter NUM_CYCLES_05 = 6, // 6-cycle
parameter NUM_CYCLES_06 = 6, //
parameter NUM_CYCLES_07 = 6, //
parameter NUM_CYCLES_08 = 6, //
parameter NUM_CYCLES_09 = 6, //
parameter NUM_CYCLES_10 = 6, //
parameter NUM_CYCLES_11 = 6, //
parameter NUM_CYCLES_12 = 6, //
parameter NUM_CYCLES_13 = 6, //
parameter NUM_CYCLES_14 = 6, //
parameter NUM_CYCLES_15 = 6 //
) ( ) (
input clk, input axi_clk,
input mclk, input mclk,
input rst, input rst,
// direct commands from AXI. No wait but for multi-cycle output and command sequencer (having higher priority) // direct commands from AXI. No wait but for multi-cycle output and command sequencer (having higher priority)
...@@ -86,7 +97,7 @@ module cmd_mux #( ...@@ -86,7 +97,7 @@ module cmd_mux #(
assign seq_length_rom_a=par_ad[NUM_CYCLES_LOW_BIT+:4]; assign seq_length_rom_a=par_ad[NUM_CYCLES_LOW_BIT+:4];
assign ss= seq_length[3]; assign ss= seq_length[3];
always @ (posedge clk or posedge rst) begin always @ (posedge axi_clk or posedge rst) begin
if (rst) selected <= 1'b0; if (rst) selected <= 1'b0;
else if (start_wburst) selected <= selected_w; else if (start_wburst) selected <= selected_w;
if (rst) busy_r <= 1'b0; if (rst) busy_r <= 1'b0;
...@@ -97,22 +108,22 @@ module cmd_mux #( ...@@ -97,22 +108,22 @@ module cmd_mux #(
// always @ (seq_length_rom_a) begin // always @ (seq_length_rom_a) begin
always @* always @*
case (seq_length_rom_a) // just temporary - fill out later case (seq_length_rom_a) // just temporary - fill out later
4'h00:seq_length<=9; // single-cycle 4'h00:seq_length <= NUM_CYCLES_00;
4'h01:seq_length<=2; // 2-cycle 4'h01:seq_length <= NUM_CYCLES_01;
4'h02:seq_length<=3; 4'h02:seq_length <= NUM_CYCLES_02;
4'h03:seq_length<=4; 4'h03:seq_length <= NUM_CYCLES_03;
4'h04:seq_length<=5; 4'h04:seq_length <= NUM_CYCLES_04;
4'h05:seq_length<=6; // 6-cycle (full) 4'h05:seq_length <= NUM_CYCLES_05;
4'h06:seq_length<=6; 4'h06:seq_length <= NUM_CYCLES_06;
4'h07:seq_length<=6; 4'h07:seq_length <= NUM_CYCLES_07;
4'h08:seq_length<=6; 4'h08:seq_length <= NUM_CYCLES_08;
4'h09:seq_length<=6; 4'h09:seq_length <= NUM_CYCLES_09;
4'h0a:seq_length<=6; 4'h0a:seq_length <= NUM_CYCLES_10;
4'h0b:seq_length<=6; 4'h0b:seq_length <= NUM_CYCLES_11;
4'h0c:seq_length<=6; 4'h0c:seq_length <= NUM_CYCLES_12;
4'h0d:seq_length<=6; 4'h0d:seq_length <= NUM_CYCLES_13;
4'h0e:seq_length<=6; 4'h0e:seq_length <= NUM_CYCLES_14;
4'h0f:seq_length<=6; 4'h0f:seq_length <= NUM_CYCLES_15;
endcase endcase
always @ (posedge rst or posedge mclk) begin always @ (posedge rst or posedge mclk) begin
if (rst) seq_busy_r<=0; if (rst) seq_busy_r<=0;
......
...@@ -104,14 +104,14 @@ module memctrl16 #( ...@@ -104,14 +104,14 @@ module memctrl16 #(
parameter REFRESH_ADDR_REL = 'h033, // address to set sequencer start address for DDR refresh parameter REFRESH_ADDR_REL = 'h033, // address to set sequencer start address for DDR refresh
parameter REFRESH_ADDR_REL_MASK = 'h3ff // address mask set refresh sequencer address parameter REFRESH_ADDR_REL_MASK = 'h3ff // address mask set refresh sequencer address
) ( ) (
input rst, input rst,
input clk, input clk,
input [15:0] want_rq, // both want_rq and need_rq should go inactive after being granted input [15:0] want_rq, // both want_rq and need_rq should go inactive after being granted
input [15:0] need_rq, input [15:0] need_rq,
output [15:0] channel_pgm_en, // channel can program sequence data output [15:0] channel_pgm_en, // channel can program sequence data
input [511:0] seq_data, //16x32 data to be written to the sequencer (and start address for software-based sequencer) input [511:0] seq_data, //16x32 data to be written to the sequencer (and start address for software-based sequencer)
input [15:0] seq_wr, // strobe for writing sequencer data (address is autoincremented) input [15:0] seq_wr, // strobe for writing sequencer data (address is autoincremented)
input [15:0] seq_done, // channel sequencer data is written. If no seq_wr pulses before seq_done, seq_data contains software sequencer start address input [15:0] seq_done, // channel sequencer data is written. If no seq_wr pulses before seq_done, seq_data contains software sequencer start address
// priority programming // priority programming
// TODO: Move to ps7 instance in this module // TODO: Move to ps7 instance in this module
...@@ -136,8 +136,8 @@ module memctrl16 #( ...@@ -136,8 +136,8 @@ module memctrl16 #(
inout NDQSL, // ~LDQS I/O pad inout NDQSL, // ~LDQS I/O pad
output SDDMU, // UDM I/O pad (actually only output) output SDDMU, // UDM I/O pad (actually only output)
inout DQSU, // UDQS I/O pad inout DQSU, // UDQS I/O pad
inout NDQSU, inout NDQSU //,
output DUMMY_TO_KEEP // to keep PS7 signals from "optimization" // output DUMMY_TO_KEEP // to keep PS7 signals from "optimization"
// input MEMCLK // input MEMCLK
); );
// TODO: copy from ddrc_test01.v // TODO: copy from ddrc_test01.v
......
/*******************************************************************************
* Module: fifo_1cycle
* Date:2014-05-20
* Author: Andrey Filippov
* Description: Configurable synchronous FIFO using the same clock for read and write
* Single clock cycle latency - simple fifo using sync in, async out RAM,
* no registers on input and output
* Copyright (c) 2014 Elphel, Inc.
* fifo_1cycle.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.
*
* fifo_1cycle.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
`define DEBUG_FIFO 1
module fifo_1cycle
#(
parameter integer DATA_WIDTH=16,
parameter integer DATA_DEPTH=4
)
(
input rst, // reset, active high
input clk, // clock - positive edge
input we, // write enable
input re, // read enable
input [DATA_WIDTH-1:0] data_in, // input data
output [DATA_WIDTH-1:0] data_out, // output data
output reg nempty, // FIFO has some data
output reg half_full // FIFO half full
`ifdef DEBUG_FIFO
,output reg under, // debug outputs - under - attempt to read from empty
output reg over, // overwritten
output reg [DATA_DEPTH-1:0] wcount,
output reg [DATA_DEPTH-1:0] rcount,
output [DATA_DEPTH-1:0] num_in_fifo
`endif
);
localparam integer DATA_2DEPTH=(1<<DATA_DEPTH)-1;
reg [DATA_DEPTH-1:0] fill=0; // RAM fill
reg [DATA_DEPTH-1:0] ra;
reg [DATA_DEPTH-1:0] wa;
wire [DATA_DEPTH-1:0] next_fill;
reg [DATA_WIDTH-1:0] ram [0:DATA_2DEPTH];
`ifdef DEBUG_FIFO
assign num_in_fifo=fill[DATA_DEPTH-1:0];
`endif
assign next_fill = fill[DATA_DEPTH-1:0]+((we && ~re)?1:((~we && re)?-1:0));
always @ (posedge clk or posedge rst) begin
if (rst) fill <= 0;
else fill <= next_fill;
if (rst) wa <= 0;
else if (we) wa <= wa+1;
if (rst) ra <= 0;
else if (re) ra <= ra+1;
else if (fill==0) ra <= wa; // Just recover from bit errors
if (rst) nempty <= 0;
else nempty <= (next_fill!=0);
`ifdef DEBUG_FIFO
if (rst) wcount <= 0;
else if (we) wcount <= wcount + 1;
if (rst) rcount <= 0;
else if (re) rcount <= rcount + 1;
`endif
end
assign data_out=ram[ra]; // async out
always @ (posedge clk) begin
half_full <=(fill & (1<<(DATA_DEPTH-1)))!=0; // MSB == 1
if (we) ram[wa] <= data_in;
`ifdef DEBUG_FIFO
under <= ~we & re & ~nempty; // underrun error
over <= we & ~re & (fill == (1<< (DATA_DEPTH-1))); // overrun error
`endif
end
endmodule
/*******************************************************************************
* Module: status_router2
* Date:2015-01-13
* Author: andrey
* Description: 2:1 status data router/mux
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* status_router2.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_router2.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/> .
*******************************************************************************/
//TODO: make a 4-input mux too?
`timescale 1ns/1ps
`define DEBUG_FIFO 1
module status_router2 (
input rst,
input clk,
// 2 input channels
input [7:0] db_in0,
input rq_in0,
output start_in0, // only for the first cycle, combinatorial
input [7:0] db_in1,
input rq_in1,
output start_in1, // only for the first cycle, combinatorial
// output (multiplexed) channel
output [7:0] db_out,
output rq_out,
input start_out // only for the first cycle, combinatorial
);
wire [1:0] rq_in={rq_in1,rq_in0};
wire [1:0] start_rcv;
reg [1:0] rcv_rest_r; // receiving remaining (after first) bytes
wire [1:0] fifo_half_full;
assign start_in0=start_rcv[0];
assign start_in1=start_rcv[1];
assign start_rcv=~fifo_half_full & ~rcv_rest_r & rq_in;
wire [7:0] fifo0_out;
wire [7:0] fifo1_out;
wire [1:0] fifo_last_byte;
wire [1:0] fifo_nempty;
wire [1:0] fifo_re;
reg next_chn;
reg current_chn_r;
reg snd_rest_r;
wire snd_pre_start;
wire snd_last_byte;
wire chn_sel_w;
wire early_chn;
assign chn_sel_w=(&fifo_nempty)?next_chn:&fifo_nempty[1];
assign fifo_re=start_out?{chn_sel_w,~chn_sel_w}:(snd_rest_r?{current_chn_r,~current_chn_r}:2'b0);
assign snd_last_byte=current_chn_r?fifo_last_byte[1]:fifo_last_byte[0];
assign snd_pre_start=|fifo_nempty && (!snd_rest_r || snd_last_byte);
assign rq_out=(snd_rest_r && !snd_last_byte) || |fifo_nempty;
assign early_chn= (snd_rest_r & ~snd_last_byte)?current_chn_r:chn_sel_w;
assign db_out=early_chn?fifo1_out:fifo0_out;
always @ (posedge rst or posedge clk) begin
if (rst) rcv_rest_r<= 0;
else rcv_rest_r <= (rcv_rest_r & rq_in) | start_rcv;
if (rst) next_chn<= 0;
else if (|fifo_re) next_chn <= fifo_re[0];
if (rst) current_chn_r<= 0;
else if (snd_pre_start) current_chn_r <= chn_sel_w;
if (rst) snd_rest_r<= 0;
else snd_rest_r <= (snd_rest_r & ~snd_last_byte) | start_out;
end
/* fifo_same_clock has currently latency of 2 cycles, use smth. faster here? - fifo_1cycle (but it has unregistered data output) */
fifo_1cycle #(
.DATA_WIDTH(9),
.DATA_DEPTH(4) // 16
) fifo_in0_i (
.rst (rst), // input
.clk (clk), // input
.we (start_rcv[0] || rcv_rest_r[0]), // input
.re (fifo_re[0]), // input
.data_in ({rcv_rest_r[0] & ~rq_in[0], db_in0}), // input[8:0] MSB marks last byte
.data_out ({fifo_last_byte[0],fifo0_out}), // output[8:0]
.nempty (fifo_nempty[0]), // output
.half_full (fifo_half_full[0]) // output reg
`ifdef DEBUG_FIFO
,.under(), // output reg
.over(), // output reg
.wcount(), // output[3:0] reg
.rcount(), // output[3:0] reg
.num_in_fifo() // output[3:0]
`endif
);
fifo_1cycle #(
.DATA_WIDTH(9),
.DATA_DEPTH(4) // 16
) fifo_in1_i (
.rst (rst), // input
.clk (clk), // input
.we (start_rcv[1] || rcv_rest_r[1]), // input
.re (fifo_re[1]), // input
.data_in ({rcv_rest_r[1] & ~rq_in[1], db_in1}), // input[8:0] MSB marks last byte
.data_out ({fifo_last_byte[1],fifo1_out}), // output[8:0]
.nempty (fifo_nempty[1]), // output
.half_full (fifo_half_full[1]) // output reg
`ifdef DEBUG_FIFO
,.under(), // output reg
.over(), // output reg
.wcount(), // output[3:0] reg
.rcount(), // output[3:0] reg
.num_in_fifo() // output[3:0]
`endif
);
// one car per green (round robin priority)
// start sending out with with one cycle latency - now 2 cycles because of the FIFO
endmodule
This diff is collapsed.
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