Commit 880f7615 authored by Andrey Filippov's avatar Andrey Filippov

added interrupts simulation, fixing circbuf pointers rollover bug

parent 374d7837
......@@ -62,52 +62,52 @@
<link>
<name>vivado_logs/VivadoBitstream.log</name>
<type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoBitstream-20160504204346976.log</location>
<location>/home/andrey/git/x393/vivado_logs/VivadoBitstream-20160507151954677.log</location>
</link>
<link>
<name>vivado_logs/VivadoOpt.log</name>
<type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoOpt-20160504204346976.log</location>
<location>/home/andrey/git/x393/vivado_logs/VivadoOpt-20160507151954677.log</location>
</link>
<link>
<name>vivado_logs/VivadoOptPhys.log</name>
<type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoOptPhys-20160504204346976.log</location>
<location>/home/andrey/git/x393/vivado_logs/VivadoOptPhys-20160507151954677.log</location>
</link>
<link>
<name>vivado_logs/VivadoOptPower.log</name>
<type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoOptPower-20160504204346976.log</location>
<location>/home/andrey/git/x393/vivado_logs/VivadoOptPower-20160507151954677.log</location>
</link>
<link>
<name>vivado_logs/VivadoPlace.log</name>
<type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoPlace-20160504204346976.log</location>
<location>/home/andrey/git/x393/vivado_logs/VivadoPlace-20160507151954677.log</location>
</link>
<link>
<name>vivado_logs/VivadoRoute.log</name>
<type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoRoute-20160504204346976.log</location>
<location>/home/andrey/git/x393/vivado_logs/VivadoRoute-20160507151954677.log</location>
</link>
<link>
<name>vivado_logs/VivadoSynthesis.log</name>
<type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoSynthesis-20160504203656004.log</location>
<location>/home/andrey/git/x393/vivado_logs/VivadoSynthesis-20160507151111576.log</location>
</link>
<link>
<name>vivado_logs/VivadoTimimgSummaryReportImplemented.log</name>
<type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoTimimgSummaryReportImplemented-20160504204346976.log</location>
<location>/home/andrey/git/x393/vivado_logs/VivadoTimimgSummaryReportImplemented-20160507151954677.log</location>
</link>
<link>
<name>vivado_logs/VivadoTimimgSummaryReportSynthesis.log</name>
<type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoTimimgSummaryReportSynthesis-20160504203656004.log</location>
<location>/home/andrey/git/x393/vivado_logs/VivadoTimimgSummaryReportSynthesis-20160507151111576.log</location>
</link>
<link>
<name>vivado_logs/VivadoTimingReportSynthesis.log</name>
<type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoTimingReportSynthesis-20160504203656004.log</location>
<location>/home/andrey/git/x393/vivado_logs/VivadoTimingReportSynthesis-20160507151111576.log</location>
</link>
<link>
<name>vivado_state/x393-opt-phys.dcp</name>
......@@ -127,7 +127,7 @@
<link>
<name>vivado_state/x393-synth.dcp</name>
<type>1</type>
<location>/home/andrey/git/x393/vivado_state/x393-synth-20160504203656004.dcp</location>
<location>/home/andrey/git/x393/vivado_state/x393-synth-20160507151111576.dcp</location>
</link>
</linkedResources>
</projectDescription>
com.elphel.store.context.iverilog=iverilog_81_TopModulesOther<-@\#\#@->iverilog_83_ExtraFiles<-@\#\#@->iverilog_88_ShowNoProblem<-@\#\#@->iverilog_77_Param_Exe<-@\#\#@->iverilog_78_VVP_Exe<-@\#\#@->iverilog_99_GrepFindErrWarn<-@\#\#@->iverilog_84_IncludeDir<-@\#\#@->iverilog_89_ShowNoProblem<-@\#\#@->iverilog_79_GtkWave_Exe<-@\#\#@->iverilog_98_GTKWaveSavFile<-@\#\#@->iverilog_100_TopModulesOther<-@\#\#@->iverilog_102_ExtraFiles<-@\#\#@->iverilog_103_IncludeDir<-@\#\#@->iverilog_101_TopModulesOther<-@\#\#@->iverilog_103_ExtraFiles<-@\#\#@->iverilog_104_IncludeDir<-@\#\#@->iverilog_113_SaveLogsSimulator<-@\#\#@->iverilog_109_ShowNoProblem<-@\#\#@->iverilog_110_ShowWarnings<-@\#\#@->iverilog_102_TopModulesOther<-@\#\#@->iverilog_104_ExtraFiles<-@\#\#@->iverilog_105_IncludeDir<-@\#\#@->iverilog_110_ShowNoProblem<-@\#\#@->iverilog_113_SaveLogsPreprocessor<-@\#\#@->iverilog_121_GrepFindErrWarn<-@\#\#@->iverilog_114_SaveLogsSimulator<-@\#\#@->iverilog_103_TopModulesOther<-@\#\#@->iverilog_105_ExtraFiles<-@\#\#@->iverilog_106_IncludeDir<-@\#\#@->iverilog_111_ShowNoProblem<-@\#\#@->iverilog_115_SaveLogsSimulator<-@\#\#@->
com.elphel.store.context.iverilog=iverilog_81_TopModulesOther<-@\#\#@->iverilog_83_ExtraFiles<-@\#\#@->iverilog_88_ShowNoProblem<-@\#\#@->iverilog_77_Param_Exe<-@\#\#@->iverilog_78_VVP_Exe<-@\#\#@->iverilog_99_GrepFindErrWarn<-@\#\#@->iverilog_84_IncludeDir<-@\#\#@->iverilog_89_ShowNoProblem<-@\#\#@->iverilog_79_GtkWave_Exe<-@\#\#@->iverilog_98_GTKWaveSavFile<-@\#\#@->iverilog_100_TopModulesOther<-@\#\#@->iverilog_102_ExtraFiles<-@\#\#@->iverilog_103_IncludeDir<-@\#\#@->iverilog_101_TopModulesOther<-@\#\#@->iverilog_103_ExtraFiles<-@\#\#@->iverilog_104_IncludeDir<-@\#\#@->iverilog_113_SaveLogsSimulator<-@\#\#@->iverilog_109_ShowNoProblem<-@\#\#@->iverilog_110_ShowWarnings<-@\#\#@->iverilog_102_TopModulesOther<-@\#\#@->iverilog_104_ExtraFiles<-@\#\#@->iverilog_105_IncludeDir<-@\#\#@->iverilog_110_ShowNoProblem<-@\#\#@->iverilog_113_SaveLogsPreprocessor<-@\#\#@->iverilog_121_GrepFindErrWarn<-@\#\#@->iverilog_114_SaveLogsSimulator<-@\#\#@->iverilog_103_TopModulesOther<-@\#\#@->iverilog_105_ExtraFiles<-@\#\#@->iverilog_106_IncludeDir<-@\#\#@->iverilog_111_ShowNoProblem<-@\#\#@->iverilog_115_SaveLogsSimulator<-@\#\#@->iverilog_120_GTKWaveSavFile<-@\#\#@->
eclipse.preferences.version=1
iverilog_100_TopModulesOther=glbl<-@\#\#@->
iverilog_101_TopModulesOther=glbl<-@\#\#@->
......@@ -20,6 +20,7 @@ iverilog_113_SaveLogsPreprocessor=false
iverilog_113_SaveLogsSimulator=true
iverilog_114_SaveLogsSimulator=true
iverilog_115_SaveLogsSimulator=true
iverilog_120_GTKWaveSavFile=x393_testbench04.sav
iverilog_121_GrepFindErrWarn=error|warning|sorry
iverilog_77_Param_Exe=/usr/local/bin/iverilog
iverilog_78_VVP_Exe=/usr/local/bin/vvp
......
......@@ -265,6 +265,9 @@ each group of 4 bits per channel : bits [1:0] - select, bit[2] - sset (0 - nop),
// wants to write (want_wleft32+1) 32-byte chunks (4,3,2,1)
wire [1:0] want_wleft32 = (|items_left[7:2])? 2'b11 : items_left[1:0]; // want to set wleft[3:2] if not roll-over (actually "3" means 2)
wire rollover_limited_w = max_wlen[1:0] < want_wleft32;
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);
......@@ -438,8 +441,6 @@ each group of 4 bits per channel : bits [1:0] - select, bit[2] - sset (0 - nop),
//ready_to_start need_to_bother
//done_burst
if (!en) busy <= 0;
// else if (pre_busy_w) busy <= {busy[2:0],1'b1};
// else if (done_burst_w) busy <= 0; // {busy[2:0],1'b0};
else busy <= {busy[2:0], pre_busy_w | (busy[0] & ~done_burst_w)};
if (!en) first_busy <= 0;
......@@ -451,16 +452,11 @@ each group of 4 bits per channel : bits [1:0] - select, bit[2] - sset (0 - nop),
//pend_last
if (!en) wleft <= 0;
/// else if (pre_busy_w) wleft <= {(|items_left[7:2])? 2'b11 : items_left[1:0], 2'b11}; // @@@******* different for roll over
/// else if (pre_busy_w) wleft <= {(max_wlen[2] || (max_wlen[1:0] > want_wleft32))? want_wleft32 : max_wlen[1:0], 2'b11};
else if (pre_busy_w) wleft <= {(max_wlen[1:0] > want_wleft32) ? want_wleft32 : max_wlen[1:0], 2'b11};
else if (wleft != 0) wleft <= wleft - 1;
/*
counts_corr2[8]
items_left
else if (pre_busy_w) wleft <= {(|counts_corr2[7:2])? 2'b11 : left_to_eof[winner2 * 8 +: 2], 2'b11};
// else if (pre_busy_w) wleft <= {(max_wlen[1:0] > want_wleft32) ? want_wleft32 : max_wlen[1:0], 2'b11};
// wire rollover_limited_w = max_wlen[1:0] < want_wleft32;
else if (pre_busy_w) wleft <= {rollover_limited_w ? max_wlen[1:0]: want_wleft32, 2'b11}; // same for ==
else if (wleft != 0) wleft <= wleft - 1;
*/
if (!en) wvalid <= 0;
else if (pre_busy_w) wvalid <= 1;
......@@ -484,8 +480,9 @@ items_left
if (pre_busy_w) begin
cur_chn <= winner2;
// last_burst_in_frame <= last_chunk_w[winner2] && pend_last[winner2];
last_burst_in_frame <= counts_corr2[8] && (left_to_eof[winner2 * 8 + 2 +: 6] == 0) && pend_last[winner2];
// wire rollover_limited_w = max_wlen[1:0] < want_wleft32;
// last_burst_in_frame <= counts_corr2[8] && (left_to_eof[winner2 * 8 + 2 +: 6] == 0) && pend_last[winner2];
last_burst_in_frame <= counts_corr2[8] && (left_to_eof[winner2 * 8 + 2 +: 6] == 0) && pend_last[winner2] &&!rollover_limited_w;
end
wlast <= done_burst_w; // when wleft==4'h1
......
......@@ -45,10 +45,11 @@ module cmprs_afi_mux_ptr(
input [ 3:0] reset_pointers, // per-channel - reset pointers
input pre_busy_w, // combinatorial signal - one before busy[0] (depends on ptr_resetting)
input [ 1:0] winner_channel, // channel that won arbitration for AXI access, valid @ pre_busy_w
input need_to_bother, // whants to start access if address and data FIFO permit
input need_to_bother, // wants to start access if address and data FIFO permit
input [1:0] chunk_inc_want_m1, // how much to increment chunk pointer (0..3) +1 - valid with busy[0] (w/o rollover)
input last_burst_in_frame, // valid with busy[0] (last_burst_in_frame<=last_chunk_w[winner2])
// last_burst_in_frame is invalid when rollover splits burst in 2
input [ 3:0] busy, // one cycle less than sending 1-4 bursts, [1] - delayed by 1, [2] - by 2
output ptr_resetting, // pointers will be reset next cycle (2-cycle-long pulse)
output reg [26:0] chunk_addr, // chunk absolute address, valid with busy[1]
......
......@@ -42,7 +42,7 @@ module cmprs_status #(
input stuffer_running,
input reading_frame,
input [NUM_FRAME_BITS - 1:0] frame_num_compressed,
input set_interrupts,
input set_interrupts, // data = 2: disable, 3 - enable, 1 - reset irq
input [1:0] data_in,
output [NUM_FRAME_BITS+7:0] status,
output irq
......@@ -54,7 +54,7 @@ module cmprs_status #(
reg im_r; // interrupt mask
reg [NUM_FRAME_BITS - 1:0] frame_irq;
assign status = {frame_irq,
assign status = {frame_irq[NUM_FRAME_BITS - 1:0],
3'b0,
flushing_fifo,
stuffer_running_r,
......
......@@ -32,7 +32,8 @@
* with at least one of the Free Software programs.
*******************************************************************************/
parameter FPGA_VERSION = 32'h03930087; // Fixed default 90% quantization table
parameter FPGA_VERSION = 32'h03930088; // Fixing circbuf rollover pointers bug
// parameter FPGA_VERSION = 32'h03930087; // Fixed default 90% quantization table
// parameter FPGA_VERSION = 32'h03930087; // Synchronizing i2c sequencer frame number with that of a command sequencer
// parameter FPGA_VERSION = 32'h03930086; // Adding byte-wide JTAG read to speed-up 10359 load
// parameter FPGA_VERSION = 32'h03930085; // Adding software control for i2c pins when sequencer is stopped, timing matched
......
......@@ -79,25 +79,36 @@
end
endtask
task read_and_wait;
input [31:0] address;
begin
axi_read_addr(
GLOBAL_READ_ID, // id
address & 32'hfffffffc, // addr
4'h0, // len - single
1 // burst type - increment
);
GLOBAL_READ_ID <= GLOBAL_READ_ID+1;
wait (!CLK && rvalid && rready);
wait (CLK);
registered_rdata <= rdata;
wait (!CLK); // registered_rdata should be valid on exit
end
input [31:0] address;
begin
IRQ_EN = 0;
wait (CLK);
while (!MAIN_GO) begin
wait (!CLK);
wait (CLK);
end
axi_read_addr_inner(
GLOBAL_READ_ID, // id
address & 32'hfffffffc, // addr
4'h0, // len - single
1 // burst type - increment
);
GLOBAL_READ_ID <= GLOBAL_READ_ID+1;
wait (!CLK && rvalid && rready);
wait (CLK);
registered_rdata <= rdata;
wait (!CLK); // registered_rdata should be valid on exit
IRQ_EN = 1;
if (IRQS) begin
@(posedge CLK);
@(negedge CLK);
end
end
endtask
task axi_write_single_w; // address in bytes, not words
task axi_write_single_w; // address in dwords
input [29:0] address;
input [31:0] data;
begin
......@@ -129,6 +140,176 @@
endtask
task axi_write_addr_data;
input [11:0] id;
input [31:0] addr;
input [31:0] data;
input [ 3:0] len;
input [ 1:0] burst;
input data_en; // if 0 - do not send data, only address
input [ 3:0] wstrb;
input last;
begin
IRQ_EN = 0;
wait (CLK);
while (!MAIN_GO) begin
wait (!CLK);
wait (CLK);
end
axi_write_addr_data_inner (id, addr, data, len, burst, data_en, wstrb, last);
IRQ_EN = 1;
if (IRQS) begin
@(posedge CLK);
@(negedge CLK);
end
end
endtask
task axi_write_data;
input [11:0] id;
input [31:0] data;
input [ 3:0] wstrb;
input last;
begin
IRQ_EN = 0;
wait (CLK);
while (!MAIN_GO) begin
wait (!CLK);
wait (CLK);
end
axi_write_data_inner (id, data, wstrb, last);
IRQ_EN = 1;
if (IRQS) begin
@(posedge CLK);
@(negedge CLK);
end
end
endtask
// Tasks called from ISR
task read_contol_register_irq;
input [29:0] reg_addr;
output [31:0] rslt;
begin
read_and_wait_w_irq(CONTROL_RBACK_ADDR+reg_addr, rslt);
end
endtask
task read_status_irq;
input [STATUS_DEPTH-1:0] address;
output [31:0] rslt;
begin
read_and_wait_w_irq(STATUS_ADDR + address , rslt);
end
endtask
task read_and_wait_w_irq;
input [29:0] address;
output [31:0] rslt;
begin
read_and_wait_irq ({address,2'b0},rslt);
end
endtask
task read_and_wait_irq;
input [31:0] address;
output reg [31:0] rslt;
begin
axi_read_addr_irq(
GLOBAL_READ_ID, // id
address & 32'hfffffffc, // addr
4'h0, // len - single
1 // burst type - increment
);
GLOBAL_READ_ID <= GLOBAL_READ_ID+1;
wait (!CLK && rvalid && rready);
wait (CLK);
rslt <= rdata;
wait (!CLK); // registered_rdata should be valid on exit
end
endtask
task axi_read_addr_irq; // called ferom the main loop, not from interrupts
input [11:0] id;
input [31:0] addr;
input [ 3:0] len;
input [ 1:0] burst;
begin
// IRQ_EN = 0;
// wait (CLK);
// while (!MAIN_GO) begin
// wait (!CLK);
// wait (CLK);
// end
axi_read_addr_inner (id, addr, len, burst);
// IRQ_EN = 1;
end
endtask
task write_contol_register_irq;
input [29:0] reg_addr;
// input integer reg_addr;
input [31:0] data;
begin
axi_write_single_w_irq(CONTROL_ADDR+reg_addr, data);
end
endtask
task axi_write_single_w_irq; // address in dwords
input [29:0] address;
input [31:0] data;
begin
`ifdef DEBUG_WR_SINGLE
$display("axi_write_single_w %h:%h @ %t",address,data,$time);
`endif
axi_write_single_irq ({address,2'b0},data);
end
endtask
task axi_write_single_irq; // address in bytes, not words
input [31:0] address;
input [31:0] data;
begin
axi_write_addr_data_irq(
GLOBAL_WRITE_ID, // id
address & 32'hfffffffc, // addr
data,
4'h0, // len - single
1, // burst type - increment
1'b1, // data_en
4'hf, // wstrb
1'b1 // last
);
GLOBAL_WRITE_ID <= GLOBAL_WRITE_ID+1;
#0.1; // without this delay axi_write_addr_data() used old value of GLOBAL_WRITE_ID
end
endtask
task axi_write_addr_data_irq;
input [11:0] id;
input [31:0] addr;
input [31:0] data;
input [ 3:0] len;
input [ 1:0] burst;
input data_en; // if 0 - do not send data, only address
input [ 3:0] wstrb;
input last;
begin
// IRQ_EN = 0;
// wait (CLK);
// while (!MAIN_GO) begin
// wait (!CLK);
// wait (CLK);
// end
axi_write_addr_data_inner (id, addr, data, len, burst, data_en, wstrb, last);
// IRQ_EN = 1;
end
endtask
// Tasks common for main ind ISR
task axi_write_addr_data_inner;
input [11:0] id;
input [31:0] addr;
input [31:0] data;
......@@ -200,7 +381,7 @@
end
endtask
task axi_write_data;
task axi_write_data_inner;
input [11:0] id;
input [31:0] data;
input [ 3:0] wstrb;
......@@ -222,7 +403,8 @@
end
endtask
task axi_read_addr;
task axi_read_addr_inner; // regardless of main loop/interrupts
input [11:0] id;
input [31:0] addr;
input [ 3:0] len;
......
......@@ -173,14 +173,21 @@ task read_block_buf;
input wait_done;
integer i; //,j;
begin
wait (~rstb);
IRQ_EN = 0;
wait (CLK);
while (!MAIN_GO) begin
wait (!CLK);
wait (CLK);
end
SIMUL_AXI_FULL<=1'b0;
$display("**** read_block_buf @%t", $time);
axi_set_rd_lag(0);
for (i = 0; i < num_read; i = i + 16) begin
wait(arready);
// $display ("read_block_buf (0x%x) @%t",i,$time);
axi_read_addr(
// axi_read_addr(
axi_read_addr_inner(
i, // id
{start_word_address,2'b0}+( i << 2), // addr
4'hf, // len
......@@ -191,5 +198,11 @@ task read_block_buf;
// wait (AXI_RD_EMPTY);
wait_read_queue_empty;
end
IRQ_EN = 1;
if (IRQS) begin
@(posedge CLK);
@(negedge CLK);
end
end
endtask
/*******************************************************************************
* Module: sim_soc_interrupts
* Date:2016-05-05
* Author: Andrey Filippov
* Description: SOC interrupts simulation
*
* Copyright (c) 2016 Elphel, Inc .
* sim_soc_interrupts.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.
*
* sim_soc_interrupts.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 sim_soc_interrupts #(
parameter NUM_INTERRUPTS = 8
)(
input clk,
input rst,
input irq_en, // automatically handled for the main thread
input [NUM_INTERRUPTS-1:0] irqm, // individual interrupts enable (bit = 1 - enable, 0 - disable)
input [NUM_INTERRUPTS-1:0] irq, // async interrupt requests
input [NUM_INTERRUPTS-1:0] irq_done, // end of ISR, turn off inta bit, re-enable arbitration
output [NUM_INTERRUPTS-1:0] irqs, // synchronized by clock masked interrupts
output [NUM_INTERRUPTS-1:0] inta, // interrupt acknowledge
output main_go // enable main therad to proceed
);
reg [NUM_INTERRUPTS-1:0] inta_r;
reg [NUM_INTERRUPTS-1:0] irqs_r;
wire [NUM_INTERRUPTS :0] irqs_ext = {irqs_r,!irq_en};
wire [NUM_INTERRUPTS-1:0] irqs_pri_w;
assign inta = inta_r;
assign irqs = irqs_r;
assign main_go = !(|inta_r) && !(irq_en && |irqs);
generate
genvar i;
for (i=0; i < NUM_INTERRUPTS; i=i+1) begin: pri_enc_block
assign irqs_pri_w[i] = irqs_r[i] && !(|irqs_ext[i:0]);
end
endgenerate
always @ (posedge clk or posedge rst) begin
if (rst) inta_r <= 0;
else if (!(|inta_r)) inta_r <= irqs_pri_w;
else inta_r <= inta_r & ~irq_done;
if (rst) irqs_r <= 0;
else irqs_r <= irq & irqm;
end
endmodule
......@@ -156,7 +156,13 @@ module status_generate_only #(
if (rst) status_changed_r <= 0;
else if (srst) status_changed_r <= 0;
else if (start) status_changed_r <= 0;
// In simulation should be able to detect changes from initial 'x' in memories, in hardware
// any initial walue is OK, if not equal - will update, if equal - keep
`ifdef SIMULATION
else status_changed_r <= status_changed_r || (status_r !== status_r0);
`else
else status_changed_r <= status_changed_r || (status_r != status_r0);
`endif
if (rst) mode <= 0;
else if (srst) mode <= 0;
......
......@@ -36,6 +36,8 @@
`define SAME_SENSOR_DATA 1
//`undef SAME_SENSOR_DATA
`define COMPRESS_SINGLE
`define USE_CMPRS_IRQ
`define USE_FRAME_SEQ_IRQ
//`define use200Mhz 1
//`define DEBUG_FIFO 1
`undef WAIT_MRS
......@@ -100,6 +102,7 @@ module x393_testbench03 #(
parameter TRIGGER_MODE = 0; // 1; // 0 - auto, 1 - triggered
parameter EXT_TRIGGER_MODE = 1 ; // 0 - internal, 1 - external trigger (camsync)
parameter EXTERNAL_TIMESTAMP = 0; // 1 ; // embed local timestamp, 1 - embed received timestamp
parameter NUM_INTERRUPTS = 9;
`include "includes/x393_localparams.vh" // SuppressThisWarning VEditor - not used
// VDT - incorrect real number calculation
......@@ -622,7 +625,44 @@ assign #10 gpio_pins[9] = gpio_pins[8];
wire CLK;
reg RST;
reg RST_CLEAN = 1;
reg RST_CLEAN = 1;
wire [NUM_INTERRUPTS-1:0] IRQ_R = {x393_i.sata_irq, x393_i.cmprs_irq[3:0], x393_i.frseq_irq[3:0]};
wire [NUM_INTERRUPTS-1:0] IRQ_ACKN;
wire [3:0] IRQ_FRSEQ_ACKN = IRQ_ACKN[3:0];
wire [3:0] IRQ_CMPRS_ACKN = IRQ_ACKN[7:4];
wire IRQ_SATA_ACKN = IRQ_ACKN[8];
reg [3:0] IRQ_FRSEQ_DONE = 0;
reg [3:0] IRQ_CMPRS_DONE = 0;
reg IRQ_SATA_DONE = 0;
wire [NUM_INTERRUPTS-1:0] IRQ_DONE = {IRQ_SATA_DONE, IRQ_CMPRS_DONE, IRQ_FRSEQ_DONE};
reg [NUM_INTERRUPTS-1:0] IRQ_M = 0; // all disabled - on/off by software
reg IRQ_EN = 1; // handled automatically when accessing MAXI_GP0
wire MAIN_GO; // main loop can proceed (no INTA)
wire [NUM_INTERRUPTS-1:0] IRQ_S; // masked interrupt requests
wire IRQS=|IRQ_S; // at least one interrupt is pending (to yield by main w/o slowing down)
wire [3:0] IRQ_FRSEQ_S = IRQ_S[3:0];
wire [3:0] IRQ_CMPRS_S = IRQ_S[7:4];
wire IRQ_SATA_S = IRQ_S[8];
/*
sim_soc_interrupts #(
.NUM_INTERRUPTS(8)
) sim_soc_interrupts_i (
.clk(), // input
.rst(), // input
.irq_en(), // input
.irqm(), // input[7:0]
.irq(), // input[7:0]
.irq_done(), // input[7:0]
.irqs(), // output[7:0]
.inta(), // output[7:0]
.main_go() // output
);
*/
reg AR_SET_CMD_r;
wire AR_READY;
......@@ -765,6 +805,13 @@ assign #10 gpio_pins[9] = gpio_pins[8];
//set simulation-only parameters
axi_set_b_lag(0); //(1);
axi_set_rd_lag(0);
// IRQ-related
IRQ_EN = 1;
IRQ_M = 0;
IRQ_FRSEQ_DONE = 0;
IRQ_CMPRS_DONE = 0;
IRQ_SATA_DONE = 0;
program_status_all(DEFAULT_STATUS_MODE,'h2a); // mode auto with sequence number increment
enable_memcntrl(1); // enable memory controller
......@@ -1067,6 +1114,22 @@ assign #10 gpio_pins[9] = gpio_pins[8];
`endif
`ifdef USE_FRAME_SEQ_IRQ
TEST_TITLE = "IRQ FRAME SEQUENCER ENABLE";
$display("===================== TEST_%s =========================",TEST_TITLE);
IRQ_M = IRQ_M | 'hf; // all frame sequencer interrupts enabled
// Enable all compressor interrupts
frame_sequencer_irq_en (0, 1);
frame_sequencer_irq_en (1, 1);
frame_sequencer_irq_en (2, 1);
frame_sequencer_irq_en (3, 1);
program_status_frame_sequencer(
3, // input [1:0] mode;
0); // input [5:0] seq_num;
`endif
`ifdef TEST_SENSOR
`ifdef DEBUG_RING
......@@ -1226,13 +1289,14 @@ assign #10 gpio_pins[9] = gpio_pins[8];
'h10000 >> 5); // input [26:0] afi_cmprs3_len; // input [26:0] length; // channel buffer length in 32-byte chunks
*/
'h10000000 >> 5, // input [26:0] afi_cmprs0_sa; // input [26:0] sa; // start address in 32-byte chunks
'h5c0 >> 5, // 'h800 >> 5, // input [26:0] afi_cmprs0_len; // input [26:0] length; // channel buffer length in 32-byte chunks
'hba0 >> 5, // 59e/5e0 (exact 2-1) 'h800 >> 5, // input [26:0] afi_cmprs0_len; // input [26:0] length; // channel buffer length in 32-byte chunks
'h10010000 >> 5, // input [26:0] afi_cmprs1_sa; // input [26:0] sa; // start address in 32-byte chunks
'h2e0 >> 5, // h400 >> 5, // input [26:0] afi_cmprs1_len; // input [26:0] length; // channel buffer length in 32-byte chunks
'h640>> 5, // 2f0/320 (exact 2) h400 >> 5, // input [26:0] afi_cmprs1_len; // input [26:0] length; // channel buffer length in 32-byte chunks
'h10020000 >> 5, // input [26:0] afi_cmprs2_sa; // input [26:0] sa; // start address in 32-byte chunks
'h280 >> 5, // 'h200 >> 5, // input [26:0] afi_cmprs2_len; // input [26:0] length; // channel buffer length in 32-byte chunks
'h520 >> 5, // 25e/2a0 (1 less)'h200 >> 5, // input [26:0] afi_cmprs2_len; // input [26:0] length; // channel buffer length in 32-byte chunks
'h10030000 >> 5, // input [26:0] afi_cmprs3_sa; // input [26:0] sa; // start address in 32-byte chunks
'h1e0 >> 5); // 'h100 >> 5); // input [26:0] afi_cmprs3_len; // input [26:0] length; // channel buffer length in 32-byte chunks
'h460 >> 5); // 1de/ 220 (1 more) 'h100 >> 5); // input [26:0] afi_cmprs3_len; // input [26:0] length; // channel buffer length in 32-byte chunks
camsync_setup (
4'hf ); // sensor_mask); //
/*
......@@ -1263,6 +1327,21 @@ assign #10 gpio_pins[9] = gpio_pins[8];
`endif
`ifdef USE_CMPRS_IRQ
TEST_TITLE = "IRQ CMPRS ENABLE";
$display("===================== TEST_%s =========================",TEST_TITLE);
// IRQ_FRSEQ_DONE = 0;
IRQ_M = IRQ_M | 'hf0; // all compressor interrupts enabled, others preserved
// IRQ_SATA_DONE = 0;
// Enable all compressor interrupts
compressor_irq_en (0, 1);
compressor_irq_en (1, 1);
compressor_irq_en (2, 1);
compressor_irq_en (3, 1);
`endif
`ifdef COMPRESS_SINGLE
TEST_TITLE = "COMPRESS_FRAME";
$display("===================== TEST_%s =========================",TEST_TITLE);
......@@ -1344,13 +1423,187 @@ end
// #30000;
// #200000;
// #250000;
#285000;
// #160000;
#175000;
// #175000;
// #60000;
$display("finish testbench 2");
$finish;
end
// Interrupt actions
task read_compressor_frame_irq;
input [1:0] chn;
output reg [3:0] frame;
reg [31:0] rdata;
begin
repeat (5) @( posedge CLK);
read_status_irq(CMPRS_STATUS_REG_BASE + CMPRS_STATUS_REG_INC * chn, rdata);
@ (posedge CLK) frame = rdata [8 +: 4];
wait (!CLK);
end
endtask
task read_compressor_pointer_irq;
input [1:0] chn;
output reg [25:0] pointer;
reg [31:0] rdata;
begin
repeat (5) @( posedge CLK);
read_status_irq(CMPRS_AFIMUX_REG_ADDR0 + chn, rdata);
@ (posedge CLK) pointer = rdata [25:0];
wait (!CLK);
end
endtask
task read_sequencer_frame_irq;
input [1:0] chn;
output reg [3:0] frame;
reg [31:0] rdata;
begin
repeat (5) @( posedge CLK);
read_status_irq(CMDSEQMUX_STATUS, rdata);
@ (posedge CLK) frame = rdata [4*chn +: 4];
wait (!CLK);
end
endtask
reg [3:0] IRQ_CMPRS_FRAME_0;
reg [3:0] IRQ_CMPRS_FRAME_1;
reg [3:0] IRQ_CMPRS_FRAME_2;
reg [3:0] IRQ_CMPRS_FRAME_3;
reg [3:0] IRQ_SEQUENCER_FRAME_0;
reg [3:0] IRQ_SEQUENCER_FRAME_1;
reg [3:0] IRQ_SEQUENCER_FRAME_2;
reg [3:0] IRQ_SEQUENCER_FRAME_3;
reg [25:0] IRQ_CMPRS_POINTER_0;
reg [25:0] IRQ_CMPRS_POINTER_1;
reg [25:0] IRQ_CMPRS_POINTER_2;
reg [25:0] IRQ_CMPRS_POINTER_3;
//reg [3:0] IRQ_SEQUENCER_FRAME;
//reg [3:0] IRQ_CMPRS_FRAME;
//reg [25:0] IRQ_CMPRS_POINTER;
localparam CHN0 = 0;
localparam CHN1 = 1;
localparam CHN2 = 2;
localparam CHN3 = 3;
always @ (posedge IRQ_CMPRS_ACKN[CHN0]) begin
// Clear that interrupt
compressor_irq_clear(CHN0);
// Read frame pointer
read_compressor_frame_irq(CHN0, IRQ_CMPRS_FRAME_0);
// @(posedge CLK) IRQ_CMPRS_FRAME_0 = IRQ_CMPRS_FRAME;