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;
......
This diff is collapsed.
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