Hazard3/hdl/arith/hazard5_shift_1bit_seq.v

73 lines
2.4 KiB
Verilog

/**********************************************************************
* DO WHAT THE FUCK YOU WANT TO AND DON'T BLAME US PUBLIC LICENSE *
* Version 3, April 2008 *
* *
* Copyright (C) 2018 Luke Wren *
* *
* Everyone is permitted to copy and distribute verbatim or modified *
* copies of this license document and accompanying software, and *
* changing either is allowed. *
* *
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION *
* *
* 0. You just DO WHAT THE FUCK YOU WANT TO. *
* 1. We're NOT RESPONSIBLE WHEN IT DOESN'T FUCKING WORK. *
* *
*********************************************************************/
module hazard5_shift_1bit_seq #(
parameter W_DATA = 32,
parameter W_SHAMT = 5
) (
input wire clk,
input wire rst_n,
input wire [W_DATA-1:0] din,
input wire din_vld, // can be asserted at any time, we always respond
input wire [W_SHAMT-1:0] shamt,
input wire right_nleft,
input wire arith,
output wire [W_DATA-1:0] dout,
output wire dout_vld,
);
reg [W_DATA-1:0] accum;
reg [W_DATA-1:0] accum_next;
reg [W_SHAMT-1:0] shamt_remaining;
reg flipped;
// Handle actual shifting
wire sext = arith && accum[W_DATA - 1];
always @ (*) begin: shift_unit
accum_next = accum;
if (din_vld) begin
accum_next = din;
end else if (shamt_remaining) begin
if (right_nleft)
accum_next = {sext, accum[W_DATA-1:1]};
else
accum_next = {accum << 1};
end
end
// No reset on datapath
always @ (posedge clk)
accum <= accum_next;
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
shamt_remaining <= {W_SHAMT{1'b0}};
end else if (din_vld) begin
shamt_remaining <= shamt;
end else begin
shamt_remaining <= shamt_remaining - |shamt_remaining;
end
end
assign dout_vld = shamt_remaining == 0;
assign dout = accum;
endmodule