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