Use shared code for Arty A7-100T example

Move Xilinx specific code into shared folder so it can be re-used by
different examples.
Use the shared RAM code and make use of byte enable signal.
Fixes lowrisc/ibex#144
This commit is contained in:
Tobias Wölfel 2019-11-12 09:20:42 +01:00 committed by Tobias Woelfel
parent 6be1e8aff3
commit 76f6a3d4c3
7 changed files with 42 additions and 75 deletions

View file

@ -1,57 +0,0 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// Synchronous dual-port SRAM register model
// This module is for simulation and small size SRAM.
// Implementing ECC should be done inside wrapper not this model.
module ram_1p #(
parameter int Width = 32, // bit
parameter int Depth = 128,
// Do not touch
parameter int Aw = $clog2(Depth)
) (
input clk_i,
input rst_ni,
input req_i,
input write_i,
input [Aw-1:0] addr_i,
input [Width-1:0] wdata_i,
output logic rvalid_o,
output logic [Width-1:0] rdata_o
);
logic [Width-1:0] storage [Depth];
// Xilinx FPGA specific Dual-port RAM coding style
// using always instead of always_ff to avoid 'ICPD - illegal combination of drivers' error
// thrown due to 'storage' being driven by two always processes below
always @(posedge clk_i) begin
if (req_i) begin
if (write_i) begin
storage[addr_i] <= wdata_i;
end
rdata_o <= storage[addr_i];
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
rvalid_o <= '0;
end else begin
rvalid_o <= req_i;
end
end
`ifdef SRAM_INIT_FILE
localparam MEM_FILE = `"`SRAM_INIT_FILE`";
initial begin
$display("Initializing SRAM from %s", MEM_FILE);
$readmemh(MEM_FILE, storage);
end
`endif
endmodule

View file

@ -26,14 +26,16 @@ module top_artya7_100 (
logic data_gnt;
logic data_rvalid;
logic data_we;
logic [3:0] data_be;
logic [31:0] data_addr;
logic [31:0] data_wdata;
logic [31:0] data_rdata;
// SRAM arbiter
logic [13:0] mem_addr_index;
logic [31:0] mem_addr;
logic mem_req;
logic mem_write;
logic [3:0] mem_be;
logic [31:0] mem_wdata;
logic mem_rvalid;
logic [31:0] mem_rdata;
@ -63,8 +65,7 @@ module top_artya7_100 (
.data_gnt_i (data_gnt),
.data_rvalid_i (data_rvalid),
.data_we_o (data_we),
// TODO: Byte access needs to be implemented
.data_be_o (),
.data_be_o (data_be),
.data_addr_o (data_addr),
.data_wdata_o (data_wdata),
.data_rdata_i (data_rdata),
@ -85,30 +86,32 @@ module top_artya7_100 (
// Connect Ibex to SRAM
always_comb begin
mem_req = 1'b0;
mem_addr_index = 14'b0;
mem_addr = 32'b0;
mem_write = 1'b0;
mem_be = 4'b0;
mem_wdata = 32'b0;
if (instr_req) begin
mem_req = (instr_addr & ~MEM_MASK) == MEM_START;
mem_addr_index = instr_addr[15:2];
mem_addr = instr_addr;
end else if (data_req) begin
mem_req = (data_addr & ~MEM_MASK) == MEM_START;
mem_write = data_we;
mem_addr_index = data_addr[15:2];
mem_be = data_be;
mem_addr = data_addr;
mem_wdata = data_wdata;
end
end
// SRAM block for instruction and data storage
ram_1p #(
.Width(32),
.Depth(MEM_SIZE / 4)
) u_ram (
.clk_i ( clk_sys ),
.rst_ni ( rst_sys_n ),
.req_i ( mem_req ),
.write_i ( mem_write ),
.addr_i ( mem_addr_index ),
.we_i ( mem_write ),
.be_i ( mem_be ),
.addr_i ( mem_addr ),
.wdata_i ( mem_wdata ),
.rvalid_o ( mem_rvalid ),
.rdata_o ( mem_rdata )
@ -130,14 +133,19 @@ module top_artya7_100 (
end
end
// Connect the led output to the lower four bits of a written data word
// Connect the LED output to the lower four bits of the most significant
// byte
logic [3:0] leds;
always_ff @(posedge clk_sys or negedge rst_sys_n) begin
if (!rst_sys_n) begin
leds <= 4'b0;
end else begin
if (mem_req && data_req && data_we) begin
leds <= data_wdata[3:0];
for (int i = 0; i < 4; i = i + 1) begin
if (data_be[i] == 1'b1) begin
leds <= data_wdata[i*8 +: 4];
end
end
end
end
end

View file

@ -8,11 +8,9 @@ filesets:
files_rtl_artya7:
depend:
- lowrisc:ibex:ibex_core
- lowrisc:ibex:fpga_xilinx_shared
files:
- rtl/top_artya7_100.sv
- rtl/ram_1p.sv
- rtl/prim_clock_gating.sv
- rtl/clkgen_xil7series.sv
file_type: systemVerilogSource
files_constraints:

View file

@ -35,10 +35,10 @@ static int usleep(unsigned long usec) {
}
int main(int argc, char **argv) {
// Any data written to the stack segment will connect the lowest four bits to
// the board leds
volatile uint32_t *var = (volatile uint32_t *) 0x0000c010;
*var = 0xa;
// The lowest four bits of the highest byte written to the memory region named
// "stack" are connected to the LEDs of the board.
volatile uint8_t *var = (volatile uint8_t *) 0x0000c010;
*var = 0x0a;
while (1) {
usleep(1000 * 1000); // 1000 ms

18
shared/fpga_xilinx.core Normal file
View file

@ -0,0 +1,18 @@
CAPI=2:
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
name: "lowrisc:ibex:fpga_xilinx_shared"
description: "Collection of useful RTL for Xilinx based examples"
filesets:
files_sv:
files:
- rtl/fpga/xilinx/prim_clock_gating.sv
- rtl/fpga/xilinx/clkgen_xil7series.sv
- rtl/ram_1p.sv
file_type: systemVerilogSource
targets:
default:
filesets:
- files_sv