First commit.
commit
1797089f79
|
@ -0,0 +1,75 @@
|
||||||
|
# Created by http://www.gitignore.io
|
||||||
|
|
||||||
|
*.o
|
||||||
|
test/obj_dir
|
||||||
|
test/test
|
||||||
|
|
||||||
|
|
||||||
|
### XilinxISE ###
|
||||||
|
# intermediate build files
|
||||||
|
*.bgn
|
||||||
|
*.bit
|
||||||
|
*.bld
|
||||||
|
*.cmd_log
|
||||||
|
*.drc
|
||||||
|
*.ll
|
||||||
|
*.lso
|
||||||
|
*.msd
|
||||||
|
*.msk
|
||||||
|
*.ncd
|
||||||
|
*.ngc
|
||||||
|
*.ngd
|
||||||
|
*.ngr
|
||||||
|
*.pad
|
||||||
|
*.par
|
||||||
|
*.pcf
|
||||||
|
*.prj
|
||||||
|
*.ptwx
|
||||||
|
*.rbb
|
||||||
|
*.rbd
|
||||||
|
*.stx
|
||||||
|
*.syr
|
||||||
|
*.twr
|
||||||
|
*.twx
|
||||||
|
*.unroutes
|
||||||
|
*.ut
|
||||||
|
*.xpi
|
||||||
|
*.xst
|
||||||
|
*_bitgen.xwbt
|
||||||
|
*_envsettings.html
|
||||||
|
*_map.map
|
||||||
|
*_map.mrp
|
||||||
|
*_map.ngm
|
||||||
|
*_map.xrpt
|
||||||
|
*_ngdbuild.xrpt
|
||||||
|
*_pad.csv
|
||||||
|
*_pad.txt
|
||||||
|
*_par.xrpt
|
||||||
|
*_summary.html
|
||||||
|
*_summary.xml
|
||||||
|
*_usage.xml
|
||||||
|
*_xst.xrpt
|
||||||
|
|
||||||
|
# project-wide generated files
|
||||||
|
*.gise
|
||||||
|
par_usage_statistics.html
|
||||||
|
usage_statistics_webtalk.html
|
||||||
|
webtalk.log
|
||||||
|
webtalk_pn.xml
|
||||||
|
|
||||||
|
# generated folders
|
||||||
|
iseconfig/
|
||||||
|
xlnx_auto_0_xdb/
|
||||||
|
xst/
|
||||||
|
_ngo/
|
||||||
|
_xmsgs/
|
||||||
|
|
||||||
|
|
||||||
|
### vim ###
|
||||||
|
[._]*.s[a-w][a-z]
|
||||||
|
[._]s[a-w][a-z]
|
||||||
|
*.un~
|
||||||
|
Session.vim
|
||||||
|
.netrwhist
|
||||||
|
*~
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
module qm_decode(
|
||||||
|
/// datapath
|
||||||
|
// input instruction register
|
||||||
|
input wire [31:0] di_IR,
|
||||||
|
// output instruction register
|
||||||
|
output wire [31:0] do_IR,
|
||||||
|
// output first operand
|
||||||
|
output wire [31:0] do_A,
|
||||||
|
// output second operand
|
||||||
|
output wire [31:0] do_B,
|
||||||
|
// output immediate
|
||||||
|
output wire [31:0] do_Imm,
|
||||||
|
|
||||||
|
// control signals
|
||||||
|
|
||||||
|
// debug signals
|
||||||
|
input wire [4:0] dbg_wa,
|
||||||
|
input wire dbg_we,
|
||||||
|
input wire [31:0] dbg_wd
|
||||||
|
);
|
||||||
|
|
||||||
|
// internal signals from the IR
|
||||||
|
wire [4:0] rs;
|
||||||
|
wire [4:0] rt;
|
||||||
|
wire [15:0] imm;
|
||||||
|
|
||||||
|
assign rs = di_IR[25:21];
|
||||||
|
assign rt = di_IR[20:16];
|
||||||
|
assign imm = di_IR[15:0];
|
||||||
|
|
||||||
|
qm_regfile regfile(
|
||||||
|
.ra1(rs),
|
||||||
|
.ra2(rt),
|
||||||
|
.rd1(do_A),
|
||||||
|
.rd2(do_B),
|
||||||
|
|
||||||
|
// unused
|
||||||
|
.wa3(dbg_wa),
|
||||||
|
.we3(dbg_we),
|
||||||
|
.wd3(dbg_wd)
|
||||||
|
);
|
||||||
|
|
||||||
|
// sign extend imm
|
||||||
|
assign do_Imm[31:0] = { {16{imm[15]}}, imm[15:0] };
|
||||||
|
|
||||||
|
assign do_IR = di_IR;
|
||||||
|
|
||||||
|
endmodule
|
|
@ -0,0 +1,9 @@
|
||||||
|
module qm_fetch(
|
||||||
|
/// datapath
|
||||||
|
// output instruction register
|
||||||
|
output wire [31:0] do_IR,
|
||||||
|
// output next pc
|
||||||
|
output wire [31:0] do_NextPC
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
|
@ -0,0 +1,66 @@
|
||||||
|
module qm_icache(
|
||||||
|
input wire [31:0] address,
|
||||||
|
input wire reset,
|
||||||
|
input wire clk,
|
||||||
|
|
||||||
|
output wire hit,
|
||||||
|
output wire stall,
|
||||||
|
output wire [31:0] data
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// 4k cache lines -> 16kword cache
|
||||||
|
reg [144:0] lines [4095:0];
|
||||||
|
|
||||||
|
/// internal signals
|
||||||
|
// the bit used to mark valid lines (flips when we flush the cache)
|
||||||
|
reg valid_bit;
|
||||||
|
wire [11:0] index;
|
||||||
|
wire index_valid;
|
||||||
|
wire [15:0] index_tag;
|
||||||
|
wire [15:0] address_tag;
|
||||||
|
wire [1:0] address_word;
|
||||||
|
|
||||||
|
assign index = address[15:4];
|
||||||
|
assign index_valid = lines[index][144];
|
||||||
|
assign index_tag = lines[index][143:128];
|
||||||
|
|
||||||
|
assign address_tag = address[31:16];
|
||||||
|
assign address_word = address[3:2];
|
||||||
|
|
||||||
|
|
||||||
|
// reset condition
|
||||||
|
generate
|
||||||
|
genvar i;
|
||||||
|
for (i = 0; i < 4096; i = i + 1) begin: ruchanie
|
||||||
|
always @(posedge clk) begin
|
||||||
|
if (reset) begin
|
||||||
|
lines[0] <= {145'b0};
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
always @(posedge clk)
|
||||||
|
if (reset)
|
||||||
|
valid_bit <= 1;
|
||||||
|
|
||||||
|
// read condition
|
||||||
|
always @(address) begin
|
||||||
|
if (index_valid == valid_bit && index_tag == address_tag) begin
|
||||||
|
if (address_word == 2'b00)
|
||||||
|
data = lines[index][31:0];
|
||||||
|
else if (address_word == 2'b01)
|
||||||
|
data = lines[index][63:32];
|
||||||
|
else if (address_word == 2'b10)
|
||||||
|
data = lines[index][95:64];
|
||||||
|
else
|
||||||
|
data = lines[index][127:96];
|
||||||
|
hit = 1;
|
||||||
|
stall = 0;
|
||||||
|
end else begin
|
||||||
|
hit = 0;
|
||||||
|
stall = 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
|
@ -0,0 +1,26 @@
|
||||||
|
module qm_regfile(
|
||||||
|
input wire we3,
|
||||||
|
input wire [4:0] ra1,
|
||||||
|
input wire [4:0] ra2,
|
||||||
|
input wire [4:0] wa3,
|
||||||
|
output wire [31:0] rd1,
|
||||||
|
output wire [31:0] rd2,
|
||||||
|
input wire [31:0] wd3
|
||||||
|
);
|
||||||
|
|
||||||
|
// three ported register file
|
||||||
|
// two read ports, one write port
|
||||||
|
|
||||||
|
// actual flops
|
||||||
|
reg [31:0] rf [31:0];
|
||||||
|
|
||||||
|
always @(wd3) begin
|
||||||
|
if (we3) begin
|
||||||
|
rf[wa3] = wd3;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign rd1 = rf[ra1];
|
||||||
|
assign rd2 = rf[ra2];
|
||||||
|
|
||||||
|
endmodule
|
|
@ -0,0 +1,26 @@
|
||||||
|
# Makefile for verilator-based tests
|
||||||
|
|
||||||
|
CXXFLAGS = -I/usr/share/verilator/include -I obj_dir/ -I /usr/share/verilator/include/vltstd/ -std=c++11
|
||||||
|
|
||||||
|
obj_dir/V%.cpp: ../rtl/verilog/%.v
|
||||||
|
verilator -Wall -cc -I../rtl/verilog/ --unroll-count 16000 $<
|
||||||
|
|
||||||
|
|
||||||
|
OBJS := /usr/share/verilator/include/verilated.cpp \
|
||||||
|
obj_dir/Vqm_decode.o \
|
||||||
|
obj_dir/Vqm_decode__Syms.cpp \
|
||||||
|
obj_dir/Vqm_icache.o \
|
||||||
|
obj_dir/Vqm_icache__Syms.cpp \
|
||||||
|
main.o \
|
||||||
|
test_decode.o \
|
||||||
|
test_icache.o
|
||||||
|
|
||||||
|
test: $(OBJS)
|
||||||
|
g++ $(CXXFLAGS) -o test $(OBJS)
|
||||||
|
|
||||||
|
%PHONY = clean
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf obj_dir
|
||||||
|
rm -rf test
|
||||||
|
rm -f *.o
|
|
@ -0,0 +1,11 @@
|
||||||
|
#include "test_decode.h"
|
||||||
|
#include "test_icache.h"
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
test_decode();
|
||||||
|
test_icache();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
#include "test_decode.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "Vqm_decode.h"
|
||||||
|
|
||||||
|
void test_decode(void)
|
||||||
|
{
|
||||||
|
Vqm_decode *decode = new Vqm_decode;
|
||||||
|
|
||||||
|
// set r5 to 666 and r4 to 0xdeadbeef
|
||||||
|
decode->dbg_wa = 5;
|
||||||
|
decode->dbg_wd = 666;
|
||||||
|
decode->dbg_we = 1;
|
||||||
|
decode->eval();
|
||||||
|
decode->dbg_wa = 4;
|
||||||
|
decode->dbg_wd = 0xdeadbeef;
|
||||||
|
decode->eval();
|
||||||
|
decode->dbg_we = 0;
|
||||||
|
|
||||||
|
decode->di_IR = 0x20a40539;
|
||||||
|
decode->eval();
|
||||||
|
|
||||||
|
std::cout << std::hex << decode->do_IR << std::endl;
|
||||||
|
std::cout << std::hex << decode->do_A << std::endl;
|
||||||
|
std::cout << std::hex << decode->do_B << std::endl;
|
||||||
|
std::cout << std::dec << decode->do_Imm << std::endl;
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef _TEST_DECODE_H
|
||||||
|
#define _TEST_DECODE_H
|
||||||
|
|
||||||
|
void test_decode(void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,30 @@
|
||||||
|
#include "test_icache.h"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
#include "Vqm_icache.h"
|
||||||
|
|
||||||
|
void test_icache(void)
|
||||||
|
{
|
||||||
|
Vqm_icache *icache = new Vqm_icache;
|
||||||
|
|
||||||
|
// reset
|
||||||
|
icache->reset = 1;
|
||||||
|
icache->clk = 0;
|
||||||
|
icache->eval();
|
||||||
|
icache->clk = 1;
|
||||||
|
icache->eval();
|
||||||
|
icache->reset = 0;
|
||||||
|
icache->clk = 0;
|
||||||
|
icache->eval();
|
||||||
|
icache->clk = 1;
|
||||||
|
icache->eval();
|
||||||
|
|
||||||
|
icache->address = 0xdeadbeef;
|
||||||
|
icache->clk = 0;
|
||||||
|
icache->eval();
|
||||||
|
icache->clk = 1;
|
||||||
|
icache->eval();
|
||||||
|
|
||||||
|
printf("Cache hit: %i Pipeline stall: %i\n", icache->hit, icache->stall);
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef _TEST_ICACHE_H
|
||||||
|
#define _TEST_ICACHE_H
|
||||||
|
|
||||||
|
void test_icache(void);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue