From 1797089f7981e9b478fa832f2e00353dae926bf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergiusz=20=27q3k=27=20Baza=C5=84ski?= Date: Sun, 7 Sep 2014 15:48:43 +0200 Subject: [PATCH] First commit. --- .gitignore | 75 ++++++++++++++++++++++++++++++++++++++++ rtl/verilog/qm_decode.v | 48 +++++++++++++++++++++++++ rtl/verilog/qm_fetch.v | 9 +++++ rtl/verilog/qm_icache.v | 66 +++++++++++++++++++++++++++++++++++ rtl/verilog/qm_regfile.v | 26 ++++++++++++++ test/Makefile | 26 ++++++++++++++ test/main.cpp | 11 ++++++ test/test_decode.cpp | 28 +++++++++++++++ test/test_decode.h | 6 ++++ test/test_icache.cpp | 30 ++++++++++++++++ test/test_icache.h | 6 ++++ 11 files changed, 331 insertions(+) create mode 100644 .gitignore create mode 100644 rtl/verilog/qm_decode.v create mode 100644 rtl/verilog/qm_fetch.v create mode 100644 rtl/verilog/qm_icache.v create mode 100644 rtl/verilog/qm_regfile.v create mode 100644 test/Makefile create mode 100644 test/main.cpp create mode 100644 test/test_decode.cpp create mode 100644 test/test_decode.h create mode 100644 test/test_icache.cpp create mode 100644 test/test_icache.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e2664f3 --- /dev/null +++ b/.gitignore @@ -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 +*~ + diff --git a/rtl/verilog/qm_decode.v b/rtl/verilog/qm_decode.v new file mode 100644 index 0000000..bc276de --- /dev/null +++ b/rtl/verilog/qm_decode.v @@ -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 diff --git a/rtl/verilog/qm_fetch.v b/rtl/verilog/qm_fetch.v new file mode 100644 index 0000000..e6f87a5 --- /dev/null +++ b/rtl/verilog/qm_fetch.v @@ -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 diff --git a/rtl/verilog/qm_icache.v b/rtl/verilog/qm_icache.v new file mode 100644 index 0000000..1638158 --- /dev/null +++ b/rtl/verilog/qm_icache.v @@ -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 diff --git a/rtl/verilog/qm_regfile.v b/rtl/verilog/qm_regfile.v new file mode 100644 index 0000000..9d0a8fe --- /dev/null +++ b/rtl/verilog/qm_regfile.v @@ -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 diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..8e90f4f --- /dev/null +++ b/test/Makefile @@ -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 diff --git a/test/main.cpp b/test/main.cpp new file mode 100644 index 0000000..9fdbb20 --- /dev/null +++ b/test/main.cpp @@ -0,0 +1,11 @@ +#include "test_decode.h" +#include "test_icache.h" + +int main(int argc, char **argv) +{ + test_decode(); + test_icache(); + + return 0; +} + diff --git a/test/test_decode.cpp b/test/test_decode.cpp new file mode 100644 index 0000000..061461e --- /dev/null +++ b/test/test_decode.cpp @@ -0,0 +1,28 @@ +#include "test_decode.h" + +#include + +#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; +} diff --git a/test/test_decode.h b/test/test_decode.h new file mode 100644 index 0000000..094a06d --- /dev/null +++ b/test/test_decode.h @@ -0,0 +1,6 @@ +#ifndef _TEST_DECODE_H +#define _TEST_DECODE_H + +void test_decode(void); + +#endif diff --git a/test/test_icache.cpp b/test/test_icache.cpp new file mode 100644 index 0000000..66df39b --- /dev/null +++ b/test/test_icache.cpp @@ -0,0 +1,30 @@ +#include "test_icache.h" + +#include + +#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); +} diff --git a/test/test_icache.h b/test/test_icache.h new file mode 100644 index 0000000..e5018c3 --- /dev/null +++ b/test/test_icache.h @@ -0,0 +1,6 @@ +#ifndef _TEST_ICACHE_H +#define _TEST_ICACHE_H + +void test_icache(void); + +#endif