OpenCores
URL https://opencores.org/ocsvn/xulalx25soc/xulalx25soc/trunk

Subversion Repositories xulalx25soc

[/] [xulalx25soc/] [trunk/] [rtl/] [wbudecompress.v] - Rev 21

Go to most recent revision | Compare with Previous | Blame | View Log

////////////////////////////////////////////////////////////////////////////////
//
// Filename:	wbudecompress.v
//
// Project:	XuLA2 board
//
// Purpose:	Compression via this interface is simply a lookup table.
//		When writing, if requested, rather than writing a new 36-bit
//	word, we may be asked to repeat a word that's been written recently.
//	That's the goal of this routine: if given a word's (relative) address
//	in the write stream, we use that address, else we expect a full 32-bit
//	word to come in to be written.
//
//
// Creator:	Dan Gisselquist, Ph.D.
//		Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of  the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
//
// License:	GPL, v3, as defined and found on www.gnu.org,
//		http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
module	wbudecompress(i_clk, i_stb, i_word, o_stb, o_word);
	input			i_clk, i_stb;
	input		[35:0]	i_word;
	output	reg		o_stb;
	output	reg	[35:0]	o_word;
 
 
	// Clock zero
	//	{ o_stb, r_stb } = 0
	wire	cmd_write_not_compressed = (i_word[35:33] == 3'h3);
 
 
	// Clock one: { o_stb, r_stb } = 4'h1 when done
	reg	[7:0]	wr_addr;
	initial	wr_addr = 8'h0;
	always @(posedge i_clk)
		if ((i_stb)&&(cmd_write_not_compressed))
			wr_addr <= wr_addr + 8'h1;
 
	reg	[31:0]	compression_tbl	[0:255];
	always @(posedge i_clk)
		if (i_stb)
		compression_tbl[wr_addr] <= { i_word[32:31], i_word[29:0] };
 
	reg	[35:0]	r_word;
	always @(posedge i_clk)
		if (i_stb)
			r_word <= i_word;
 
 
	// Clock two, calculate the table address ... 1 is the smallest address
	//	{ o_stb, r_stb } = 4'h2 when done
	reg	[7:0]	cmd_addr;
	always @(posedge i_clk)
		cmd_addr = wr_addr - { r_word[32:31], r_word[29:24] };
 
	// Let's also calculate the address, in case this is a compressed
	// address word
	reg	[24:0]	r_addr;
	always @(posedge i_clk)
		case(r_word[32:30])
		3'b000: r_addr <= { 19'h0, r_word[29:24] };
		3'b010: r_addr <= { 13'h0, r_word[29:18] };
		3'b100: r_addr <= {  7'h0, r_word[29:12] };
		3'b110: r_addr <= {  1'h0, r_word[29: 6] };
		3'b001: r_addr <= { {(19){ r_word[29]}}, r_word[29:24] };
		3'b011: r_addr <= { {(13){ r_word[29]}}, r_word[29:18] };
		3'b101: r_addr <= { {( 7){ r_word[29]}}, r_word[29:12] };
		3'b111: r_addr <= { {( 1){ r_word[29]}}, r_word[29: 6] };
		endcase
	wire	[31:0]	w_addr;
	assign	w_addr = { {(7){r_addr[24]}}, r_addr };
 
	reg	[9:0]	rd_len;
	always @(posedge i_clk)
		if (~r_word[34])
			rd_len <= 10'h01 + { 6'h00, r_word[33:31] };
		else
			rd_len <= 10'h08 + { 1'b0, r_word[33:31], r_word[29:24] };
 
	// Clock three, read the table value
	//	{ o_stb, r_stb } = 4'h4 when done
	// Maintaining ...
	//	r_word (clock 1)
	//	r_addr, rd_len (clock 2)
	reg	[31:0]	cword;
	always @(posedge i_clk)
		cword <= compression_tbl[cmd_addr];
 
 
	// Pipeline the strobe signal to create an output strobe, 3 clocks later
	reg	[2:0]	r_stb;
	initial	r_stb = 0;
	always @(posedge i_clk)
		r_stb <= { r_stb[1:0], i_stb };
 
	// Clock four, now that the table value is valid, let's set our output
	// word.
	//	{ o_stb, r_stb } = 4'h8 when done
	always @(posedge i_clk)
		o_stb <= r_stb[2];
	// Maintaining ...
	//	r_word		(clock 1)
	//	r_addr, rd_len	(clock 2)
	//	cword		(clock 3)
	//		Any/all of these can be pipelined for faster operation
	// However, speed is really limited by the speed of the I/O port.  At
	// it's fastest, it's 1 bit per clock, 48 clocks per codeword therefore,
	// thus ... things will hold still for much longer than just 5 clocks.
	always @(posedge i_clk)
		if (r_word[35:30] == 6'b101110)
			o_word <= r_word;
		else casez(r_word[35:30])
		// Set address from something compressed ... unsigned
		6'b001??0: o_word <= { 4'h0, w_addr[31:0] };
		// Set a new address as a signed offset from the last (set) one
		//	(The last address is kept further down the chain,
		//	we just mark here that the address is to be set
		//	relative to it, and by how much.)
		6'b001??1: o_word <= { 3'h1, w_addr[31:30], 1'b1, w_addr[29:0]};
		// Write a value to the bus, with the value given from our
		// codeword table
		6'b010???: o_word <=
			{ 3'h3, cword[31:30], r_word[30], cword[29:0] };
		// Read, highly compressed length (1 word)
		6'b10????: o_word <= { 5'b11000, r_word[30], 20'h00, rd_len };
		// Read, two word (3+9 bits) length
		6'b11????: o_word <= { 5'b11000, r_word[30], 20'h00, rd_len };
		default: o_word <= r_word;
		endcase
endmodule
 
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.