URL
https://opencores.org/ocsvn/rf6809/rf6809/trunk
Subversion Repositories rf6809
[/] [rf6809/] [trunk/] [rtl/] [noc/] [lib/] [random.sv] - Rev 22
Go to most recent revision | Compare with Previous | Blame | View Log
// ============================================================================
// __
// \\__/ o\ (C) 2011-2022 Robert Finch, Waterloo
// \ __ / All rights reserved.
// \/_// robfinch<remove>@finitron.ca
// ||
//
// random.v
// Multi-stream random number generator.
//
//
// This source file 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 of the License, or
// (at your option) any later version.
//
// This source file 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Reg no.
// 0 read: random output bits [31:0], write: gen next number
// 1 random stream number
// 2 m_z seed setting bits [31:0]
// 3 m_w seed setting bits [31:0]
//
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// |WISHBONE Datasheet
// |WISHBONE SoC Architecture Specification, Revision B.3
// |
// |Description: Specifications:
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// |General Description: random number generator
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// |Supported Cycles: SLAVE,READ/WRITE
// | SLAVE,BLOCK READ/WRITE
// | SLAVE,RMW
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// |Data port, size: 16 bit
// |Data port, granularity: 16 bit
// |Data port, maximum operand size: 16 bit
// |Data transfer ordering: Undefined
// |Data transfer sequencing: Undefined
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// |Clock frequency constraints: none
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// |Supported signal list and Signal Name WISHBONE equiv.
// |cross reference to equivalent ack_o ACK_O
// |WISHBONE signals adr_i[43:0] ADR_I()
// | clk_i CLK_I
// | rst_i RST_I()
// | dat_i(15:0) DAT_I()
// | dat_o(15:0) DAT_O()
// | cyc_i CYC_I
// | stb_i STB_I
// | we_i WE_I
// |
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// |Special requirements:
// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
// ============================================================================
//
// Uses George Marsaglia's multiply method
//
// m_w = <choose-initializer>; /* must not be zero */
// m_z = <choose-initializer>; /* must not be zero */
//
// uint get_random()
// {
// m_z = 36969 * (m_z & 65535) + (m_z >> 16);
// m_w = 18000 * (m_w & 65535) + (m_w >> 16);
// return (m_z << 16) + m_w; /* 32-bit result */
// }
//
`define TRUE 1'b1
`define FALSE 1'b0
module random(rst_i, clk_i, cs_i, cyc_i, stb_i, ack_o, we_i, adr_i, dat_i, dat_o);
input rst_i;
input clk_i;
input cs_i;
input cyc_i;
input stb_i;
output reg ack_o;
input we_i;
input [3:0] adr_i;
input [11:0] dat_i;
output reg [11:0] dat_o;
parameter pAckStyle = 1'b0;
reg ack;
reg cs;
reg we;
reg [3:0] adr;
reg [11:0] dat;
always_ff @(posedge clk_i)
cs <= cs_i && cyc_i && stb_i;
always_ff @(posedge clk_i)
we <= we_i;
always_ff @(posedge clk_i)
adr <= adr_i;
always_ff @(posedge clk_i)
dat <= dat_i;
always_ff @(posedge clk_i)
ack_o <= cs & cs_i & cyc_i & stb_i;
//always @*
// ack_o <= cs ? ack : pAckStyle;
reg [9:0] stream;
reg [35:0] next_m_z;
reg [35:0] next_m_w;
reg [35:0] out;
reg wrw, wrz;
reg [35:0] w=32'd3,z=32'd17;
wire [35:0] m_zs;
wire [35:0] m_ws;
wire pe_we;
edge_det ued1 (.rst(rst_i), .clk(clk_i), .ce(1'b1), .i(we), .pe(pe_we), .ne(), .ee());
rand_ram u1 (clk_i, wrw, stream, w, m_ws);
rand_ram u2 (clk_i, wrz, stream, z, m_zs);
always_comb
begin
next_m_z = (18'h36969 * m_zs[17:0]) + m_zs[35:18];
next_m_w = (18'h18000 * m_ws[17:0]) + m_ws[35:18];
end
reg [35:0] m_zsws;
always_comb
m_zsws <= {m_zs[17:0],18'd0} + m_ws;
// Register read path
//
always_ff @(posedge clk_i)
if (cs_i)
case(adr[3:0])
4'd0: dat_o <= 12'h0;
4'd1: dat_o <= m_zsws[35:24];
4'd2: dat_o <= m_zsws[23:12];
4'd3: dat_o <= m_zsws[11: 0];
4'd5: dat_o <= {2'h0,stream};
// Uncomment these for register read-back
// 3'd4: dat_o <= m_z[31:16];
// 3'd5: dat_o <= m_z[15: 0];
// 3'd6: dat_o <= m_w[31:16];
// 3'd7: dat_o <= m_w[15: 0];
default: dat_o <= 12'h000;
endcase
else
dat_o <= 12'h0;
// Register write path
//
always_ff @(posedge clk_i)
begin
wrw <= `FALSE;
wrz <= `FALSE;
if (cs) begin
if (pe_we)
case(adr[3:0])
4'd3:
begin
z <= next_m_z;
w <= next_m_w;
wrw <= `TRUE;
wrz <= `TRUE;
end
4'd5: stream <= dat[9:0];
4'd8: ;
4'd9: z[35:24] <= dat;
4'd10: z[23:12] <= dat;
4'd11: begin z[11: 0] <= dat; wrz <= `TRUE; end
4'd12: ;
4'd13: w[35:24] <= dat;
4'd14: w[23:12] <= dat;
4'd15: begin w[11:0] <= dat; wrw <= `TRUE; end
endcase
end
end
endmodule
// Tools were inferring a massive distributed ram so we help them out a bit by
// creating an explicit ram definition.
module rand_ram(clk, wr, ad, i, o);
input clk;
input wr;
input [9:0] ad;
input [35:0] i;
output [35:0] o;
reg [35:0] ri;
reg [9:0] regadr;
reg regwr;
(* RAM_STYLE="BLOCK" *)
reg [35:0] mem [0:1023];
always_ff @(posedge clk)
regadr <= ad;
always_ff @(posedge clk)
regwr <= wr;
always_ff @(posedge clk)
ri <= i;
always_ff @(posedge clk)
if (regwr)
mem[regadr] <= ri;
assign o = mem[regadr];
endmodule
Go to most recent revision | Compare with Previous | Blame | View Log