blob: c347178ef92a72a243a962b8c7b584350487f6ea [file] [log] [blame]
//////////////////////////////////////////////////////////////////////////////
// SPDX-FileCopyrightText: 2021 , Dinesh Annayya
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileContributor: Created by Dinesh Annayya <dinesha@opencores.org>
//
//////////////////////////////////////////////////////////////////////
//// ////
//// Semaphore Register ////
//// ////
//// This file is part of the riscduino cores project ////
//// https://github.com/dineshannayya/riscduino.git ////
//// ////
//// Description ////
//// A semaphore is a variable or abstract data type that ////
//// provides a simple but useful abstraction for controlling ////
//// access by multiple processes to a common resource in a ////
//// parallel programming or multi-user environment. ////
//// ////
//// To Do: ////
//// nothing ////
//// ////
//// Author(s): ////
//// - Dinesh Annayya, dinesha@opencores.org ////
//// ////
//// Revision : ////
//// 0.1 - 15th Aug 2022, Dinesh A ////
//// initial version ////
//////////////////////////////////////////////////////////////////////
//
/***************************************************************
Special Semaphore Register Implementation
Read access from 0 to 14 will return corresponsonding bit lock status.
If lock is free, then it return '1' and also lock the corresponding bit
If lock is busy, then it return '0'
Write & Read access with address 15 does normal write and read access,
this location should used for only debug purpose
*****************************************************************/
module semaphore_reg #(parameter DW = 16, // DATA WIDTH
parameter AW = $clog2(DW), // ADDRESS WIDTH
parameter BW = $clog2(AW) // BYTE WIDTH
) (
// System Signals
// Inputs
input logic mclk,
input logic h_reset_n,
// Reg Bus Interface Signal
input logic reg_cs,
input logic reg_wr,
input logic [AW-1:0] reg_addr,
input logic [DW-1:0] reg_wdata,
input logic [BW-1:0] reg_be,
// Outputs
output logic [DW-1:0] reg_rdata,
output logic reg_ack
);
//-----------------------------------------------------------------------
// Internal Wire Declarations
//-----------------------------------------------------------------------
logic sw_rd_en ;
logic sw_wr_en ;
logic [AW-1:0] sw_addr ; // addressing 16 registers
logic [DW-1:0] sw_reg_wdata ;
logic [BW-1:0] sw_be ;
logic [DW-1:0] reg_out ;
logic [DW-1:0] reg_0 ;
logic sw_wr_en_0 ;
assign sw_addr = reg_addr;
assign sw_rd_en = reg_cs & !reg_wr;
assign sw_wr_en = reg_cs & reg_wr;
always @ (posedge mclk or negedge h_reset_n)
begin : preg_out_Seq
if (h_reset_n == 1'b0) begin
reg_rdata <= 'h0;
reg_ack <= 1'b0;
end else if (reg_cs && !reg_ack) begin
reg_rdata <= reg_out[DW-1:0] ;
reg_ack <= 1'b1;
end else begin
reg_ack <= 1'b0;
end
end
/***************************************************************
Special Semaphore Register Implementation
Read access from 0 to 30 will return corresponsonding bit lock status.
If lock is free, then it return '1' and lock the corresponding bit
If lock is busy, then it return '0' and lock the corresponding bit
*****************************************************************/
gen_16b_reg #('h0) u_reg_0 (
//List of Inputs
.reset_n (h_reset_n ),
.clk (mclk ),
.cs (sw_wr_en_0 ),
.we (sw_be[BW-1:0] ),
.data_in (sw_reg_wdata[DW-1:0] ),
//List of Outs
.data_out (reg_0 )
);
//-----------------------------------------------------------------------
// Register Write Data
//-----------------------------------------------------------------------
always_comb
begin
sw_reg_wdata = 'h0;
sw_wr_en_0 = 'b0;
sw_be = 'h0;
// Address 0xF, is Simple Write Register
if(sw_addr == {AW {1'b1}}) begin
sw_reg_wdata = reg_0;
sw_wr_en_0 = sw_wr_en & reg_ack;
sw_be = reg_be[BW-1:0];
end else begin // 0 to 0xE is Semaphore Register
if(sw_rd_en) begin // Read will always lock the bit '1'
sw_reg_wdata = (reg_0 | ( 1 << sw_addr)) ;
end else begin // To release the Lock Write with '1'
sw_reg_wdata = (reg_0 ^ ((reg_wdata [DW-1:0] & 'h1) << sw_addr)) ;
end
sw_wr_en_0 = reg_ack;
sw_be = {BW{1'b1}};
end
end
//-----------------------------------------------------------------------
// Register Read Path Multiplexer instantiation
//-----------------------------------------------------------------------
always_comb
begin
if(sw_addr == {AW {1'b1}}) begin
reg_out = reg_0;
end else begin
reg_out = (reg_0 >> sw_addr ) ^ 'h1;
end
end
endmodule