First commit.

master
q3k 2014-09-07 15:48:43 +02:00
commit 1797089f79
11 changed files with 331 additions and 0 deletions

75
.gitignore vendored Normal file
View File

@ -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
*~

48
rtl/verilog/qm_decode.v Normal file
View File

@ -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

9
rtl/verilog/qm_fetch.v Normal file
View File

@ -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

66
rtl/verilog/qm_icache.v Normal file
View File

@ -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

26
rtl/verilog/qm_regfile.v Normal file
View File

@ -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

26
test/Makefile Normal file
View File

@ -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

11
test/main.cpp Normal file
View File

@ -0,0 +1,11 @@
#include "test_decode.h"
#include "test_icache.h"
int main(int argc, char **argv)
{
test_decode();
test_icache();
return 0;
}

28
test/test_decode.cpp Normal file
View File

@ -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;
}

6
test/test_decode.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef _TEST_DECODE_H
#define _TEST_DECODE_H
void test_decode(void);
#endif

30
test/test_icache.cpp Normal file
View File

@ -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);
}

6
test/test_icache.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef _TEST_ICACHE_H
#define _TEST_ICACHE_H
void test_icache(void);
#endif