diff --git a/lib/rggen/builtins/register_block/host_ifs/axi4lite.erb b/lib/rggen/builtins/register_block/host_ifs/axi4lite.erb index 943daff..c8b9b94 100644 --- a/lib/rggen/builtins/register_block/host_ifs/axi4lite.erb +++ b/lib/rggen/builtins/register_block/host_ifs/axi4lite.erb @@ -1,6 +1,7 @@ rggen_host_if_axi4lite #( .LOCAL_ADDRESS_WIDTH (<%= local_address_width %>), .DATA_WIDTH (<%= data_width %>), + .TOTAL_REGISTERS (<%= total_registers %>), .ACCESS_PRIORITY (<%= access_priority %>) ) u_host_if ( .clk (<%= clock %>), diff --git a/lib/rggen/builtins/register_block/host_ifs/axi4lite.rb b/lib/rggen/builtins/register_block/host_ifs/axi4lite.rb index b5c8657..f16c32e 100644 --- a/lib/rggen/builtins/register_block/host_ifs/axi4lite.rb +++ b/lib/rggen/builtins/register_block/host_ifs/axi4lite.rb @@ -11,9 +11,9 @@ rtl do build do parameter :register_block, :access_priority, - name: 'ACCESS_PRIORITY', - type: :'rggen_rtl_pkg::rggen_direction', - default: :'rggen_rtl_pkg::RGGEN_WRITE' + name: 'ACCESS_PRIORITY', + data_type: :'rggen_rtl_pkg::rggen_direction', + default: :'rggen_rtl_pkg::RGGEN_WRITE' interface_port :register_block, :axi4lite_if, type: :rggen_axi4lite_if, modport: :slave diff --git a/rtl/rggen_axi4lite_if.sv b/rtl/rggen_axi4lite_if.sv index aacad19..02f8508 100644 --- a/rtl/rggen_axi4lite_if.sv +++ b/rtl/rggen_axi4lite_if.sv @@ -7,7 +7,7 @@ interface rggen_axi4lite_if #( logic [ADDRESS_WIDTH-1:0] awaddr; logic [2:0] awprot; logic wvalid; - logic wraedy; + logic wready; logic [DATA_WIDTH-1:0] wdata; logic [DATA_WIDTH/8-1:0] wstrb; logic bvalid; @@ -28,7 +28,7 @@ interface rggen_axi4lite_if #( output awaddr, output awprot, output wvalid, - input wraedy, + input wready, output wdata, output wstrb, input bvalid, @@ -50,7 +50,7 @@ interface rggen_axi4lite_if #( input awaddr, input awprot, input wvalid, - output wraedy, + output wready, input wdata, input wstrb, output bvalid, diff --git a/rtl/rggen_host_if_axi4lite.sv b/rtl/rggen_host_if_axi4lite.sv index 08a3418..048d8ac 100644 --- a/rtl/rggen_host_if_axi4lite.sv +++ b/rtl/rggen_host_if_axi4lite.sv @@ -3,12 +3,159 @@ module rggen_host_if_axi4lite #( parameter int LOCAL_ADDRESS_WIDTH = 16, parameter int DATA_WIDTH = 32, + parameter int TOTAL_REGISTERS = 1, parameter rggen_direction ACCESS_PRIORITY = RGGEN_WRITE )( - input clk, - input rst_n, - rggen_axi4lite_if.slave axi4lite_if, - rggen_bus_if.master bus_if + input logic clk, + input logic rst_n, + rggen_axi4lite_if.slave axi4lite_if, + rggen_register_if.master register_if[TOTAL_REGISTERS] ); - // TODO + typedef enum logic [4:0] { + IDLE = 5'b00001, + WRITE_IN_PROGRESS = 5'b00010, + WAIT_FOR_BREADY = 5'b00100, + READ_IN_PROGRESS = 5'b01000, + WAIT_FOR_RREADY = 5'b10000 + } e_state; + + rggen_bus_if #(LOCAL_ADDRESS_WIDTH, DATA_WIDTH) bus_if(); + e_state state; + +//-------------------------------------------------------------- +// AXI4 Lite +//-------------------------------------------------------------- + logic write_request; + logic valid_write_request; + logic write_request_ack; + logic read_request; + logic valid_read_request; + logic read_request_ack; + logic [DATA_WIDTH-1:0] read_data; + rggen_status status; + + assign axi4lite_if.awready = write_request_ack; + assign axi4lite_if.wready = write_request_ack; + assign axi4lite_if.bvalid = state[2]; + assign axi4lite_if.bresp = status; + assign axi4lite_if.arready = read_request_ack; + assign axi4lite_if.rvalid = state[4]; + assign axi4lite_if.rdata = read_data; + assign axi4lite_if.rresp = status; + + assign write_request = (axi4lite_if.awvalid && axi4lite_if.wvalid) ? '1 : '0; + assign read_request = axi4lite_if.arvalid; + + generate if (ACCESS_PRIORITY == RGGEN_WRITE) begin + assign valid_write_request = (state[0]) ? write_request : '0; + assign valid_read_request = (state[0] && (!valid_write_request)) ? read_request : '0; + end + else begin + assign valid_write_request = (state[0] && (!valid_read_request)) ? write_request : '0; + assign valid_read_request = (state[0]) ? read_request : '0; + end endgenerate + + always_ff @(posedge clk, negedge rst_n) begin + if (!rst_n) begin + write_request_ack <= '0; + read_request_ack <= '0; + end + else begin + write_request_ack <= valid_write_request; + read_request_ack <= valid_read_request; + end + end + + always_ff @(posedge clk, negedge rst_n) begin + if (!rst_n) begin + read_data <= '0; + status <= RGGEN_OKAY; + end + else if ((state[1] || state[3]) && bus_if.done) begin + read_data <= bus_if.read_data; + status <= bus_if.status; + end + end + +//-------------------------------------------------------------- +// Bus IF +//-------------------------------------------------------------- + rggen_direction direction; + logic [LOCAL_ADDRESS_WIDTH-1:0] address; + logic [DATA_WIDTH-1:0] write_data; + logic [DATA_WIDTH/8-1:0] write_strobe; + + assign bus_if.request = (state[1] || state[3]) ? '1 : '0; + assign bus_if.direction = direction; + assign bus_if.address = address; + assign bus_if.write_data = write_data; + assign bus_if.write_strobe = write_strobe; + + always_ff @(posedge clk, negedge rst_n) begin + if (!rst_n) begin + direction <= RGGEN_READ; + address <= '0; + write_data <= '0; + write_strobe <= '0; + end + else if (state[0]) begin + if (valid_write_request) begin + direction <= RGGEN_WRITE; + address <= axi4lite_if.awaddr; + write_data <= axi4lite_if.wdata; + write_strobe <= axi4lite_if.wstrb; + end + else if (valid_read_request) begin + direction <= RGGEN_READ; + address <= axi4lite_if.araddr; + end + end + end + + rggen_bus_splitter #( + DATA_WIDTH, TOTAL_REGISTERS + ) u_bus_splitter ( + clk, rst_n, bus_if, register_if + ); + +//-------------------------------------------------------------- +// State Machine +//-------------------------------------------------------------- + always_ff @(posedge clk, negedge rst_n) begin + if (!rst_n) begin + state <= IDLE; + end + else begin + case (state) + IDLE: begin + if (valid_write_request) begin + state <= WRITE_IN_PROGRESS; + end + else if (valid_read_request) begin + state <= READ_IN_PROGRESS; + end + end + WRITE_IN_PROGRESS: begin + if (bus_if.write_done) begin + state <= WAIT_FOR_BREADY; + end + end + WAIT_FOR_BREADY: begin + if (axi4lite_if.bready) begin + state <= IDLE; + end + end + READ_IN_PROGRESS: begin + if (bus_if.read_done) begin + state <= WAIT_FOR_RREADY; + end + end + WAIT_FOR_RREADY: begin + if (axi4lite_if.rready) begin + state <= IDLE; + end + end + endcase + end + end endmodule diff --git a/spec/rggen/builtins/register_block/host_ifs/axi4lite_spec.rb b/spec/rggen/builtins/register_block/host_ifs/axi4lite_spec.rb index 62978b5..2918a91 100644 --- a/spec/rggen/builtins/register_block/host_ifs/axi4lite_spec.rb +++ b/spec/rggen/builtins/register_block/host_ifs/axi4lite_spec.rb @@ -7,8 +7,13 @@ before(:all) do enable :global, [:address_width, :data_width] - enable :register_block, [:name, :byte_size, :clock_reset, :host_if] + enable :register_block, [:name, :byte_size] + enable :register_block, [:host_if, :clock_reset] enable :register_block, :host_if, :axi4lite + enable :register, [:name, :offset_address, :array, :type] + enable :register, :type, [:indirect, :external] + enable :bit_field, [:name, :bit_assignment, :type, :initial_value, :reference] + enable :bit_field, :type, :rw end after(:all) do @@ -51,8 +56,17 @@ def configuration(load_data = {}) register_map = create_register_map( configuration, "block_0" => [ - [nil, nil, "block_0"], - [nil, nil, 256 ] + [nil, nil , "block_0" ], + [nil, nil , 252 ], + [ ], + [ ], + [nil, "register_0", "0x00" , nil , nil , "bit_field_0_0", "[0]" , "rw", 0 , nil], + [nil, nil , nil , nil , nil , "bit_field_0_1", "[31:16]", "rw", 0 , nil], + [nil, "register_1", "0x04" , nil , nil , "bit_field_1_0", "[31:0]" , "rw", 0 , nil], + [nil, "register_2", "0x08-0x0F", "[2]" , nil , "bit_field_2_0", "[31:0]" , "rw", 0 , nil], + [nil, "register_3", "0x10" , "[2,4]", "indirect: bit_field_0_0, bit_field_0_1", "bit_field_3_0", "[31:0]" , "rw", 0 , nil], + [nil, "register_4", "0x14" , nil , :external , nil , nil , nil , nil, nil], + [nil, "register_5", "0x18" , nil , :external , nil , nil , nil , nil, nil] ] ) @rtl = build_rtl_factory.create(configuration, register_map).register_blocks[0] @@ -62,16 +76,8 @@ def configuration(load_data = {}) @rtl end - let(:data_width) do - 32 - end - - let(:host_address_width) do - 16 - end - it "読み書きの優先度を決めるパラメータを持つ" do - expect(rtl).to have_parameter(:register_block, :access_priority, name: 'ACCESS_PRIORITY', type: :'rggen_rtl_pkg::rggen_direction', default: :'rggen_rtl_pkg::RGGEN_WRITE') + expect(rtl).to have_parameter(:register_block, :access_priority, name: 'ACCESS_PRIORITY', data_type: :'rggen_rtl_pkg::rggen_direction', default: :'rggen_rtl_pkg::RGGEN_WRITE') end it "rggen_axi4lite_ifを入出力ポートに持つ" do @@ -84,6 +90,7 @@ def configuration(load_data = {}) rggen_host_if_axi4lite #( .LOCAL_ADDRESS_WIDTH (8), .DATA_WIDTH (32), + .TOTAL_REGISTERS (14), .ACCESS_PRIORITY (ACCESS_PRIORITY) ) u_host_if ( .clk (clk),