OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /eco32
    from Rev 311 to Rev 312
    Reverse comparison

Rev 311 → Rev 312

/trunk/fpga/experiments/memctrl/sim/memctrl-0/ramtest/ramtest.v
0,0 → 1,262
//
// ramtest.v -- RAM test generator
//
 
 
`timescale 1ns/10ps
`default_nettype none
 
 
`define SIMULATE
`define VERBOSE
 
`define INST_PERIOD 31
`define INST_PHASE 19
`define DATA_PERIOD 17
`define DATA_PHASE 7
 
 
//
// memory test generator
//
// Algorithm: Three independent address/data generators
// produce exactly the same sequence of address/data pairs,
// although at different times: data write, data read, and
// instruction read. Three out of four data cycles are writes,
// one is a read. Instruction reads are also less frequent
// than data writes: 1/31 < 1/17 * 3/4. The writing process
// is therefore always ahead of the reading processes, with
// an increasing gap in between.
//
 
module ramtest(clk, rst,
inst_stb, inst_addr,
inst_din, inst_ack,
data_stb, data_we, data_addr,
data_dout, data_din, data_ack,
test_ended, test_error);
input clk;
input rst;
output reg inst_stb;
output [25:0] inst_addr;
input [63:0] inst_din;
input inst_ack;
output reg data_stb;
output reg data_we;
output [25:0] data_addr;
output [63:0] data_dout;
input [63:0] data_din;
input data_ack;
output test_ended;
output test_error;
 
reg [4:0] inst_timer;
reg [4:0] data_timer;
reg [9:0] data_counter;
 
wire ir_next;
wire [21:0] ir_a;
wire [63:0] ir_d;
 
wire dw_next;
wire [21:0] dw_a;
wire [63:0] dw_d;
 
wire dr_next;
wire [21:0] dr_a;
wire [63:0] dr_d;
 
`ifdef SIMULATE
reg error_1;
reg error_3;
`endif
reg error_2;
reg error_4;
 
always @(posedge clk) begin
if (rst) begin
inst_timer <= 0;
inst_stb <= 0;
`ifdef SIMULATE
error_1 <= 0;
`endif
error_2 <= 0;
end else begin
if (~test_ended) begin
if (~inst_stb) begin
if (inst_timer == `INST_PERIOD - 1) begin
inst_timer <= 0;
end else begin
inst_timer <= inst_timer + 1;
end
if (inst_timer == `INST_PHASE) begin
inst_stb <= 1;
end
end else begin
if (inst_ack) begin
inst_stb <= 0;
`ifdef SIMULATE
`ifdef VERBOSE
$display("%t: inst read @ 0x%h", $realtime, ir_a);
$display(" value = 0x%h", inst_din);
`endif
if (^inst_din[63:0] === 1'bx) begin
$display("Warning: Input data has don't cares at %t",
$realtime);
error_1 <= 1;
end
`endif
if (inst_din[63:0] != ir_d[63:0]) begin
error_2 <= 1;
end
end
end
end
end
end
 
adgen adgen_ir(
.clk(clk),
.rst(rst),
.next(ir_next),
.addr(ir_a),
.data(ir_d)
);
 
assign ir_next = inst_ack;
assign inst_addr[25:0] = { 4'h0, ir_a[21:0] };
 
always @(posedge clk) begin
if (rst) begin
data_timer <= 0;
data_stb <= 0;
data_we <= 0;
data_counter <= 0;
`ifdef SIMULATE
error_3 <= 0;
`endif
error_4 <= 0;
end else begin
if (~test_ended) begin
if (~data_stb) begin
if (data_timer == `DATA_PERIOD - 1) begin
data_timer <= 0;
end else begin
data_timer <= data_timer + 1;
end
if (data_timer == `DATA_PHASE) begin
data_stb <= 1;
data_we <= ~&data_counter[1:0];
end
end else begin
if (data_ack) begin
data_stb <= 0;
data_we <= 0;
data_counter <= data_counter + 1;
`ifdef SIMULATE
`ifdef VERBOSE
if (data_we == 1) begin
$display("%t: data write @ 0x%h", $realtime, dw_a);
$display(" value = 0x%h", dw_d);
end else begin
$display("%t: data read @ 0x%h", $realtime, dr_a);
$display(" value = 0x%h", data_din);
end
`endif
if (data_we == 0 &&
^data_din[63:0] === 1'bx) begin
$display("Warning: Input data has don't cares at %t",
$realtime);
error_3 <= 1;
end
`endif
if (data_we == 0 &&
data_din[63:0] != dr_d[63:0]) begin
error_4 <= 1;
end
end
end
end
end
end
 
adgen adgen_dw(
.clk(clk),
.rst(rst),
.next(dw_next),
.addr(dw_a),
.data(dw_d)
);
 
adgen adgen_dr(
.clk(clk),
.rst(rst),
.next(dr_next),
.addr(dr_a),
.data(dr_d)
);
 
assign dw_next = data_ack & data_we;
assign dr_next = data_ack & ~data_we;
assign data_addr[25:0] = { 4'h0, data_we ? dw_a[21:0] : dr_a[21:0] };
assign data_dout[63:0] = dw_d[63:0];
 
assign test_ended = &data_counter[9:0];
 
`ifdef SIMULATE
assign test_error = error_1 | error_2 | error_3 | error_4;
`else
assign test_error = error_2 | error_4;
`endif
 
endmodule
 
 
//
// address & data generator
//
// compute pseudo-random 32-bit address
// and 64-bit data on request
//
 
module adgen(clk, rst,
next, addr, data);
input clk;
input rst;
input next;
output [21:0] addr;
output [63:0] data;
 
reg [31:0] a;
reg [63:0] d;
 
always @(posedge clk) begin
if (rst) begin
a[31: 0] <= 32'hC70337DB;
d[63:32] <= 32'h7F4D514F;
d[31: 0] <= 32'h75377599;
end else begin
if (next) begin
if (a[0] == 0) begin
a[31:0] <= a[31:0] >> 1;
end else begin
a[31:0] <= (a[31:0] >> 1) ^ 32'hD0000001;
end
if (d[32] == 0) begin
d[63:32] <= d[63:32] >> 1;
end else begin
d[63:32] <= (d[63:32] >> 1) ^ 32'hD0000001;
end
if (d[0] == 0) begin
d[31:0] <= d[31:0] >> 1;
end else begin
d[31:0] <= (d[31:0] >> 1) ^ 32'hD0000001;
end
end
end
end
 
assign addr[21:0] = a[21:0];
assign data[63:0] = d[63:0];
 
endmodule
/trunk/fpga/experiments/memctrl/sim/memctrl-0/memtest.v
0,0 → 1,92
//
// memtest.v -- test bench for memory controller
//
 
 
`include "ramtest/ramtest.v"
`include "ramctrl/ramctrl.v"
 
 
`timescale 1ns/10ps
`default_nettype none
 
 
module memtest;
 
reg clk; // system clock
reg rst_in; // reset, input
reg rst; // system reset
 
wire inst_stb;
wire [25:0] inst_addr;
wire [63:0] inst_to_cache;
wire inst_ack;
wire inst_timeout;
 
wire data_stb;
wire data_we;
wire [25:0] data_addr;
wire [63:0] data_to_mctrl;
wire [63:0] data_to_cache;
wire data_ack;
wire data_timeout;
 
wire test_ended;
wire test_error;
 
// simulation control
initial begin
#0 $timeformat(-9, 1, " ns", 12);
$dumpfile("dump.vcd");
$dumpvars(0, memtest);
clk = 1;
rst_in = 1;
#23 rst_in = 0;
#252400 $finish;
end
 
// clock generator
always begin
#5 clk = ~clk; // 10 nsec cycle time
end
 
// reset synchronizer
always @(posedge clk) begin
rst <= rst_in;
end
 
ramctrl ramctrl_1(
.clk(clk),
.rst(rst),
.inst_stb(inst_stb),
.inst_addr(inst_addr[25:0]),
.inst_dout(inst_to_cache[63:0]),
.inst_ack(inst_ack),
.inst_timeout(inst_timeout),
.data_stb(data_stb),
.data_we(data_we),
.data_addr(data_addr[25:0]),
.data_din(data_to_mctrl[63:0]),
.data_dout(data_to_cache[63:0]),
.data_ack(data_ack),
.data_timeout(data_timeout)
);
 
ramtest ramtest_1(
.clk(clk),
.rst(rst),
.inst_stb(inst_stb),
.inst_addr(inst_addr[25:0]),
.inst_din(inst_to_cache[63:0]),
.inst_ack(inst_ack | inst_timeout),
.data_stb(data_stb),
.data_we(data_we),
.data_addr(data_addr[25:0]),
.data_dout(data_to_mctrl[63:0]),
.data_din(data_to_cache[63:0]),
.data_ack(data_ack | data_timeout),
.test_ended(test_ended),
.test_error(test_error)
);
 
endmodule
/trunk/fpga/experiments/memctrl/sim/memctrl-0/ramctrl/ram.v
0,0 → 1,72
//
// ram.v -- simulate external RAM
// 8M x 32 bit = 32 MB
//
 
 
`timescale 1ns/10ps
`default_nettype none
 
 
//
// use this set of parameters for minimal access times
//
`define RD_CYCLES 4'd2 // # cycles for read, min = 2
`define WR_CYCLES 4'd2 // # cycles for write, min = 2
 
//
// use this set of parameters for realistic access times
//
//`define RD_CYCLES 4'd14 // # cycles for read, min = 2
//`define WR_CYCLES 4'd6 // # cycles for write, min = 2
 
 
module ram(clk, rst,
stb, we, addr,
data_in, data_out, ack);
input clk;
input rst;
input stb;
input we;
input [24:2] addr;
input [31:0] data_in;
output reg [31:0] data_out;
output ack;
 
reg [31:0] mem[0:8388607];
reg [3:0] counter;
 
always @(posedge clk) begin
if (stb) begin
if (we) begin
// write cycle
mem[addr] <= data_in;
end else begin
// read cycle
data_out <= mem[addr];
end
end
end
 
always @(posedge clk) begin
if (rst) begin
counter[3:0] <= 4'h0;
end else begin
if (counter[3:0] == 4'h0) begin
if (stb & ~we) begin
// a read may need some clock cycles
counter[3:0] <= `RD_CYCLES - 1;
end
if (stb & we) begin
// a write may need some clock cycles
counter[3:0] <= `WR_CYCLES - 1;
end
end else begin
counter[3:0] <= counter[3:0] - 1;
end
end
end
 
assign ack = (counter[3:0] == 4'h1) ? 1 : 0;
 
endmodule
/trunk/fpga/experiments/memctrl/sim/memctrl-0/ramctrl/ramctrl.v
0,0 → 1,388
//
// ramctrl.v -- RAM controller
//
 
 
`include "ramctrl/ram.v"
 
 
`timescale 1ns/10ps
`default_nettype none
 
 
module ramctrl(clk, rst,
inst_stb, inst_addr,
inst_dout, inst_ack,
inst_timeout,
data_stb, data_we,
data_addr, data_din,
data_dout, data_ack,
data_timeout);
input clk;
input rst;
input inst_stb;
input [25:0] inst_addr;
output [63:0] inst_dout;
output reg inst_ack;
output reg inst_timeout;
input data_stb;
input data_we;
input [25:0] data_addr;
input [63:0] data_din;
output [63:0] data_dout;
output reg data_ack;
output reg data_timeout;
 
reg ram_stb;
reg ram_we;
wire [22:0] ram_addr;
wire [31:0] ram_dout;
wire [31:0] ram_din;
wire ram_ack;
 
wire inst_addr_out_of_range;
wire data_addr_out_of_range;
 
reg ram_as;
reg ram_a0;
 
reg ram_ds;
 
reg [63:0] data;
reg data_wh;
reg data_wl;
 
reg [3:0] state;
reg [3:0] next_state;
 
//
// create ram instance
//
 
ram ram_1(
.clk(clk),
.rst(rst),
.stb(ram_stb),
.we(ram_we),
.addr(ram_addr[22:0]),
.data_in(ram_dout[31:0]),
.data_out(ram_din[31:0]),
.ack(ram_ack)
);
 
//
// address range check
//
 
assign inst_addr_out_of_range = | inst_addr[25:22];
assign data_addr_out_of_range = | data_addr[25:22];
 
//
// address output to ram
//
 
assign ram_addr[22:0] =
~ram_as ? { inst_addr[21:0], ram_a0 } :
{ data_addr[21:0], ram_a0 };
 
//
// data output to ram
//
 
assign ram_dout[31:0] =
~ram_ds ? data_din[63:32] : data_din[31:0];
 
//
// data output to cache
//
 
always @(posedge clk) begin
if (data_wh) begin
data[63:32] <= ram_din[31:0];
end
if (data_wl) begin
data[31: 0] <= ram_din[31:0];
end
end
 
assign inst_dout[63:0] = data[63:0];
assign data_dout[63:0] = data[63:0];
 
//
// ramctrl state machine
//
 
always @(posedge clk) begin
if (rst) begin
state <= 0;
end else begin
state <= next_state;
end
end
 
always @(*) begin
case (state)
4'd0:
// idle, request arbitration
begin
inst_ack = 1'b0;
inst_timeout = 1'b0;
data_ack = 1'b0;
data_timeout = 1'b0;
ram_stb = 1'b0;
ram_we = 1'b0;
ram_as = 1'bx;
ram_a0 = 1'bx;
ram_ds = 1'bx;
data_wh = 1'b0;
data_wl = 1'b0;
if (data_stb) begin
if (data_addr_out_of_range) begin
// illegal data address
next_state = 4'd11;
end else begin
// data address is ok
if (data_we) begin
// data write request
next_state = 4'd7;
end else begin
// data read request
next_state = 4'd4;
end
end
end else begin
if (inst_stb) begin
if (inst_addr_out_of_range) begin
// illegal inst address
next_state = 4'd10;
end else begin
// inst address is ok
// inst read request
next_state = 4'd1;
end
end else begin
// no request
next_state = 4'd0;
end
end
end
4'd1:
// inst read, phase 1
begin
inst_ack = 1'b0;
inst_timeout = 1'b0;
data_ack = 1'b0;
data_timeout = 1'b0;
ram_stb = 1'b1;
ram_we = 1'b0;
ram_as = 1'b0;
ram_a0 = 1'b0;
ram_ds = 1'bx;
data_wh = ram_ack;
data_wl = 1'b0;
if (ram_ack) begin
next_state = 4'd2;
end else begin
next_state = 4'd1;
end
end
4'd2:
// inst read, phase 2
begin
inst_ack = 1'b0;
inst_timeout = 1'b0;
data_ack = 1'b0;
data_timeout = 1'b0;
ram_stb = 1'b1;
ram_we = 1'b0;
ram_as = 1'b0;
ram_a0 = 1'b1;
ram_ds = 1'bx;
data_wh = 1'b0;
data_wl = ram_ack;
if (ram_ack) begin
next_state = 4'd3;
end else begin
next_state = 4'd2;
end
end
4'd3:
// inst read, phase 3
begin
inst_ack = 1'b1;
inst_timeout = 1'b0;
data_ack = 1'b0;
data_timeout = 1'b0;
ram_stb = 1'b0;
ram_we = 1'b0;
ram_as = 1'bx;
ram_a0 = 1'bx;
ram_ds = 1'bx;
data_wh = 1'b0;
data_wl = 1'b0;
next_state = 4'd0;
end
4'd4:
// data read, phase 1
begin
inst_ack = 1'b0;
inst_timeout = 1'b0;
data_ack = 1'b0;
data_timeout = 1'b0;
ram_stb = 1'b1;
ram_we = 1'b0;
ram_as = 1'b1;
ram_a0 = 1'b0;
ram_ds = 1'bx;
data_wh = ram_ack;
data_wl = 1'b0;
if (ram_ack) begin
next_state = 4'd5;
end else begin
next_state = 4'd4;
end
end
4'd5:
// data read, phase 2
begin
inst_ack = 1'b0;
inst_timeout = 1'b0;
data_ack = 1'b0;
data_timeout = 1'b0;
ram_stb = 1'b1;
ram_we = 1'b0;
ram_as = 1'b1;
ram_a0 = 1'b1;
ram_ds = 1'bx;
data_wh = 1'b0;
data_wl = ram_ack;
if (ram_ack) begin
next_state = 4'd6;
end else begin
next_state = 4'd5;
end
end
4'd6:
// data read, phase 3
begin
inst_ack = 1'b0;
inst_timeout = 1'b0;
data_ack = 1'b1;
data_timeout = 1'b0;
ram_stb = 1'b0;
ram_we = 1'b0;
ram_as = 1'bx;
ram_a0 = 1'bx;
ram_ds = 1'bx;
data_wh = 1'b0;
data_wl = 1'b0;
next_state = 4'd0;
end
4'd7:
// data write, phase 1
begin
inst_ack = 1'b0;
inst_timeout = 1'b0;
data_ack = 1'b0;
data_timeout = 1'b0;
ram_stb = 1'b1;
ram_we = 1'b1;
ram_as = 1'b1;
ram_a0 = 1'b0;
ram_ds = 1'b0;
data_wh = 1'b0;
data_wl = 1'b0;
if (ram_ack) begin
next_state = 4'd8;
end else begin
next_state = 4'd7;
end
end
4'd8:
// data write, phase 2
begin
inst_ack = 1'b0;
inst_timeout = 1'b0;
data_ack = 1'b0;
data_timeout = 1'b0;
ram_stb = 1'b1;
ram_we = 1'b1;
ram_as = 1'b1;
ram_a0 = 1'b1;
ram_ds = 1'b1;
data_wh = 1'b0;
data_wl = 1'b0;
if (ram_ack) begin
next_state = 4'd9;
end else begin
next_state = 4'd8;
end
end
4'd9:
// data write, phase 3
begin
inst_ack = 1'b0;
inst_timeout = 1'b0;
data_ack = 1'b1;
data_timeout = 1'b0;
ram_stb = 1'b0;
ram_we = 1'b0;
ram_as = 1'bx;
ram_a0 = 1'bx;
ram_ds = 1'bx;
data_wh = 1'b0;
data_wl = 1'b0;
next_state = 4'd0;
end
4'd10:
// illegal inst address
begin
inst_ack = 1'b0;
inst_timeout = 1'b1;
data_ack = 1'b0;
data_timeout = 1'b0;
ram_stb = 1'b0;
ram_we = 1'b0;
ram_as = 1'bx;
ram_a0 = 1'bx;
ram_ds = 1'bx;
data_wh = 1'b0;
data_wl = 1'b0;
next_state = 4'd0;
end
4'd11:
// illegal data address
begin
inst_ack = 1'b0;
inst_timeout = 1'b0;
data_ack = 1'b0;
data_timeout = 1'b1;
ram_stb = 1'b0;
ram_we = 1'b0;
ram_as = 1'bx;
ram_a0 = 1'bx;
ram_ds = 1'bx;
data_wh = 1'b0;
data_wl = 1'b0;
next_state = 4'd0;
end
default:
// not used
begin
inst_ack = 1'b0;
inst_timeout = 1'b0;
data_ack = 1'b0;
data_timeout = 1'b0;
ram_stb = 1'b0;
ram_we = 1'b0;
ram_as = 1'bx;
ram_a0 = 1'bx;
ram_ds = 1'bx;
data_wh = 1'b0;
data_wl = 1'b0;
next_state = 4'd0;
end
endcase
end
 
endmodule
/trunk/fpga/experiments/memctrl/sim/memctrl-0/memtest.cfg
0,0 → 1,48
[timestart] 0
[size] 1280 725
[pos] -1 -1
*-16.000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] memtest.
[treeopen] memtest.ramctrl_1.
@28
memtest.clk
memtest.rst_in
memtest.rst
@200
--- INST RD --
@28
memtest.inst_stb
@22
memtest.inst_addr[25:0]
memtest.inst_to_cache[63:0]
@28
memtest.inst_ack
memtest.inst_timeout
@200
--- DATA RD/WR --
@28
memtest.data_stb
memtest.data_we
@22
memtest.data_addr[25:0]
memtest.data_to_mctrl[63:0]
memtest.data_to_cache[63:0]
@28
memtest.data_ack
memtest.data_timeout
@200
--- TEST RESULT --
@28
memtest.test_ended
memtest.test_error
@200
---- RAM CHIP --
@28
memtest.ramctrl_1.ram_stb
memtest.ramctrl_1.ram_we
@22
memtest.ramctrl_1.ram_addr[22:0]
memtest.ramctrl_1.ram_dout[31:0]
memtest.ramctrl_1.ram_din[31:0]
@28
memtest.ramctrl_1.ram_ack
/trunk/fpga/experiments/memctrl/sim/memctrl-0/Makefile
0,0 → 1,18
#
# Makefile for testing the memory controller
#
 
all: show
 
install:
 
memtest: memtest.v
iverilog -Wall -o memtest memtest.v
 
show: memtest
./memtest
gtkwave dump.vcd memtest.cfg
 
clean:
rm -f *~ memtest dump.vcd
rm -f ramtest/*~ ramctrl/*~
/trunk/fpga/experiments/memctrl/sim/memctrl-0/README
0,0 → 1,44
Structure
---------
 
A top-level module (memtest.v) creates instances of a memory
test circuit (ramtest/ramtest.v) and a memory controller
(ramctrl/ramctrl.v), which in turn builds an internal model
of the external RAM (ramctrl/ram.v).
 
 
Intended Use
------------
 
The memory controller offers a complete simulation of the memory
subsystem, if the given (simplistic) RAM implementation is used.
If the RAM is substituted by a word-oriented, single-access SDRAM
controller, the memory controller will in fact do its job on a real
FPGA too, although it won't exploit the full potential of the SDRAM
chip.
 
 
Front-End (interface to caches)
-------------------------------
 
instruction read:
2^26 * 64 bit = 512 MB
strobe/acknowledge/timeout handshake
 
data read/write:
2^26 * 64 bit = 512 MB
strobe/acknowledge/timeout handshake
 
 
Back-End (interface to RAM)
---------------------------
 
2^23 * 32 bit = 32 MB
strobe/acknowledge handshake
 
 
RAM
---
 
The RAM has got separately adjustable access times for read and
write operations (minimum is two clock cycles each).

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.