Commit 874f587a authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

wip on wishbone BIU

parent 14e06a77
module rv_csr
(
input clk_i,
input rst_i,
input x_stall_i,
input d_csr_write_rd_i,
input [31:0] d_rs1_i,
input [31:0] d_pc_i, // for exception strage
output reg [31:0] x_rd_o,
output reg x_rd_write_o,
input x_exception_i,
input x_exception_irq_i,
input [2:0] x_exception_id_i
output [31:0] x_exception_pc_o
);
reg [31:0] csr_mepc;
reg [31:0] csr_mscratch;
reg [31:0] csr_mcause;
reg [31:0] csr_mstatus;
wire csr_mie;
assign x_exception_pc_o = csr_mepc;
/*
`include "rv_defs.v"
`timescale 1ns/1ps
module rv_multiply
(
input clk_i,
input rst_i,
input x_stall_i,
input [31:0] x_rs1_i,
input [31:0] x_rs2_i,
input [4:0] x_opcode_i,
input [2:0] x_fun_i,
output [31:0] x_rd_o,
output x_rd_valid_o,
output x_stall_req_o
);
parameter g_latency = 2;
wire sign_a = ( x_fun_i == `FUNC_MUL || x_fun_i == `FUNC_MULHSU ) ? x_rs1_i[31] : 1'b0;
wire sign_b = ( x_fun_i == `FUNC_MUL ) ? x_rs2_i[31] : 1'b0;
wire [32:0] a = { sign_a, x_rs1_i };
wire [32:0] b = { sign_b, x_rs2_i };
reg [65:0] stage0;
reg [3:0] pipe;
always@(posedge clk_i)
if(rst_i)
pipe <= 0;
else if (x_opcode_i = `OPC_MUL )
pipe <= (1<<g_latency);
else
pipe <= {1'b0, pipe [3:1]};
always@(posedge clk_i)
begin
stage0 <= $signed(a) * $signed(b);
if( d_fun_i != `FUNC_MUL )
x_rd_o <= stage0[63:32];
else
x_rd_o <= stage0[31:0];
end
endmodule // rv_multiply
*/
`timescale 1ns/1ps
module rv_top_test
(
input clk_i,
input rst_i,
output reg [7:0] io_o
);
localparam mem_size=16384;
localparam mem_addr_bits = 16;
reg [31:0] mem[0:mem_size- 1];
wire [31:0] im_addr;
reg [31:0] im_data;
reg im_valid;
wire [31:0] dm_addr;
wire [31:0] dm_data_s;
reg [31:0] dm_data_l;
wire [3:0] dm_data_select;
wire dm_write;
reg dm_valid_l = 1;
reg dm_ready = 1;
always@(posedge clk_i)
begin
im_data <= mem[im_addr[mem_addr_bits-1:2] ];
im_valid <= 1;
end
wire mem_sel = (dm_addr[mem_addr_bits+1] == 1'b0);
wire io_sel = (dm_addr[mem_addr_bits+1] == 1'b1);
always@(posedge clk_i)
begin
if(dm_write && dm_data_select[0] && mem_sel)
mem [dm_addr[mem_addr_bits-1:2]][7:0] <= dm_data_s[7:0];
if(dm_write && dm_data_select[1] && mem_sel)
mem [dm_addr[mem_addr_bits-1:2]][15:8] <= dm_data_s[15:8];
if(dm_write && dm_data_select[2] && mem_sel)
mem [dm_addr[mem_addr_bits-1:2]][23:16] <= dm_data_s[23:16];
if(dm_write && dm_data_select[3] && mem_sel)
mem [dm_addr[mem_addr_bits-1:2]][31:24] <= dm_data_s[31:24];
dm_data_l <= mem [dm_addr[mem_addr_bits-1:2]];
end // always@ (posedge clk)
always@(posedge clk_i)
if(dm_write && io_sel)
io_o <= dm_data_s[7:0];
rv_cpu DUT
(
.clk_i(clk_i),
.rst_i(rst_i),
// instruction mem I/F
.im_addr_o(im_addr),
.im_data_i(im_data),
.im_valid_i(im_valid),
// data mem I/F
.dm_addr_o(dm_addr),
.dm_data_s_o(dm_data_s),
.dm_data_l_i(dm_data_l),
.dm_data_select_o(dm_data_select),
.dm_store_o(dm_write),
.dm_load_o(),
.dm_store_done_i(1'b1),
.dm_load_done_i(1'b1),
.dm_ready_i(dm_ready)
);
endmodule
`include "rv_defs.v"
`timescale 1ns/1ps
module rv_core_wishbone
(
input clk_i,
input cpu_rst_i,
input rst_i,
// data Wishbone bus
output reg d_cyc_o,
output reg d_stb_o,
output reg d_we_o,
output reg [3:0] d_sel_o,
output reg [31:0] d_adr_o,
output reg [31:0] d_dat_o,
input [31:0] d_dat_i,
input d_stall_i,
input d_ack_i,
// mem host access bus
input ha_cyc_i,
input ha_stb_i,
input ha_we_i,
input [3:0] ha_sel_i,
input [31:0] ha_adr_i,
input [31:0] ha_dat_i,
output reg [31:0] ha_dat_o,
output reg ha_ack_o,
output ha_stall_o
);
parameter g_mem_size = 16384;
parameter g_mem_addr_bits = 16;
parameter g_address_space_bits = 18;
parameter g_wishbone_start = 'h20000;
reg [31:0] mem[0:g_mem_size- 1];
// instruction memory/host access wishbone port logic
wire [31:0] im_addr;
reg [31:0] im_data;
reg im_valid;
reg [g_address_space_bits-1:0] ha_im_addr;
reg [31:0] ha_im_wdata;
reg [31:0] ha_im_rdata;
reg ha_im_access, ha_im_access_d;
reg ha_im_write;
assign ha_stall_o = 0;
// Host access to the CPU memory (through instruction port)
always@(posedge clk_i or posedge rst_i)
if(rst_i)
begin
ha_im_access <= 0;
ha_im_access_d <= 0;
ha_im_write <= 0;
end else begin
ha_im_access <= ha_cyc_i & ha_stb_i;
ha_im_access_d <= ha_im_access;
ha_im_write <= ha_cyc_i & ha_stb_i & ha_we_i;
ha_im_wdata <= ha_dat_i;
if(ha_im_access_d) begin
ha_im_access <= 0;
ha_im_access_d <= 0;
ha_ack_o <= 1;
ha_dat_o <= ha_im_rdata;
end
end // else: !if(rst_i)
wire [g_address_space_bits-1: 0] im_addr_muxed = (ha_im_access ? ha_im_addr : im_addr);
// Internal memory, instruction/host port
always@(posedge clk_i)
if(rst_i)
im_valid <= 0;
else begin
if(ha_im_write)
mem[im_addr_muxed[g_mem_addr_bits-1:2] ] <= ha_im_wdata;
im_data <= mem[im_addr_muxed[g_mem_addr_bits-1:2] ];
im_valid <= !ha_im_access;
end
// data memory & Wishbone out
wire [31:0] dm_addr;
wire [31:0] dm_data_s;
reg [31:0] dm_data_l;
wire [3:0] dm_data_select;
wire dm_load;
wire dm_store;
reg dm_load_done;
reg dm_store_done;
wire dm_ready = 1;
reg dm_cycle_in_progress;
wire dm_is_wishbone = (dm_addr >= g_wishbone_start);
reg [31:0] dm_mem_rdata;
reg [31:0] dm_wb_rdata;
reg dm_wb_write;
reg dm_select_wb;
always@(posedge clk_i)
if(rst_i) begin
d_cyc_o <= 0;
dm_cycle_in_progress <= 0;
dm_load_done <= 0;
dm_store_done <= 0;
dm_select_wb <= 0;
end else begin
if(!dm_cycle_in_progress) // access to internal memory
begin
if(!dm_is_wishbone) begin
if(dm_store) begin
dm_load_done <= 0;
dm_store_done <= 1;
dm_select_wb <= 0;
end else if (dm_load) begin
dm_load_done <= 1;
dm_store_done <= 0;
dm_select_wb <= 0;
end else begin
dm_store_done <= 0;
dm_load_done <= 0;
dm_select_wb <= 0;
end
end else begin // if (!dm_is_wishbone)
if(dm_load || dm_store) begin
d_cyc_o <= 1;
d_stb_o <= 1;
d_we_o <= dm_store;
dm_wb_write <= dm_store;
d_adr_o <= dm_addr;
d_dat_o <= dm_data_s;
d_sel_o <= dm_data_select;
dm_load_done <= 0;
dm_store_done <= 0;
dm_cycle_in_progress <= 1;
end else begin // if (dm_load || dm_store)
dm_store_done <= 0;
dm_load_done <= 0;
dm_cycle_in_progress <= 0;
end // else: !if(dm_load || dm_store)
end // else: !if(!dm_is_wishbone)
end else begin // if (!dm_cycle_in_progress)
if(!d_stall_i)
d_stb_o <= 0;
if(d_ack_i) begin
if(!dm_wb_write) begin
dm_wb_rdata <= d_dat_i;
dm_select_wb <= 1;
dm_load_done <= 1;
end else begin
dm_store_done <= 1;
end
dm_cycle_in_progress <= 0;
d_cyc_o <= 0;
end // if (d_ack_i)
end // else: !if(!dm_cycle_in_progress)
end // else: !if(rst_i)
always@*
if(dm_select_wb)
dm_data_l <= dm_wb_rdata;
else
dm_data_l <= dm_mem_rdata;
// Internal memory, data port
always@(posedge clk_i)
begin
if(!dm_is_wishbone) // access to local mem
begin
if(dm_store && dm_data_select[0])
mem [dm_addr[g_mem_addr_bits-1:2]][7:0] <= dm_data_s[7:0];
if(dm_store && dm_data_select[1])
mem [dm_addr[g_mem_addr_bits-1:2]][15:8] <= dm_data_s[15:8];
if(dm_store && dm_data_select[2])
mem [dm_addr[g_mem_addr_bits-1:2]][23:16] <= dm_data_s[23:16];
if(dm_store && dm_data_select[3])
mem [dm_addr[g_mem_addr_bits-1:2]][31:24] <= dm_data_s[31:24];
end // if (!d_is_wishbone)
dm_mem_rdata <= mem [dm_addr[g_mem_addr_bits-1:2]];
end // always@ (posedge clk)
// The CPU!
reg cpu_reset;
always@(posedge clk_i)
cpu_reset <= rst_i & cpu_rst_i;
rv_cpu cpu_core
(
.clk_i(clk_i),
.rst_i(rst_i),
.im_addr_o(im_addr),
.im_data_i(im_data),
.im_valid_i(im_valid),
.dm_addr_o(dm_addr),
.dm_data_s_o(dm_data_s),
.dm_data_l_i(dm_data_l),
.dm_data_select_o(dm_data_select),
.dm_ready_i(dm_ready),
.dm_store_o(dm_store),
.dm_load_o(dm_load),
.dm_load_done_i(dm_load_done),
.dm_store_done_i(dm_store_done)
);
endmodule
--
-- uRV - a tiny and dumb RISC-V core
-- Copyright (c) 2015 twl <twlostow@printf.cc>.
--
-- This library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser General Public
-- License as published by the Free Software Foundation; either
-- version 3.0 of the License, or (at your option) any later version.
--
-- This library is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- Lesser General Public License for more details.
--
-- You should have received a copy of the GNU Lesser General Public
-- License along with this library.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
use work.genram_pkg.all;
entity xrv_core is
generic (
g_internal_ram_size : integer := 65536;
g_internal_ram_init_file : string := "";
g_address_bits : integer := 32;
g_wishbone_start : unsigned(31 downto 0) := x"00020000"
);
port (
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
cpu_rst_i : in std_logic := '0';
-- not implemented yet ;-(
irq_i : in std_logic_vector(7 downto 0) := x"00";
dwb_o : out t_wishbone_master_out;
dwb_i : in t_wishbone_master_in;
host_slave_i : in t_wishbone_slave_in := cc_dummy_slave_in;
host_slave_o : out t_wishbone_slave_out
);
end xrv_core;
architecture wrapper of xrv_core is
constant c_mem_address_bits : integer := f_ceil_log2(g_internal_ram_size / 4);
component rv_cpu is
port(
clk_i : in std_logic;
rst_i : in std_logic;
im_addr_o : out std_logic_vector(31 downto 0);
im_data_i : in std_logic_vector(31 downto 0);
im_valid_i : in std_logic;
dm_addr_o : out std_logic_vector(31 downto 0);
dm_data_s_o : out std_logic_vector(31 downto 0);
dm_data_l_i : in std_logic_vector(31 downto 0);
dm_data_select_o : out std_logic_vector(3 downto 0);
dm_ready_i : in std_logic;
dm_store_o : out std_logic;
dm_load_o : out std_logic;
dm_load_done_i : in std_logic;
dm_store_done_i : in std_logic
);
end component;
signal cpu_rst : std_logic;
signal im_addr : std_logic_vector(31 downto 0);
signal im_data : std_logic_vector(31 downto 0);
signal im_valid : std_logic;
signal ha_im_addr : std_logic_vector(g_address_bits-1 downto 0);
signal ha_im_wdata, ha_im_rdata : std_logic_vector(31 downto 0);
signal ha_im_access, ha_im_access_d, ha_im_write : std_logic;
signal im_addr_muxed : std_logic_vector(g_address_bits-1 downto 0);
signal dm_addr, dm_data_s, dm_data_l : std_logic_vector(31 downto 0);
signal dm_data_select : std_logic_vector(3 downto 0);
signal dm_load, dm_store, dm_load_done, dm_store_done, dm_ready : std_logic;
signal dm_cycle_in_progress, dm_is_wishbone : std_logic;
signal dm_mem_rdata, dm_wb_rdata : std_logic_vector(31 downto 0);
signal dm_wb_write, dm_select_wb : std_logic;
signal dm_data_write : std_logic;
begin
cpu_rst <= (not rst_n_i) or cpu_rst_i;
-- Host access to the CPU memory (through instruction port)
process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if(rst_n_i = '0') then
ha_im_access <= '0';
ha_im_access_d <= '0';
ha_im_write <= '0';
else
ha_im_access <= host_slave_i.cyc and host_slave_i.stb;
ha_im_access_d <= ha_im_access;
ha_im_write <= host_slave_i.cyc and host_slave_i.stb and host_slave_i.we;
ha_im_wdata <= host_slave_i.dat;
ha_im_addr <= host_slave_i.adr(g_address_bits-1 downto 0);
if ha_im_access_d = '1' then
ha_im_access <= '0';
ha_im_access_d <= '0';
host_slave_o.ack <= '1';
host_slave_o.dat <= ha_im_rdata;
end if;
end if;
end if;
end process;
dm_is_wishbone <= '1' when unsigned(dm_addr(g_address_bits-1 downto 0)) >= g_wishbone_start else '0';
-- Wishbone bus arbitration / internal RAM access
process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if(rst_n_i = '0') then
dwb_o.cyc <= '0';
dm_cycle_in_progress <= '0';
dm_load_done <= '0';
dm_store_done <= '0';
dm_select_wb <= '0';
else
if(dm_cycle_in_progress = '0') then -- access to internal memory
if(dm_is_wishbone = '0') then
if(dm_store = '1') then
dm_load_done <= '0';
dm_store_done <= '1';
dm_select_wb <= '0';
elsif (dm_load = '1') then
dm_load_done <= '1';
dm_store_done <= '0';
dm_select_wb <= '0';
else
dm_store_done <= '0';
dm_load_done <= '0';
dm_select_wb <= '0';
end if;
else
if(dm_load = '1' or dm_store = '1') then
dwb_o.cyc <= '1';
dwb_o.stb <= '1';
dwb_o.we <= dm_store;
dm_wb_write <= dm_store;
dwb_o.adr <= dm_addr;
dwb_o.dat <= dm_data_s;
dwb_o.sel <= dm_data_select;
dm_load_done <= '0';
dm_store_done <= '0';
dm_cycle_in_progress <= '1';
else
dm_store_done <= '0';
dm_load_done <= '0';
dm_cycle_in_progress <= '0';
end if;
end if;
else
if(dwb_i.stall = '0') then
dwb_o.stb <= '0';
end if;
if(dwb_i.ack = '1') then
if(dm_wb_write = '0') then
dm_wb_rdata <= dwb_i.dat;
dm_select_wb <= '1';
dm_load_done <= '1';
else
dm_store_done <= '1';
dm_select_wb <= '0';
end if;
dm_cycle_in_progress <= '0';
dwb_o.cyc <= '0';
end if;
end if;
end if;
end if;
end process;
dm_data_l <= dm_wb_rdata when dm_select_wb = '1' else dm_mem_rdata;
im_addr_muxed <= ha_im_addr when ha_im_access = '1' else im_addr(g_address_bits-1 downto 0);
dm_ready <= '1';
cpu_core : rv_cpu
port map (
clk_i => clk_sys_i,
rst_i => cpu_rst,
im_addr_o => im_addr,
im_data_i => im_data,
im_valid_i => im_valid,
dm_addr_o => dm_addr,
dm_data_s_o => dm_data_s,
dm_data_l_i => dm_data_l,
dm_data_select_o => dm_data_select,
dm_ready_i => dm_ready,
dm_store_o => dm_store,
dm_load_o => dm_load,
dm_load_done_i => dm_load_done,
dm_store_done_i => dm_store_done);
dm_data_write <= not dm_is_wishbone and dm_store;
U_iram : generic_dpram
generic map (
g_data_width => 32,
g_size => g_internal_ram_size/ 4,
g_with_byte_enable => true,
g_dual_clock => false,
g_addr_conflict_resolution => "read_first",
g_init_file => g_internal_ram_init_file)
port map (
rst_n_i => rst_n_i,
clka_i => clk_sys_i,
wea_i => ha_im_write,
aa_i => im_addr_muxed(c_mem_address_bits + 1 downto 2),
da_i => ha_im_wdata,
qa_o => im_data,
clkb_i => clk_sys_i,
bweb_i => dm_data_select,
web_i => dm_data_write,
ab_i => dm_addr(c_mem_address_bits + 1 downto 2),
db_i => dm_data_s,
qb_o => dm_mem_rdata
);
process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if(cpu_rst = '1') then
im_valid <= '0';
else
im_valid <= not ha_im_access;
end if;
end if;
end process;
host_slave_o.stall <= '0';
host_slave_o.err <= '0';
host_slave_o.rty <= '0';
end wrapper;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment