Showing preview only (288K chars total). Download the full file or copy to clipboard to get everything.
Repository: ultraembedded/core_jpeg
Branch: main
Commit: bb03cce45d0b
Files: 33
Total size: 275.5 KB
Directory structure:
gitextract_xejh9o8w/
├── LICENSE
├── README.md
├── c_model/
│ ├── README.md
│ ├── jpeg_bit_buffer.h
│ ├── jpeg_dht.h
│ ├── jpeg_dqt.h
│ ├── jpeg_idct.h
│ ├── jpeg_mcu_block.h
│ ├── main.cpp
│ └── makefile
└── src_v/
├── jpeg_bitbuffer.v
├── jpeg_core.v
├── jpeg_dht.v
├── jpeg_dht_std_cx_ac.v
├── jpeg_dht_std_cx_dc.v
├── jpeg_dht_std_y_ac.v
├── jpeg_dht_std_y_dc.v
├── jpeg_dqt.v
├── jpeg_idct.v
├── jpeg_idct_fifo.v
├── jpeg_idct_ram.v
├── jpeg_idct_ram_dp.v
├── jpeg_idct_transpose.v
├── jpeg_idct_transpose_ram.v
├── jpeg_idct_x.v
├── jpeg_idct_y.v
├── jpeg_input.v
├── jpeg_mcu_id.v
├── jpeg_mcu_proc.v
├── jpeg_output.v
├── jpeg_output_cx_ram.v
├── jpeg_output_fifo.v
└── jpeg_output_y_ram.v
================================================
FILE CONTENTS
================================================
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.
================================================
FILE: README.md
================================================
# High throughput JPEG decoder
Github: [https://github.com/ultraembedded/core_jpeg](https://github.com/ultraembedded/core_jpeg)
This project is a JPEG decoder core for FPGA written in Verilog.

## Features
* Baseline JPEG Decoder IP (sequential encoded images).
* 32-bit AXI Stream input.
* Input format: JPEG (JPEG File Interchange Format)
* Output format: 24-bit RGB output in 8x8 blocks (row-major ordering).
* Support for Monochrome, 4:4:4, 4:2:0 chroma subsampling support.
* Support for fixed standard Huffman tables (reduced logic usage, fast).
* Support for dynamic Huffman tables (from JPEG input stream -> slower decode, more logic).
* Dynamic DQT tables from JPEG input stream.
* Synthesizable Verilog 2001, Verilator and FPGA friendly.
* Multipliers and tables / FIFO's map efficiently to FPGA resources (DSP48, blockRAM, etc).
* Verified using co-simulation against a C-model and tested on FPGA with thousands of images.
## Design Aims
1. Fast decode performance suitable for video playback
2. Support a minimal JPEG baseline feature set.
3. Be well tested (with verification against a reference C-model).
4. Map to FPGA resources such as BlockRAM, DSP macros wherever possible.
## FPGA Mapping
The current version of the JPEG decoder uses the following resources on a Xilinx 7 series FPGA (post-implementation);

The design is also able to meet timing >= 75MHz.
## Performance
Peak JPEG decode performance is as follows;
* Monochrome = 66 cycles per 8x8 pixels (1.0 cycles per pixel)
* YCbCr 4:2:0 = 137 cycles per 8x8 pixels (2.1 cycles per pixel)
* YCbCr 4:4:4 = 198 cycles per 8x8 pixels (3.1 cycles per pixel)
## Use Case
The purpose of this design was to replace a 3rd party JPEG decoder core used in my [Motion JPEG](https://en.wikipedia.org/wiki/Motion_JPEG) based [FPGA video player](https://github.com/ultraembedded/FPGAmp).
Motion JPEG has worse compression performance than MPEG based video, but the complexity of the HW required is low enough that it can be used on low(-ish)-end FPGAs.
Video playback usually requires at least 25 frames per second, hence there is a budget of less than 40ms per JPEG frame.
This fact drives the design choices taken for this implementation.
Clearly, the higher the resolution, the more pixels that must be produced from the JPEG decoder within that 40ms budget, so this core is designed to have high throughput in the output stages - with additional resources dedicated to the IDCT transform, and output re-ordering stages to facilitate this.
## Limitations
The current release does not support;
* Restart markers
* 4:2:2 H/V chroma subsampling (only 4:4:4 and 4:2:0 are supported).
Under the GNU Image Manipulation Program, the following 'X' options are **not** supported currently;

Note: Support for 'optimised' Huffman tables is possible when design parameter SUPPORT_WRITABLE_DHT=1.
This functionality increases the core size substantially and reduces performance.
## Future Work / TODO
* Add support for the first layer of progressive JPEG images.
* Add option to reduce arithmetic precision to reduce design size.
* Add lightweight variant of the core with reduced performance (for smaller FPGAs).
================================================
FILE: c_model/README.md
================================================
## JPEG Decoder C Model
This a simple C model of a JPEG decoder that can decode baseline JPEG images.
The purpose of this is to provide a reference to test the digital HW design against.
It supports;
* YCbCr 4:4:4 (no chroma subsampling), 4:2:0 and monochrome images.
* Conversion to a bitmap file (PPM / P6 format).
* Optimised (Huffman tables) images.
It does not support (currently);
* Progressive
* YCbCr 4:2:2 chroma subsampling
* Restart markers
* App data, COM sections, will be ignored.
### Building / Usage
```
# Build
make
# Run
./jpeg my_image.jpg bitmap.ppm
```
================================================
FILE: c_model/jpeg_bit_buffer.h
================================================
#ifndef JPEG_BIT_BUFFER_H
#define JPEG_BIT_BUFFER_H
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#define dprintf
#ifndef TEST_HOOKS_BITBUFFER
#define TEST_HOOKS_BITBUFFER(x)
#endif
#ifndef TEST_HOOKS_BITBUFFER_DECL
#define TEST_HOOKS_BITBUFFER_DECL
#endif
//-----------------------------------------------------------------------------
// jpeg_bit_buffer:
//-----------------------------------------------------------------------------
class jpeg_bit_buffer
{
public:
jpeg_bit_buffer()
{
m_buffer = NULL;
reset(-1);
}
void reset(int max_size = -1)
{
if (m_buffer)
{
delete [] m_buffer;
m_buffer = NULL;
}
if (max_size <= 0)
m_max_size = 1 << 20;
else
m_max_size = max_size;
m_buffer = new uint8_t[m_max_size];
memset(m_buffer, 0, m_max_size);
m_wr_offset = 0;
m_last = 0;
m_rd_offset = 0;
}
// Push byte into stream (return false if marker found)
bool push(uint8_t b)
{
uint8_t last = m_last;
// Skip padding
if (last == 0xFF && b == 0x00)
;
// Marker found
else if (last == 0xFF && b != 0x00)
{
m_wr_offset--;
return false;
}
// Push byte into buffer
else
{
assert(m_wr_offset < m_max_size);
m_buffer[m_wr_offset++] = b;
}
m_last = b;
return true;
}
// Read upto 32-bit (aligned to MSB)
uint32_t read_word(void)
{
if (eof())
return 0;
int byte = m_rd_offset / 8;
int bit = m_rd_offset % 8; // 0 - 7
uint64_t w = 0;
for (int x=0;x<5;x++)
{
w |= m_buffer[byte+x];
w <<= 8;
}
w <<= bit;
return w >> 16;
}
void advance(int bits)
{
TEST_HOOKS_BITBUFFER(bits);
m_rd_offset += bits;
}
bool eof(void)
{
return (((m_rd_offset+7) / 8) >= m_wr_offset);
}
TEST_HOOKS_BITBUFFER_DECL;
private:
uint8_t *m_buffer;
uint8_t m_last;
int m_max_size;
int m_wr_offset;
int m_rd_offset; // in bits
};
#endif
================================================
FILE: c_model/jpeg_dht.h
================================================
#ifndef JPEG_DHT_H
#define JPEG_DHT_H
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#define DHT_TABLE_Y_DC 0x00
#define DHT_TABLE_Y_DC_IDX 0
#define DHT_TABLE_Y_AC 0x10
#define DHT_TABLE_Y_AC_IDX 1
#define DHT_TABLE_CX_DC 0x01
#define DHT_TABLE_CX_DC_IDX 2
#define DHT_TABLE_CX_AC 0x11
#define DHT_TABLE_CX_AC_IDX 3
#define dprintf
//-----------------------------------------------------------------------------
// jpeg_dqt:
//-----------------------------------------------------------------------------
class jpeg_dht
{
public:
jpeg_dht() { reset(); }
void reset(void)
{
for (int i=0;i<4;i++)
memset(&m_dht_table[i], 0, sizeof(t_huffman_table));
}
int process(uint8_t *data, int len)
{
uint8_t *buf = data;
int consumed = 0;
// DHT tables can be combined into one section (it seems)
while (consumed <= (len-17))
{
// Huffman table info, first four MSBs represent table type (0 for DC, 1 for AC), last four LSBs represent table #
uint8_t table_info = *buf++;
int table_idx = 0;
switch (table_info)
{
case DHT_TABLE_Y_DC:
table_idx = DHT_TABLE_Y_DC_IDX;
break;
case DHT_TABLE_Y_AC:
table_idx = DHT_TABLE_Y_AC_IDX;
break;
case DHT_TABLE_CX_DC:
table_idx = DHT_TABLE_CX_DC_IDX;
break;
case DHT_TABLE_CX_AC:
table_idx = DHT_TABLE_CX_AC_IDX;
break;
default:
assert(!"ERROR: Bad JPEG");
break;
}
dprintf("DHT (Table idx %d)\n", table_idx);
// Reset table
memset(&m_dht_table[table_idx], 0, sizeof(m_dht_table[0]));
// Extract symbol count
uint8_t symb_count[16];
for (int x=0;x<16;x++)
{
symb_count[x] = *buf++;
dprintf(" bit length: %d, symbols: %d\n", x, symb_count[x]);
}
// Extract table values
// Build the Huffman map of (length, code) -> value
uint16_t code = 0;
int entry = 0;
for (int x=0;x<16;x++)
{
for (int j=0;j<symb_count[x];j++)
{
uint8_t dht_val = *buf++;
m_dht_table[table_idx].code[entry] = code;
m_dht_table[table_idx].code_len[entry] = x+1;
m_dht_table[table_idx].value[entry++] = dht_val;
dprintf(" %d: %x -> %x\n", entry, code, dht_val);
code++;
}
code <<= 1;
}
m_dht_table[table_idx].entries = entry;
consumed = buf - data;
}
return buf - data;
}
// lookup: Perform huffman lookup (starting from bit 15 of w)
int lookup(int table_idx, uint16_t w, uint8_t &value)
{
for (int i=0;i<m_dht_table[table_idx].entries;i++)
{
int width = m_dht_table[table_idx].code_len[i];
uint16_t bitmap = m_dht_table[table_idx].code[i];
uint16_t shift_val = w >> (16-width);
//printf("- %d: check against %04x ", width, shift_val);
//print_bin(shift_val, width);
//printf(" == %04x -> %02x\n", bitmap, value);
if (shift_val == bitmap)
{
value = m_dht_table[table_idx].value[i];
return width;
}
}
return 0;
}
private:
typedef struct
{
// 16-bit (max) code
uint16_t code[255];
// Code length
uint8_t code_len[255];
// Value to translate to
uint8_t value[255];
int entries;
} t_huffman_table;
t_huffman_table m_dht_table[4];
};
#endif
================================================
FILE: c_model/jpeg_dqt.h
================================================
#ifndef JPEG_DQT_H
#define JPEG_DQT_H
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
// Zigzag table
static const int m_zigzag_table[]=
{
0, 1, 8, 16,9, 2, 3,10,
17,24,32,25,18,11, 4, 5,
12,19,26,33,40,48,41,34,
27,20,13, 6, 7,14,21,28,
35,42,49,56,57,50,43,36,
29,22,15,23,30,37,44,51,
58,59,52,45,38,31,39,46,
53,60,61,54,47,55,62,63,
0
};
#define dprintf
//-----------------------------------------------------------------------------
// jpeg_dqt:
//-----------------------------------------------------------------------------
class jpeg_dqt
{
public:
jpeg_dqt() { reset(); }
//-------------------------------------------------------------------------
// reset: Reset DQT tables
//-------------------------------------------------------------------------
void reset(void)
{
memset(&m_table_dqt[0], 0, 64 * 4);
}
//-------------------------------------------------------------------------
// process: Store DQT table from input stream
//-------------------------------------------------------------------------
int process(uint8_t *data, int len)
{
uint8_t *buf = data;
// Table number
uint8_t table_num = (*buf++) & 0x3;
dprintf(" DQT: Table %d\n", table_num);
for (int x=0;x<64;x++)
{
// 8-bit
uint8_t qv = *buf++;
dprintf(" %d: %x\n", x, qv);
m_table_dqt[table_num][x] = qv;
}
return buf - data;
}
//-------------------------------------------------------------------------
// lookup: DQT table entry lookup
//-------------------------------------------------------------------------
uint8_t lookup(int table_num, int position)
{
return m_table_dqt[table_num][position];
}
//-------------------------------------------------------------------------
// process_samples: Multiply out samples and de-zigzag ready for IDCT
// samples: (idx, value)
//-------------------------------------------------------------------------
void process_samples(int quant_table, int *sample_in, int *block_out, int count)
{
// Apply quantisation and zigzag
memset(block_out, 0, sizeof(block_out[0])*64);
for (int i=0;i<count;i++)
{
int16_t smpl = (int16_t)(sample_in[i] & 0xFFFF);
int block_idx = (sample_in[i] >> 16);
dprintf("DEQ: %d: %d * %d -> %d @ %d\n", block_idx, smpl, lookup(quant_table,block_idx), smpl * lookup(quant_table,block_idx), m_zigzag_table[block_idx]);
block_out[m_zigzag_table[block_idx]] = smpl * lookup(quant_table,block_idx);
}
}
private:
uint8_t m_table_dqt[4][64];
};
#endif
================================================
FILE: c_model/jpeg_idct.h
================================================
#ifndef JPEG_IDCT_H
#define JPEG_IDCT_H
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
//-----------------------------------------------------------------------------
// jpeg_idct:
//-----------------------------------------------------------------------------
class jpeg_idct
{
public:
jpeg_idct() { reset(); }
void reset(void) { }
//-----------------------------------------------------------------------------
// process: Perform inverse DCT on already dequantized data.
// [Not quite sure who to attribute this implementation to...]
//-----------------------------------------------------------------------------
void process(int *data_in, int *data_out)
{
int s0,s1,s2,s3,s4,s5,s6,s7;
int t0,t1,t2,t3,t4,t5,t6,t7;
int working_buf[64];
int *temp_buf = working_buf;
// X - Rows
for(int i=0;i<8;i++)
{
s0 = (data_in[0] + data_in[4]) * C4;
s1 = (data_in[0] - data_in[4]) * C4;
s3 = (data_in[2] * C2) + (data_in[6] * C6);
s2 = (data_in[2] * C6) - (data_in[6] * C2);
s7 = (data_in[1] * C1) + (data_in[7] * C7);
s4 = (data_in[1] * C7) - (data_in[7] * C1);
s6 = (data_in[5] * C5) + (data_in[3] * C3);
s5 = (data_in[5] * C3) - (data_in[3] * C5);
// Next row
data_in += 8;
t0 = s0 + s3;
t3 = s0 - s3;
t1 = s1 + s2;
t2 = s1 - s2;
t4 = s4 + s5;
t5 = s4 - s5;
t7 = s7 + s6;
t6 = s7 - s6;
s6 = (t5 + t6) * 181 / 256; // 1/sqrt(2)
s5 = (t6 - t5) * 181 / 256; // 1/sqrt(2)
*temp_buf++ = (t0 + t7) >> 11;
*temp_buf++ = (t1 + s6) >> 11;
*temp_buf++ = (t2 + s5) >> 11;
*temp_buf++ = (t3 + t4) >> 11;
*temp_buf++ = (t3 - t4) >> 11;
*temp_buf++ = (t2 - s5) >> 11;
*temp_buf++ = (t1 - s6) >> 11;
*temp_buf++ = (t0 - t7) >> 11;
}
// Y - Columns
temp_buf = working_buf;
for(int i=0;i<8;i++)
{
s0 = (temp_buf[0] + temp_buf[32]) * C4;
s1 = (temp_buf[0] - temp_buf[32]) * C4;
s3 = temp_buf[16] * C2 + temp_buf[48] * C6;
s2 = temp_buf[16] * C6 - temp_buf[48] * C2;
s7 = temp_buf[8] * C1 + temp_buf[56] * C7;
s4 = temp_buf[8] * C7 - temp_buf[56] * C1;
s6 = temp_buf[40] * C5 + temp_buf[24] * C3;
s5 = temp_buf[40] * C3 - temp_buf[24] * C5;
t0 = s0 + s3;
t1 = s1 + s2;
t2 = s1 - s2;
t3 = s0 - s3;
t4 = s4 + s5;
t5 = s4 - s5;
t6 = s7 - s6;
t7 = s6 + s7;
s5 = (t6 - t5) * 181 / 256; // 1/sqrt(2)
s6 = (t5 + t6) * 181 / 256; // 1/sqrt(2)
data_out[0] = ((t0 + t7) >> 15);
data_out[56] = ((t0 - t7) >> 15);
data_out[8] = ((t1 + s6) >> 15);
data_out[48] = ((t1 - s6) >> 15);
data_out[16] = ((t2 + s5) >> 15);
data_out[40] = ((t2 - s5) >> 15);
data_out[24] = ((t3 + t4) >> 15);
data_out[32] = ((t3 - t4) >> 15);
temp_buf++;
data_out++;
}
data_out -= 8;
}
static const int C1 = 4017; // cos( pi/16) x4096
static const int C2 = 3784; // cos(2pi/16) x4096
static const int C3 = 3406; // cos(3pi/16) x4096
static const int C4 = 2896; // cos(4pi/16) x4096
static const int C5 = 2276; // cos(5pi/16) x4096
static const int C6 = 1567; // cos(6pi/16) x4096
static const int C7 = 799; // cos(7pi/16) x4096
};
#endif
================================================
FILE: c_model/jpeg_mcu_block.h
================================================
#ifndef JPEG_MCU_BLOCK_H
#define JPEG_MCU_BLOCK_H
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include "jpeg_bit_buffer.h"
#include "jpeg_dht.h"
#define dprintf
//-----------------------------------------------------------------------------
// jpeg_mcu_block:
//-----------------------------------------------------------------------------
class jpeg_mcu_block
{
public:
jpeg_mcu_block(jpeg_bit_buffer *bit_buf, jpeg_dht *dht)
{
m_bit_buffer = bit_buf;
m_dht = dht;
reset();
}
void reset(void) { }
//-----------------------------------------------------------------------------
// decode: Run huffman entropy decoder on input stream, expand to DC + upto
// 63 AC samples.
//-----------------------------------------------------------------------------
int decode(int table_idx, int16_t &olddccoeff, int32_t *block_out)
{
int samples = 0;
for (int coeff=0;coeff<64;coeff++)
{
// Read 32-bit word
uint32_t input_word = m_bit_buffer->read_word();
// Start with upper 16-bits
uint16_t input_data = input_word >> 16;
// Perform huffman decode on input data (code=RLE,num_bits)
uint8_t code = 0;
int code_width = m_dht->lookup(table_idx + (coeff != 0), input_data, code);
int coef_bits = code & 0xF;
// Move input point past decoded data
if (coeff == 0)
m_bit_buffer->advance(code_width + coef_bits);
// End of block or ZRL (no coefficient)
else if (code == 0 || code == 0xF0)
m_bit_buffer->advance(code_width);
else
m_bit_buffer->advance(code_width + coef_bits);
// Use remaining data for actual coeffecient
input_data = input_word >> (16 - code_width);
// DC
if (coeff == 0)
{
input_data >>= (16 - code);
int16_t dcoeff = decode_number(input_data, coef_bits) + olddccoeff;
olddccoeff = dcoeff;
block_out[samples++] = (0 << 16) | (dcoeff & 0xFFFF);
}
// AC
else
{
// End of block
if (code == 0)
{
dprintf("SMPL: EOB\n");
coeff = 64;
break;
}
// The first part of the AC key_len is the number of leading zeros
if (code == 0xF0)
{
// When the ZRL code comes, it is regarded as 15 zero data
dprintf("SMPL: ZRL\n");
coeff += 15; // +1 in the loop
continue;
}
else if (code > 15)
coeff += code >> 4;
input_data >>= (16 - coef_bits);
if (coeff < 64)
{
int16_t acoeff = decode_number(input_data, coef_bits);
block_out[samples++] = (coeff << 16) | (acoeff & 0xFFFF);
}
}
}
return samples;
}
private:
//-----------------------------------------------------------------------------
// decode_number: Extract number from code / width
//-----------------------------------------------------------------------------
int16_t decode_number(uint16_t code, int bits)
{
if (!(code & (1<<(bits-1))) && bits != 0)
{
code |= (~0) << bits;
code += 1;
}
return code;
}
private:
jpeg_bit_buffer *m_bit_buffer;
jpeg_dht *m_dht;
};
#endif
================================================
FILE: c_model/main.cpp
================================================
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include "jpeg_dqt.h"
#include "jpeg_dht.h"
#include "jpeg_idct.h"
#include "jpeg_bit_buffer.h"
#include "jpeg_mcu_block.h"
static jpeg_dqt m_dqt;
static jpeg_dht m_dht;
static jpeg_idct m_idct;
static jpeg_bit_buffer m_bit_buffer;
static jpeg_mcu_block m_mcu_dec(&m_bit_buffer, &m_dht);
static uint16_t m_width;
static uint16_t m_height;
typedef enum eJpgMode
{
JPEG_MONOCHROME,
JPEG_YCBCR_444,
JPEG_YCBCR_420,
JPEG_UNSUPPORTED
} t_jpeg_mode;
static t_jpeg_mode m_mode;
static uint8_t m_dqt_table[3];
#define get_byte(_buf, _idx) _buf[_idx++]
#define get_word(_buf, _idx) ((_buf[_idx++] << 8) | (_buf[_idx++]))
static uint8_t *m_output_r;
static uint8_t *m_output_g;
static uint8_t *m_output_b;
#define dprintf
#define dprintf_blk(_name, _arr, _max) for (int __i=0;__i<_max;__i++) { dprintf("%s: %d -> %d\n", _name, __i, _arr[__i]); }
//-----------------------------------------------------------------------------
// ConvertYUV2RGB: Convert from YUV to RGB
//-----------------------------------------------------------------------------
static void ConvertYUV2RGB(int block_num, int *y, int *cb, int *cr)
{
int x_blocks = (m_width / 8);
// If width is not a multiple of 8, round up
if (m_width % 8)
x_blocks++;
int x_start = (block_num % x_blocks) * 8;
int y_start = (block_num / x_blocks) * 8;
if (m_mode == JPEG_MONOCHROME)
{
for (int i=0;i<64;i++)
{
int r = 128 + y[i];
int g = 128 + y[i];
int b = 128 + y[i];
// Avoid overflows
r = (r & 0xffffff00) ? (r >> 24) ^ 0xff : r;
g = (g & 0xffffff00) ? (g >> 24) ^ 0xff : g;
b = (b & 0xffffff00) ? (b >> 24) ^ 0xff : b;
int _x = x_start + (i % 8);
int _y = y_start + (i / 8);
int offset = (_y * m_width) + _x;
dprintf("RGB: r=%d g=%d b=%d -> %d\n", r, g, b, offset);
m_output_r[offset] = r;
m_output_g[offset] = g;
m_output_b[offset] = b;
}
}
else
{
for (int i=0;i<64;i++)
{
int r = 128 + y[i] + (cr[i] * 1.402);
int g = 128 + y[i] - (cb[i] * 0.34414) - (cr[i] * 0.71414);
int b = 128 + y[i] + (cb[i] * 1.772);
// Avoid overflows
r = (r & 0xffffff00) ? (r >> 24) ^ 0xff : r;
g = (g & 0xffffff00) ? (g >> 24) ^ 0xff : g;
b = (b & 0xffffff00) ? (b >> 24) ^ 0xff : b;
int _x = x_start + (i % 8);
int _y = y_start + (i / 8);
int offset = (_y * m_width) + _x;
if (_x < m_width && _y < m_height)
{
dprintf("RGB: r=%d g=%d b=%d -> %d [x=%d,y=%d]\n", r, g, b, offset, _x, _y);
m_output_r[offset] = r;
m_output_g[offset] = g;
m_output_b[offset] = b;
}
}
}
}
//-----------------------------------------------------------------------------
// DecodeImage: Decode image data section (supports 4:4:4, 4:2:0, monochrom)
//-----------------------------------------------------------------------------
static bool DecodeImage(void)
{
int16_t dc_coeff_Y = 0;
int16_t dc_coeff_Cb= 0;
int16_t dc_coeff_Cr= 0;
int32_t sample_out[64];
int block_out[64];
int y_dct_out[4*64];
int cb_dct_out[64];
int cr_dct_out[64];
int count = 0;
int loop = 0;
int block_num = 0;
while (!m_bit_buffer.eof())
{
// [Y0 Y1 Y2 Y3 Cb Cr] x N
if (m_mode == JPEG_YCBCR_420)
{
// Y0
count = m_mcu_dec.decode(DHT_TABLE_Y_DC_IDX, dc_coeff_Y, sample_out);
m_dqt.process_samples(m_dqt_table[0], sample_out, block_out, count);
dprintf_blk("DCT-IN", block_out, 64);
m_idct.process(block_out, &y_dct_out[0]);
// Y1
count = m_mcu_dec.decode(DHT_TABLE_Y_DC_IDX, dc_coeff_Y, sample_out);
m_dqt.process_samples(m_dqt_table[0], sample_out, block_out, count);
dprintf_blk("DCT-IN", block_out, 64);
m_idct.process(block_out, &y_dct_out[64]);
// Y2
count = m_mcu_dec.decode(DHT_TABLE_Y_DC_IDX, dc_coeff_Y, sample_out);
m_dqt.process_samples(m_dqt_table[0], sample_out, block_out, count);
dprintf_blk("DCT-IN", block_out, 64);
m_idct.process(block_out, &y_dct_out[128]);
// Y3
count = m_mcu_dec.decode(DHT_TABLE_Y_DC_IDX, dc_coeff_Y, sample_out);
m_dqt.process_samples(m_dqt_table[0], sample_out, block_out, count);
dprintf_blk("DCT-IN", block_out, 64);
m_idct.process(block_out, &y_dct_out[192]);
// Cb
count = m_mcu_dec.decode(DHT_TABLE_CX_DC_IDX, dc_coeff_Cb, sample_out);
m_dqt.process_samples(m_dqt_table[1], sample_out, block_out, count);
dprintf_blk("DCT-IN", block_out, 64);
m_idct.process(block_out, &cb_dct_out[0]);
// Cr
count = m_mcu_dec.decode(DHT_TABLE_CX_DC_IDX, dc_coeff_Cr, sample_out);
m_dqt.process_samples(m_dqt_table[2], sample_out, block_out, count);
dprintf_blk("DCT-IN", block_out, 64);
m_idct.process(block_out, &cr_dct_out[0]);
// Expand Cb/Cr samples to match Y0-3
int cb_dct_out_x2[256];
int cr_dct_out_x2[256];
for (int i=0;i<64;i++)
{
int x = i % 8;
int y = i / 16;
int sub_idx = (y * 8) + (x / 2);
cb_dct_out_x2[i] = cb_dct_out[sub_idx];
cr_dct_out_x2[i] = cr_dct_out[sub_idx];
}
for (int i=0;i<64;i++)
{
int x = i % 8;
int y = i / 16;
int sub_idx = (y * 8) + 4 + (x / 2);
cb_dct_out_x2[64 + i] = cb_dct_out[sub_idx];
cr_dct_out_x2[64 + i] = cr_dct_out[sub_idx];
}
for (int i=0;i<64;i++)
{
int x = i % 8;
int y = i / 16;
int sub_idx = 32 + (y * 8) + (x / 2);
cb_dct_out_x2[128+i] = cb_dct_out[sub_idx];
cr_dct_out_x2[128+i] = cr_dct_out[sub_idx];
}
for (int i=0;i<64;i++)
{
int x = i % 8;
int y = i / 16;
int sub_idx = 32 + (y * 8) + 4 + (x / 2);
cb_dct_out_x2[192 + i] = cb_dct_out[sub_idx];
cr_dct_out_x2[192 + i] = cr_dct_out[sub_idx];
}
int mcu_width = m_width / 8;
if (m_width % 8)
mcu_width++;
// Output all 4 blocks of pixels
ConvertYUV2RGB((block_num/2) + 0, &y_dct_out[0], &cb_dct_out_x2[0], &cr_dct_out_x2[0]);
ConvertYUV2RGB((block_num/2) + 1, &y_dct_out[64], &cb_dct_out_x2[64], &cr_dct_out_x2[64]);
ConvertYUV2RGB((block_num/2) + mcu_width + 0, &y_dct_out[128], &cb_dct_out_x2[128], &cr_dct_out_x2[128]);
ConvertYUV2RGB((block_num/2) + mcu_width + 1, &y_dct_out[192], &cb_dct_out_x2[192], &cr_dct_out_x2[192]);
block_num += 4;
if (++loop == (mcu_width / 2))
{
block_num += (mcu_width * 2);
loop = 0;
}
}
// [Y Cb Cr] x N
else if (m_mode == JPEG_YCBCR_444)
{
// Y
count = m_mcu_dec.decode(DHT_TABLE_Y_DC_IDX, dc_coeff_Y, sample_out);
m_dqt.process_samples(m_dqt_table[0], sample_out, block_out, count);
dprintf_blk("DCT-IN", block_out, 64);
m_idct.process(block_out, &y_dct_out[0]);
// Cb
count = m_mcu_dec.decode(DHT_TABLE_CX_DC_IDX, dc_coeff_Cb, sample_out);
m_dqt.process_samples(m_dqt_table[1], sample_out, block_out, count);
dprintf_blk("DCT-IN", block_out, 64);
m_idct.process(block_out, &cb_dct_out[0]);
// Cr
count = m_mcu_dec.decode(DHT_TABLE_CX_DC_IDX, dc_coeff_Cr, sample_out);
m_dqt.process_samples(m_dqt_table[2], sample_out, block_out, count);
dprintf_blk("DCT-IN", block_out, 64);
m_idct.process(block_out, &cr_dct_out[0]);
ConvertYUV2RGB(block_num++, y_dct_out, cb_dct_out, cr_dct_out);
}
// [Y] x N
else if (m_mode == JPEG_MONOCHROME)
{
// Y
count = m_mcu_dec.decode(DHT_TABLE_Y_DC_IDX, dc_coeff_Y, sample_out);
m_dqt.process_samples(m_dqt_table[0], sample_out, block_out, count);
dprintf_blk("DCT-IN", block_out, 64);
m_idct.process(block_out, &y_dct_out[0]);
ConvertYUV2RGB(block_num++, y_dct_out, cb_dct_out, cr_dct_out);
}
}
return true;
}
//-----------------------------------------------------------------------------
// main:
//-----------------------------------------------------------------------------
int main(int argc, char* argv[])
{
if (argc < 3)
{
printf("./jpeg src_image.jpg dst_image.ppm\n");
return -1;
}
const char *src_image = argv[1];
const char *dst_image = argv[2];
// Load source file
uint8_t *buf = NULL;
int len = 0;
FILE *f = fopen(src_image, "rb");
if (f)
{
long size;
// Get size
fseek(f, 0, SEEK_END);
size = ftell(f);
rewind(f);
// Read file data in
buf = (uint8_t*)malloc(size);
assert(buf);
len = fread(buf, 1, size, f);
fclose(f);
}
else
{
printf("./jpeg src_image.jpg dst_image.ppm\n");
return -1;
}
m_dqt.reset();
m_dht.reset();
m_idct.reset();
m_mode = JPEG_UNSUPPORTED;
m_output_r = NULL;
m_output_g = NULL;
m_output_b = NULL;
uint8_t last_b = 0;
bool decode_done = false;
for (int i=0;i<len;)
{
uint8_t b = buf[i++];
//-----------------------------------------------------------------------------
// SOI: Start of image
//-----------------------------------------------------------------------------
if (last_b == 0xFF && b == 0xd8)
printf("Section: SOI\n");
//-----------------------------------------------------------------------------
// SOF0: Indicates that this is a baseline DCT-based JPEG
//-----------------------------------------------------------------------------
else if (last_b == 0xFF && b == 0xc0)
{
printf("Section: SOF0\n");
int seg_start = i;
// Length of the segment
uint16_t seg_len = get_word(buf, i);
// Precision of the frame data
uint8_t precision = get_byte(buf,i);
// Image height in pixels
m_height = get_word(buf, i);
// Image width in pixels
m_width = get_word(buf, i);
// Allocate pixel buffer
m_output_r = new uint8_t[m_height * m_width];
m_output_g = new uint8_t[m_height * m_width];
m_output_b = new uint8_t[m_height * m_width];
memset(m_output_r, 0, m_height * m_width);
memset(m_output_g, 0, m_height * m_width);
memset(m_output_b, 0, m_height * m_width);
// # of components (n) in frame, 1 for monochrom, 3 for colour images
uint8_t num_comps = get_byte(buf,i);
assert(num_comps <= 3);
printf(" x=%d, y=%d, components=%d\n", m_width, m_height, num_comps);
uint8_t comp_id[3];
uint8_t comp_sample_factor[3];
uint8_t horiz_factor[3];
uint8_t vert_factor[3];
for (int x=0;x<num_comps;x++)
{
// First byte identifies the component
comp_id[x] = get_byte(buf,i);
// id: 1 = Y, 2 = Cb, 3 = Cr
// Second byte represents sampling factor (first four MSBs represent horizonal, last four LSBs represent vertical)
comp_sample_factor[x] = get_byte(buf,i);
horiz_factor[x] = comp_sample_factor[x] >> 4;
vert_factor[x] = comp_sample_factor[x] & 0xF;
// Third byte represents which quantization table to use for this component
m_dqt_table[x] = get_byte(buf,i);
printf(" num: %d a: %02x b: %02x\n", comp_id[x], comp_sample_factor[x], m_dqt_table[x]);
printf(" horiz_factor: %d, vert_factor: %d\n", horiz_factor[x], vert_factor[x]);
}
m_mode = JPEG_UNSUPPORTED;
// Single component (Y)
if (num_comps == 1)
{
printf(" Mode: Monochrome\n");
m_mode = JPEG_MONOCHROME;
}
// Colour image (YCbCr)
else if (num_comps == 3)
{
// YCbCr ordering expected
if (comp_id[0] == 1 && comp_id[1] == 2 && comp_id[2] == 3)
{
if (horiz_factor[0] == 1 && vert_factor[0] == 1 &&
horiz_factor[1] == 1 && vert_factor[1] == 1 &&
horiz_factor[2] == 1 && vert_factor[2] == 1)
{
m_mode = JPEG_YCBCR_444;
printf(" Mode: YCbCr 4:4:4\n");
}
else if (horiz_factor[0] == 2 && vert_factor[0] == 2 &&
horiz_factor[1] == 1 && vert_factor[1] == 1 &&
horiz_factor[2] == 1 && vert_factor[2] == 1)
{
m_mode = JPEG_YCBCR_420;
printf(" Mode: YCbCr 4:2:0\n");
}
}
}
i = seg_start + seg_len;
}
//-----------------------------------------------------------------------------
// DQT: Quantisation table
//-----------------------------------------------------------------------------
else if (last_b == 0xFF && b == 0xdb)
{
printf("Section: DQT Table\n");
int seg_start = i;
uint16_t seg_len = get_word(buf, i);
m_dqt.process(&buf[i], seg_len);
i = seg_start + seg_len;
}
//-----------------------------------------------------------------------------
// DHT: Huffman table
//-----------------------------------------------------------------------------
else if (last_b == 0xFF && b == 0xc4)
{
int seg_start = i;
uint16_t seg_len = get_word(buf, i);
printf("Section: DHT Table\n");
m_dht.process(&buf[i], seg_len);
i = seg_start + seg_len;
}
//-----------------------------------------------------------------------------
// EOI: End of image
//-----------------------------------------------------------------------------
else if (last_b == 0xFF && b == 0xd9)
{
printf("Section: EOI\n");
break;
}
//-----------------------------------------------------------------------------
// SOS: Start of Scan Segment (SOS)
//-----------------------------------------------------------------------------
else if (last_b == 0xFF && b == 0xda)
{
printf("Section: SOS\n");
int seg_start = i;
if (m_mode == JPEG_UNSUPPORTED)
{
printf("ERROR: Unsupported JPEG mode\n");
break;
}
uint16_t seg_len = get_word(buf, i);
// Component count (n)
uint8_t comp_count = get_byte(buf,i);
// Component data
for (int x=0;x<comp_count;x++)
{
// First byte denotes component ID
uint8_t comp_id = get_byte(buf,i);
// Second byte denotes the Huffman table used (first four MSBs denote Huffman table for DC, and last four LSBs denote Huffman table for AC)
uint8_t comp_table = get_byte(buf,i);
printf(" %d: ID=%x Table=%x\n", x, comp_id, comp_table);
}
// Skip bytes
get_byte(buf,i);
get_byte(buf,i);
get_byte(buf,i);
i = seg_start + seg_len;
//-----------------------------------------------------------------------
// Process data segment
//-----------------------------------------------------------------------
m_bit_buffer.reset(len);
while (i < len)
{
b = buf[i];
if (m_bit_buffer.push(b))
i++;
// Marker detected (reverse one byte)
else
{
i--;
break;
}
}
decode_done = DecodeImage();
}
//-----------------------------------------------------------------------------
// Unsupported / Skipped
//-----------------------------------------------------------------------------
else if (last_b == 0xFF && b == 0xc2)
{
printf("Section: SOF2\n");
int seg_start = i;
uint16_t seg_len = get_word(buf, i);
i = seg_start + seg_len;
printf("ERROR: Progressive JPEG not supported\n");
break; // ERROR: Not supported
}
else if (last_b == 0xFF && b == 0xdd)
{
printf("Section: DRI\n");
int seg_start = i;
uint16_t seg_len = get_word(buf, i);
i = seg_start + seg_len;
}
else if (last_b == 0xFF && b >= 0xd0 && b <= 0xd7)
{
printf("Section: RST%d\n", b - 0xd0);
int seg_start = i;
uint16_t seg_len = get_word(buf, i);
i = seg_start + seg_len;
}
else if (last_b == 0xFF && b >= 0xe0 && b <= 0xef)
{
printf("Section: APP%d\n", b - 0xe0);
int seg_start = i;
uint16_t seg_len = get_word(buf, i);
i = seg_start + seg_len;
}
else if (last_b == 0xFF && b == 0xfe)
{
printf("Section: COM\n");
int seg_start = i;
uint16_t seg_len = get_word(buf, i);
i = seg_start + seg_len;
}
last_b = b;
}
if (decode_done)
{
FILE *f = fopen(dst_image, "w");
if (f)
{
fprintf(f, "P6\n");
fprintf(f, "%d %d\n", m_width, m_height);
fprintf(f, "255\n");
for (int y=0;y<m_height;y++)
for (int x=0;x<m_width;x++)
{
putc(m_output_r[(y*m_width)+x], f);
putc(m_output_g[(y*m_width)+x], f);
putc(m_output_b[(y*m_width)+x], f);
}
fclose(f);
}
else
{
fprintf(stderr, "ERROR: Could not write file\n");
decode_done = false;
}
}
if (m_output_r) delete [] m_output_r;
if (m_output_g) delete [] m_output_g;
if (m_output_b) delete [] m_output_b;
return decode_done ? 0 : -1;
}
================================================
FILE: c_model/makefile
================================================
###############################################################################
# Makefile
###############################################################################
# Target
TARGET ?= jpeg
# Source Files
SRC_DIR = .
CFLAGS = -O2 -fPIC
CFLAGS += -Wno-format
INCLUDE_PATH += $(SRC_DIR)
CFLAGS += $(patsubst %,-I%,$(INCLUDE_PATH))
LDFLAGS =
LIBS =
###############################################################################
# Variables
###############################################################################
OBJ_DIR ?= obj/
###############################################################################
# Variables: Lists of objects, source and deps
###############################################################################
# SRC / Object list
src2obj = $(OBJ_DIR)$(patsubst %$(suffix $(1)),%.o,$(notdir $(1)))
SRC ?= $(foreach src,$(SRC_DIR),$(wildcard $(src)/*.cpp))
OBJ ?= $(foreach src,$(SRC),$(call src2obj,$(src)))
###############################################################################
# Rules: Compilation macro
###############################################################################
define template_cpp
$(call src2obj,$(1)): $(1) | $(OBJ_DIR)
@echo "# Compiling $(notdir $(1))"
@g++ $(CFLAGS) -c $$< -o $$@
endef
###############################################################################
# Rules
###############################################################################
all: $(TARGET)
$(OBJ_DIR):
@mkdir -p $@
$(foreach src,$(SRC),$(eval $(call template_cpp,$(src))))
$(TARGET): $(OBJ) makefile
@echo "# Linking $(notdir $@)"
@g++ $(LDFLAGS) $(OBJ) $(LIBS) -o $@
clean:
-rm -rf $(OBJ_DIR) $(TARGET)
================================================
FILE: src_v/jpeg_bitbuffer.v
================================================
//-----------------------------------------------------------------
// Baseline JPEG Decoder
// V0.1
// Ultra-Embedded.com
// Copyright 2020
//
// admin@ultra-embedded.com
//-----------------------------------------------------------------
// License: Apache 2.0
// This IP can be freely used in commercial projects, however you may
// want access to unreleased materials such as verification environments,
// or test vectors, as well as changes to the IP for integration purposes.
// If this is the case, contact the above address.
// I am interested to hear how and where this IP is used, so please get
// in touch!
//-----------------------------------------------------------------
// Copyright 2020 Ultra-Embedded.com
//
// 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.
//-----------------------------------------------------------------
module jpeg_bitbuffer
(
// Inputs
input clk_i
,input rst_i
,input img_start_i
,input img_end_i
,input inport_valid_i
,input [ 7:0] inport_data_i
,input inport_last_i
,input [ 5:0] outport_pop_i
// Outputs
,output inport_accept_o
,output outport_valid_o
,output [ 31:0] outport_data_o
,output outport_last_o
);
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
reg [7:0] ram_q[7:0];
reg [5:0] rd_ptr_q;
reg [5:0] wr_ptr_q;
reg [6:0] count_q;
reg drain_q;
//-----------------------------------------------------------------
// Input side FIFO
//-----------------------------------------------------------------
reg [6:0] count_r;
always @ *
begin
count_r = count_q;
// Count up
if (inport_valid_i && inport_accept_o)
count_r = count_r + 7'd8;
// Count down
if (outport_valid_o && (|outport_pop_i))
count_r = count_r - outport_pop_i;
end
always @ (posedge clk_i )
if (rst_i)
begin
count_q <= 7'b0;
rd_ptr_q <= 6'b0;
wr_ptr_q <= 6'b0;
drain_q <= 1'b0;
end
else if (img_start_i)
begin
count_q <= 7'b0;
rd_ptr_q <= 6'b0;
wr_ptr_q <= 6'b0;
drain_q <= 1'b0;
end
else
begin
// End of image
if (inport_last_i)
drain_q <= 1'b1;
// Push
if (inport_valid_i && inport_accept_o)
begin
ram_q[wr_ptr_q[5:3]] <= inport_data_i;
wr_ptr_q <= wr_ptr_q + 6'd8;
end
// Pop
if (outport_valid_o && (|outport_pop_i))
rd_ptr_q <= rd_ptr_q + outport_pop_i;
count_q <= count_r;
end
assign inport_accept_o = (count_q <= 7'd56);
//-------------------------------------------------------------------
// Output side FIFO
//-------------------------------------------------------------------
reg [39:0] fifo_data_r;
always @ *
begin
fifo_data_r = 40'b0;
case (rd_ptr_q[5:3])
3'd0: fifo_data_r = {ram_q[0], ram_q[1], ram_q[2], ram_q[3], ram_q[4]};
3'd1: fifo_data_r = {ram_q[1], ram_q[2], ram_q[3], ram_q[4], ram_q[5]};
3'd2: fifo_data_r = {ram_q[2], ram_q[3], ram_q[4], ram_q[5], ram_q[6]};
3'd3: fifo_data_r = {ram_q[3], ram_q[4], ram_q[5], ram_q[6], ram_q[7]};
3'd4: fifo_data_r = {ram_q[4], ram_q[5], ram_q[6], ram_q[7], ram_q[0]};
3'd5: fifo_data_r = {ram_q[5], ram_q[6], ram_q[7], ram_q[0], ram_q[1]};
3'd6: fifo_data_r = {ram_q[6], ram_q[7], ram_q[0], ram_q[1], ram_q[2]};
3'd7: fifo_data_r = {ram_q[7], ram_q[0], ram_q[1], ram_q[2], ram_q[3]};
endcase
end
wire [39:0] data_shifted_w = fifo_data_r << rd_ptr_q[2:0];
assign outport_valid_o = (count_q >= 7'd32) || (drain_q && count_q != 7'd0);
assign outport_data_o = data_shifted_w[39:8];
assign outport_last_o = 1'b0;
`ifdef verilator
function get_valid; /*verilator public*/
begin
get_valid = inport_valid_i && inport_accept_o;
end
endfunction
function [7:0] get_data; /*verilator public*/
begin
get_data = inport_data_i;
end
endfunction
`endif
endmodule
================================================
FILE: src_v/jpeg_core.v
================================================
//-----------------------------------------------------------------
// Baseline JPEG Decoder
// V0.1
// Ultra-Embedded.com
// Copyright 2020
//
// admin@ultra-embedded.com
//-----------------------------------------------------------------
// License: Apache 2.0
// This IP can be freely used in commercial projects, however you may
// want access to unreleased materials such as verification environments,
// or test vectors, as well as changes to the IP for integration purposes.
// If this is the case, contact the above address.
// I am interested to hear how and where this IP is used, so please get
// in touch!
//-----------------------------------------------------------------
// Copyright 2020 Ultra-Embedded.com
//
// 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.
//-----------------------------------------------------------------
module jpeg_core
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
#(
parameter SUPPORT_WRITABLE_DHT = 0
)
//-----------------------------------------------------------------
// Ports
//-----------------------------------------------------------------
(
// Inputs
input clk_i
,input rst_i
,input inport_valid_i
,input [ 31:0] inport_data_i
,input [ 3:0] inport_strb_i
,input inport_last_i
,input outport_accept_i
// Outputs
,output inport_accept_o
,output outport_valid_o
,output [ 15:0] outport_width_o
,output [ 15:0] outport_height_o
,output [ 15:0] outport_pixel_x_o
,output [ 15:0] outport_pixel_y_o
,output [ 7:0] outport_pixel_r_o
,output [ 7:0] outport_pixel_g_o
,output [ 7:0] outport_pixel_b_o
,output idle_o
);
wire [ 15:0] idct_outport_data_w;
wire dqt_inport_valid_w;
wire [ 31:0] dqt_inport_id_w;
wire [ 31:0] output_outport_data_w;
wire [ 5:0] idct_inport_idx_w;
wire dqt_inport_eob_w;
wire img_start_w;
wire [ 15:0] img_height_w;
wire output_inport_accept_w;
wire [ 15:0] img_width_w;
wire dht_cfg_valid_w;
wire lookup_req_w;
wire lookup_valid_w;
wire [ 1:0] img_dqt_table_cb_w;
wire [ 7:0] dht_cfg_data_w;
wire img_end_w;
wire [ 31:0] idct_inport_id_w;
wire [ 4:0] lookup_width_w;
wire idct_inport_accept_w;
wire [ 5:0] output_inport_idx_w;
wire [ 15:0] dqt_outport_data_w;
wire dqt_inport_blk_space_w;
wire idct_inport_valid_w;
wire [ 7:0] dqt_cfg_data_w;
wire [ 1:0] img_dqt_table_y_w;
wire idct_inport_eob_w;
wire dht_cfg_accept_w;
wire [ 31:0] output_inport_id_w;
wire output_inport_valid_w;
wire [ 15:0] lookup_input_w;
wire dqt_cfg_accept_w;
wire [ 7:0] lookup_value_w;
wire [ 1:0] lookup_table_w;
wire dht_cfg_last_w;
wire [ 5:0] dqt_inport_idx_w;
wire [ 1:0] img_mode_w;
wire [ 1:0] img_dqt_table_cr_w;
wire bb_inport_valid_w;
wire bb_outport_last_w;
wire bb_inport_last_w;
wire [ 5:0] bb_outport_pop_w;
wire [ 7:0] bb_inport_data_w;
wire dqt_cfg_valid_w;
wire bb_outport_valid_w;
wire bb_inport_accept_w;
wire [ 31:0] bb_outport_data_w;
wire dqt_cfg_last_w;
jpeg_input
u_jpeg_input
(
// Inputs
.clk_i(clk_i)
,.rst_i(rst_i)
,.inport_valid_i(inport_valid_i)
,.inport_data_i(inport_data_i)
,.inport_strb_i(inport_strb_i)
,.inport_last_i(inport_last_i)
,.dqt_cfg_accept_i(dqt_cfg_accept_w)
,.dht_cfg_accept_i(dht_cfg_accept_w)
,.data_accept_i(bb_inport_accept_w)
// Outputs
,.inport_accept_o(inport_accept_o)
,.img_start_o(img_start_w)
,.img_end_o(img_end_w)
,.img_width_o(img_width_w)
,.img_height_o(img_height_w)
,.img_mode_o(img_mode_w)
,.img_dqt_table_y_o(img_dqt_table_y_w)
,.img_dqt_table_cb_o(img_dqt_table_cb_w)
,.img_dqt_table_cr_o(img_dqt_table_cr_w)
,.dqt_cfg_valid_o(dqt_cfg_valid_w)
,.dqt_cfg_data_o(dqt_cfg_data_w)
,.dqt_cfg_last_o(dqt_cfg_last_w)
,.dht_cfg_valid_o(dht_cfg_valid_w)
,.dht_cfg_data_o(dht_cfg_data_w)
,.dht_cfg_last_o(dht_cfg_last_w)
,.data_valid_o(bb_inport_valid_w)
,.data_data_o(bb_inport_data_w)
,.data_last_o(bb_inport_last_w)
);
jpeg_dht
#(
.SUPPORT_WRITABLE_DHT(SUPPORT_WRITABLE_DHT)
)
u_jpeg_dht
(
// Inputs
.clk_i(clk_i)
,.rst_i(rst_i)
,.cfg_valid_i(dht_cfg_valid_w)
,.cfg_data_i(dht_cfg_data_w)
,.cfg_last_i(dht_cfg_last_w)
,.lookup_req_i(lookup_req_w)
,.lookup_table_i(lookup_table_w)
,.lookup_input_i(lookup_input_w)
// Outputs
,.cfg_accept_o(dht_cfg_accept_w)
,.lookup_valid_o(lookup_valid_w)
,.lookup_width_o(lookup_width_w)
,.lookup_value_o(lookup_value_w)
);
jpeg_idct
u_jpeg_idct
(
// Inputs
.clk_i(clk_i)
,.rst_i(rst_i)
,.img_start_i(img_start_w)
,.img_end_i(img_end_w)
,.inport_valid_i(idct_inport_valid_w)
,.inport_data_i(idct_outport_data_w)
,.inport_idx_i(idct_inport_idx_w)
,.inport_eob_i(idct_inport_eob_w)
,.inport_id_i(idct_inport_id_w)
,.outport_accept_i(output_inport_accept_w)
// Outputs
,.inport_accept_o(idct_inport_accept_w)
,.outport_valid_o(output_inport_valid_w)
,.outport_data_o(output_outport_data_w)
,.outport_idx_o(output_inport_idx_w)
,.outport_id_o(output_inport_id_w)
);
jpeg_dqt
u_jpeg_dqt
(
// Inputs
.clk_i(clk_i)
,.rst_i(rst_i)
,.img_start_i(img_start_w)
,.img_end_i(img_end_w)
,.img_dqt_table_y_i(img_dqt_table_y_w)
,.img_dqt_table_cb_i(img_dqt_table_cb_w)
,.img_dqt_table_cr_i(img_dqt_table_cr_w)
,.cfg_valid_i(dqt_cfg_valid_w)
,.cfg_data_i(dqt_cfg_data_w)
,.cfg_last_i(dqt_cfg_last_w)
,.inport_valid_i(dqt_inport_valid_w)
,.inport_data_i(dqt_outport_data_w)
,.inport_idx_i(dqt_inport_idx_w)
,.inport_id_i(dqt_inport_id_w)
,.inport_eob_i(dqt_inport_eob_w)
,.outport_accept_i(idct_inport_accept_w)
// Outputs
,.cfg_accept_o(dqt_cfg_accept_w)
,.inport_blk_space_o(dqt_inport_blk_space_w)
,.outport_valid_o(idct_inport_valid_w)
,.outport_data_o(idct_outport_data_w)
,.outport_idx_o(idct_inport_idx_w)
,.outport_id_o(idct_inport_id_w)
,.outport_eob_o(idct_inport_eob_w)
);
jpeg_output
u_jpeg_output
(
// Inputs
.clk_i(clk_i)
,.rst_i(rst_i)
,.img_start_i(img_start_w)
,.img_end_i(img_end_w)
,.img_width_i(img_width_w)
,.img_height_i(img_height_w)
,.img_mode_i(img_mode_w)
,.inport_valid_i(output_inport_valid_w)
,.inport_data_i(output_outport_data_w)
,.inport_idx_i(output_inport_idx_w)
,.inport_id_i(output_inport_id_w)
,.outport_accept_i(outport_accept_i)
// Outputs
,.inport_accept_o(output_inport_accept_w)
,.outport_valid_o(outport_valid_o)
,.outport_width_o(outport_width_o)
,.outport_height_o(outport_height_o)
,.outport_pixel_x_o(outport_pixel_x_o)
,.outport_pixel_y_o(outport_pixel_y_o)
,.outport_pixel_r_o(outport_pixel_r_o)
,.outport_pixel_g_o(outport_pixel_g_o)
,.outport_pixel_b_o(outport_pixel_b_o)
,.idle_o(idle_o)
);
jpeg_bitbuffer
u_jpeg_bitbuffer
(
// Inputs
.clk_i(clk_i)
,.rst_i(rst_i)
,.img_start_i(img_start_w)
,.img_end_i(img_end_w)
,.inport_valid_i(bb_inport_valid_w)
,.inport_data_i(bb_inport_data_w)
,.inport_last_i(bb_inport_last_w)
,.outport_pop_i(bb_outport_pop_w)
// Outputs
,.inport_accept_o(bb_inport_accept_w)
,.outport_valid_o(bb_outport_valid_w)
,.outport_data_o(bb_outport_data_w)
,.outport_last_o(bb_outport_last_w)
);
jpeg_mcu_proc
u_jpeg_mcu_proc
(
// Inputs
.clk_i(clk_i)
,.rst_i(rst_i)
,.img_start_i(img_start_w)
,.img_end_i(img_end_w)
,.img_width_i(img_width_w)
,.img_height_i(img_height_w)
,.img_mode_i(img_mode_w)
,.inport_valid_i(bb_outport_valid_w)
,.inport_data_i(bb_outport_data_w)
,.inport_last_i(bb_outport_last_w)
,.lookup_valid_i(lookup_valid_w)
,.lookup_width_i(lookup_width_w)
,.lookup_value_i(lookup_value_w)
,.outport_blk_space_i(dqt_inport_blk_space_w)
// Outputs
,.inport_pop_o(bb_outport_pop_w)
,.lookup_req_o(lookup_req_w)
,.lookup_table_o(lookup_table_w)
,.lookup_input_o(lookup_input_w)
,.outport_valid_o(dqt_inport_valid_w)
,.outport_data_o(dqt_outport_data_w)
,.outport_idx_o(dqt_inport_idx_w)
,.outport_id_o(dqt_inport_id_w)
,.outport_eob_o(dqt_inport_eob_w)
);
endmodule
================================================
FILE: src_v/jpeg_dht.v
================================================
//-----------------------------------------------------------------
// Baseline JPEG Decoder
// V0.1
// Ultra-Embedded.com
// Copyright 2020
//
// admin@ultra-embedded.com
//-----------------------------------------------------------------
// License: Apache 2.0
// This IP can be freely used in commercial projects, however you may
// want access to unreleased materials such as verification environments,
// or test vectors, as well as changes to the IP for integration purposes.
// If this is the case, contact the above address.
// I am interested to hear how and where this IP is used, so please get
// in touch!
//-----------------------------------------------------------------
// Copyright 2020 Ultra-Embedded.com
//
// 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.
//-----------------------------------------------------------------
module jpeg_dht
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
#(
parameter SUPPORT_WRITABLE_DHT = 0
)
//-----------------------------------------------------------------
// Ports
//-----------------------------------------------------------------
(
// Inputs
input clk_i
,input rst_i
,input cfg_valid_i
,input [ 7:0] cfg_data_i
,input cfg_last_i
,input lookup_req_i
,input [ 1:0] lookup_table_i
,input [ 15:0] lookup_input_i
// Outputs
,output cfg_accept_o
,output lookup_valid_o
,output [ 4:0] lookup_width_o
,output [ 7:0] lookup_value_o
);
localparam DHT_TABLE_Y_DC = 8'h00;
localparam DHT_TABLE_Y_AC = 8'h10;
localparam DHT_TABLE_CX_DC = 8'h01;
localparam DHT_TABLE_CX_AC = 8'h11;
//---------------------------------------------------------------------
// Support writable huffman tables (e.g. file contains optimised tables)
//---------------------------------------------------------------------
generate
if (SUPPORT_WRITABLE_DHT)
begin
reg [15:0] y_dc_min_code_q[0:15];
reg [15:0] y_dc_max_code_q[0:15];
reg [9:0] y_dc_ptr_q[0:15];
reg [15:0] y_ac_min_code_q[0:15];
reg [15:0] y_ac_max_code_q[0:15];
reg [9:0] y_ac_ptr_q[0:15];
reg [15:0] cx_dc_min_code_q[0:15];
reg [15:0] cx_dc_max_code_q[0:15];
reg [9:0] cx_dc_ptr_q[0:15];
reg [15:0] cx_ac_min_code_q[0:15];
reg [15:0] cx_ac_max_code_q[0:15];
reg [9:0] cx_ac_ptr_q[0:15];
// DHT tables can be combined into one section...
// Reset the table state machine at the end of each table
wire cfg_last_w = cfg_last_i || (total_entries_q == idx_q && idx_q >= 12'd16);
//-----------------------------------------------------------------
// Capture Index
//-----------------------------------------------------------------
reg [11:0] idx_q;
always @ (posedge clk_i )
if (rst_i)
idx_q <= 12'hFFF;
else if (cfg_valid_i && cfg_last_w && cfg_accept_o)
idx_q <= 12'hFFF;
else if (cfg_valid_i && cfg_accept_o)
idx_q <= idx_q + 12'd1;
//-----------------------------------------------------------------
// Table Index
//-----------------------------------------------------------------
reg [7:0] cfg_table_q;
always @ (posedge clk_i )
if (rst_i)
cfg_table_q <= 8'b0;
else if (cfg_valid_i && cfg_accept_o && idx_q == 12'hFFF)
cfg_table_q <= cfg_data_i;
//-----------------------------------------------------------------
// Extract symbol count (temporary)
//-----------------------------------------------------------------
reg [7:0] num_entries_q[0:15];
reg [15:0] has_entries_q; // bitmap
reg [11:0] total_entries_q;
always @ (posedge clk_i )
if (rst_i)
begin
num_entries_q[0] <= 8'b0;
num_entries_q[1] <= 8'b0;
num_entries_q[2] <= 8'b0;
num_entries_q[3] <= 8'b0;
num_entries_q[4] <= 8'b0;
num_entries_q[5] <= 8'b0;
num_entries_q[6] <= 8'b0;
num_entries_q[7] <= 8'b0;
num_entries_q[8] <= 8'b0;
num_entries_q[9] <= 8'b0;
num_entries_q[10] <= 8'b0;
num_entries_q[11] <= 8'b0;
num_entries_q[12] <= 8'b0;
num_entries_q[13] <= 8'b0;
num_entries_q[14] <= 8'b0;
num_entries_q[15] <= 8'b0;
has_entries_q <= 16'b0;
total_entries_q <= 12'd15;
end
else if (cfg_valid_i && cfg_accept_o && idx_q < 12'd16)
begin
num_entries_q[idx_q[3:0]] <= cfg_data_i;
has_entries_q[idx_q[3:0]] <= (cfg_data_i != 8'b0);
total_entries_q <= total_entries_q + {4'b0, cfg_data_i};
end
// End of DHT table
else if (cfg_valid_i && cfg_last_w && cfg_accept_o)
begin
num_entries_q[0] <= 8'b0;
num_entries_q[1] <= 8'b0;
num_entries_q[2] <= 8'b0;
num_entries_q[3] <= 8'b0;
num_entries_q[4] <= 8'b0;
num_entries_q[5] <= 8'b0;
num_entries_q[6] <= 8'b0;
num_entries_q[7] <= 8'b0;
num_entries_q[8] <= 8'b0;
num_entries_q[9] <= 8'b0;
num_entries_q[10] <= 8'b0;
num_entries_q[11] <= 8'b0;
num_entries_q[12] <= 8'b0;
num_entries_q[13] <= 8'b0;
num_entries_q[14] <= 8'b0;
num_entries_q[15] <= 8'b0;
has_entries_q <= 16'b0;
total_entries_q <= 12'd15;
end
//-----------------------------------------------------------------
// Fill tables
//-----------------------------------------------------------------
reg [3:0] i_q;
reg [7:0] j_q;
reg [15:0] code_q;
reg [9:0] next_ptr_q;
always @ (posedge clk_i )
if (rst_i)
begin
y_dc_min_code_q[0] <= 16'b0;
y_dc_max_code_q[0] <= 16'b0;
y_dc_ptr_q[0] <= 10'b0;
y_dc_min_code_q[1] <= 16'b0;
y_dc_max_code_q[1] <= 16'b0;
y_dc_ptr_q[1] <= 10'b0;
y_dc_min_code_q[2] <= 16'b0;
y_dc_max_code_q[2] <= 16'b0;
y_dc_ptr_q[2] <= 10'b0;
y_dc_min_code_q[3] <= 16'b0;
y_dc_max_code_q[3] <= 16'b0;
y_dc_ptr_q[3] <= 10'b0;
y_dc_min_code_q[4] <= 16'b0;
y_dc_max_code_q[4] <= 16'b0;
y_dc_ptr_q[4] <= 10'b0;
y_dc_min_code_q[5] <= 16'b0;
y_dc_max_code_q[5] <= 16'b0;
y_dc_ptr_q[5] <= 10'b0;
y_dc_min_code_q[6] <= 16'b0;
y_dc_max_code_q[6] <= 16'b0;
y_dc_ptr_q[6] <= 10'b0;
y_dc_min_code_q[7] <= 16'b0;
y_dc_max_code_q[7] <= 16'b0;
y_dc_ptr_q[7] <= 10'b0;
y_dc_min_code_q[8] <= 16'b0;
y_dc_max_code_q[8] <= 16'b0;
y_dc_ptr_q[8] <= 10'b0;
y_dc_min_code_q[9] <= 16'b0;
y_dc_max_code_q[9] <= 16'b0;
y_dc_ptr_q[9] <= 10'b0;
y_dc_min_code_q[10] <= 16'b0;
y_dc_max_code_q[10] <= 16'b0;
y_dc_ptr_q[10] <= 10'b0;
y_dc_min_code_q[11] <= 16'b0;
y_dc_max_code_q[11] <= 16'b0;
y_dc_ptr_q[11] <= 10'b0;
y_dc_min_code_q[12] <= 16'b0;
y_dc_max_code_q[12] <= 16'b0;
y_dc_ptr_q[12] <= 10'b0;
y_dc_min_code_q[13] <= 16'b0;
y_dc_max_code_q[13] <= 16'b0;
y_dc_ptr_q[13] <= 10'b0;
y_dc_min_code_q[14] <= 16'b0;
y_dc_max_code_q[14] <= 16'b0;
y_dc_ptr_q[14] <= 10'b0;
y_dc_min_code_q[15] <= 16'b0;
y_dc_max_code_q[15] <= 16'b0;
y_dc_ptr_q[15] <= 10'b0;
y_ac_min_code_q[0] <= 16'b0;
y_ac_max_code_q[0] <= 16'b0;
y_ac_ptr_q[0] <= 10'b0;
y_ac_min_code_q[1] <= 16'b0;
y_ac_max_code_q[1] <= 16'b0;
y_ac_ptr_q[1] <= 10'b0;
y_ac_min_code_q[2] <= 16'b0;
y_ac_max_code_q[2] <= 16'b0;
y_ac_ptr_q[2] <= 10'b0;
y_ac_min_code_q[3] <= 16'b0;
y_ac_max_code_q[3] <= 16'b0;
y_ac_ptr_q[3] <= 10'b0;
y_ac_min_code_q[4] <= 16'b0;
y_ac_max_code_q[4] <= 16'b0;
y_ac_ptr_q[4] <= 10'b0;
y_ac_min_code_q[5] <= 16'b0;
y_ac_max_code_q[5] <= 16'b0;
y_ac_ptr_q[5] <= 10'b0;
y_ac_min_code_q[6] <= 16'b0;
y_ac_max_code_q[6] <= 16'b0;
y_ac_ptr_q[6] <= 10'b0;
y_ac_min_code_q[7] <= 16'b0;
y_ac_max_code_q[7] <= 16'b0;
y_ac_ptr_q[7] <= 10'b0;
y_ac_min_code_q[8] <= 16'b0;
y_ac_max_code_q[8] <= 16'b0;
y_ac_ptr_q[8] <= 10'b0;
y_ac_min_code_q[9] <= 16'b0;
y_ac_max_code_q[9] <= 16'b0;
y_ac_ptr_q[9] <= 10'b0;
y_ac_min_code_q[10] <= 16'b0;
y_ac_max_code_q[10] <= 16'b0;
y_ac_ptr_q[10] <= 10'b0;
y_ac_min_code_q[11] <= 16'b0;
y_ac_max_code_q[11] <= 16'b0;
y_ac_ptr_q[11] <= 10'b0;
y_ac_min_code_q[12] <= 16'b0;
y_ac_max_code_q[12] <= 16'b0;
y_ac_ptr_q[12] <= 10'b0;
y_ac_min_code_q[13] <= 16'b0;
y_ac_max_code_q[13] <= 16'b0;
y_ac_ptr_q[13] <= 10'b0;
y_ac_min_code_q[14] <= 16'b0;
y_ac_max_code_q[14] <= 16'b0;
y_ac_ptr_q[14] <= 10'b0;
y_ac_min_code_q[15] <= 16'b0;
y_ac_max_code_q[15] <= 16'b0;
y_ac_ptr_q[15] <= 10'b0;
cx_dc_min_code_q[0] <= 16'b0;
cx_dc_max_code_q[0] <= 16'b0;
cx_dc_ptr_q[0] <= 10'b0;
cx_dc_min_code_q[1] <= 16'b0;
cx_dc_max_code_q[1] <= 16'b0;
cx_dc_ptr_q[1] <= 10'b0;
cx_dc_min_code_q[2] <= 16'b0;
cx_dc_max_code_q[2] <= 16'b0;
cx_dc_ptr_q[2] <= 10'b0;
cx_dc_min_code_q[3] <= 16'b0;
cx_dc_max_code_q[3] <= 16'b0;
cx_dc_ptr_q[3] <= 10'b0;
cx_dc_min_code_q[4] <= 16'b0;
cx_dc_max_code_q[4] <= 16'b0;
cx_dc_ptr_q[4] <= 10'b0;
cx_dc_min_code_q[5] <= 16'b0;
cx_dc_max_code_q[5] <= 16'b0;
cx_dc_ptr_q[5] <= 10'b0;
cx_dc_min_code_q[6] <= 16'b0;
cx_dc_max_code_q[6] <= 16'b0;
cx_dc_ptr_q[6] <= 10'b0;
cx_dc_min_code_q[7] <= 16'b0;
cx_dc_max_code_q[7] <= 16'b0;
cx_dc_ptr_q[7] <= 10'b0;
cx_dc_min_code_q[8] <= 16'b0;
cx_dc_max_code_q[8] <= 16'b0;
cx_dc_ptr_q[8] <= 10'b0;
cx_dc_min_code_q[9] <= 16'b0;
cx_dc_max_code_q[9] <= 16'b0;
cx_dc_ptr_q[9] <= 10'b0;
cx_dc_min_code_q[10] <= 16'b0;
cx_dc_max_code_q[10] <= 16'b0;
cx_dc_ptr_q[10] <= 10'b0;
cx_dc_min_code_q[11] <= 16'b0;
cx_dc_max_code_q[11] <= 16'b0;
cx_dc_ptr_q[11] <= 10'b0;
cx_dc_min_code_q[12] <= 16'b0;
cx_dc_max_code_q[12] <= 16'b0;
cx_dc_ptr_q[12] <= 10'b0;
cx_dc_min_code_q[13] <= 16'b0;
cx_dc_max_code_q[13] <= 16'b0;
cx_dc_ptr_q[13] <= 10'b0;
cx_dc_min_code_q[14] <= 16'b0;
cx_dc_max_code_q[14] <= 16'b0;
cx_dc_ptr_q[14] <= 10'b0;
cx_dc_min_code_q[15] <= 16'b0;
cx_dc_max_code_q[15] <= 16'b0;
cx_dc_ptr_q[15] <= 10'b0;
cx_ac_min_code_q[0] <= 16'b0;
cx_ac_max_code_q[0] <= 16'b0;
cx_ac_ptr_q[0] <= 10'b0;
cx_ac_min_code_q[1] <= 16'b0;
cx_ac_max_code_q[1] <= 16'b0;
cx_ac_ptr_q[1] <= 10'b0;
cx_ac_min_code_q[2] <= 16'b0;
cx_ac_max_code_q[2] <= 16'b0;
cx_ac_ptr_q[2] <= 10'b0;
cx_ac_min_code_q[3] <= 16'b0;
cx_ac_max_code_q[3] <= 16'b0;
cx_ac_ptr_q[3] <= 10'b0;
cx_ac_min_code_q[4] <= 16'b0;
cx_ac_max_code_q[4] <= 16'b0;
cx_ac_ptr_q[4] <= 10'b0;
cx_ac_min_code_q[5] <= 16'b0;
cx_ac_max_code_q[5] <= 16'b0;
cx_ac_ptr_q[5] <= 10'b0;
cx_ac_min_code_q[6] <= 16'b0;
cx_ac_max_code_q[6] <= 16'b0;
cx_ac_ptr_q[6] <= 10'b0;
cx_ac_min_code_q[7] <= 16'b0;
cx_ac_max_code_q[7] <= 16'b0;
cx_ac_ptr_q[7] <= 10'b0;
cx_ac_min_code_q[8] <= 16'b0;
cx_ac_max_code_q[8] <= 16'b0;
cx_ac_ptr_q[8] <= 10'b0;
cx_ac_min_code_q[9] <= 16'b0;
cx_ac_max_code_q[9] <= 16'b0;
cx_ac_ptr_q[9] <= 10'b0;
cx_ac_min_code_q[10] <= 16'b0;
cx_ac_max_code_q[10] <= 16'b0;
cx_ac_ptr_q[10] <= 10'b0;
cx_ac_min_code_q[11] <= 16'b0;
cx_ac_max_code_q[11] <= 16'b0;
cx_ac_ptr_q[11] <= 10'b0;
cx_ac_min_code_q[12] <= 16'b0;
cx_ac_max_code_q[12] <= 16'b0;
cx_ac_ptr_q[12] <= 10'b0;
cx_ac_min_code_q[13] <= 16'b0;
cx_ac_max_code_q[13] <= 16'b0;
cx_ac_ptr_q[13] <= 10'b0;
cx_ac_min_code_q[14] <= 16'b0;
cx_ac_max_code_q[14] <= 16'b0;
cx_ac_ptr_q[14] <= 10'b0;
cx_ac_min_code_q[15] <= 16'b0;
cx_ac_max_code_q[15] <= 16'b0;
cx_ac_ptr_q[15] <= 10'b0;
j_q <= 8'b0;
i_q <= 4'b0;
code_q <= 16'b0;
end
else if (idx_q < 12'd16 || idx_q == 12'hFFF)
begin
j_q <= 8'b0;
i_q <= 4'b0;
code_q <= 16'b0;
end
else if (cfg_valid_i && cfg_accept_o)
begin
if (j_q == 8'b0)
begin
case (cfg_table_q)
DHT_TABLE_Y_DC:
begin
y_dc_min_code_q[i_q] <= code_q;
y_dc_max_code_q[i_q] <= code_q + {8'b0, num_entries_q[i_q]};
y_dc_ptr_q[i_q] <= next_ptr_q;
end
DHT_TABLE_Y_AC:
begin
y_ac_min_code_q[i_q] <= code_q;
y_ac_max_code_q[i_q] <= code_q + {8'b0, num_entries_q[i_q]};
y_ac_ptr_q[i_q] <= next_ptr_q;
end
DHT_TABLE_CX_DC:
begin
cx_dc_min_code_q[i_q] <= code_q;
cx_dc_max_code_q[i_q] <= code_q + {8'b0, num_entries_q[i_q]};
cx_dc_ptr_q[i_q] <= next_ptr_q;
end
default:
begin
cx_ac_min_code_q[i_q] <= code_q;
cx_ac_max_code_q[i_q] <= code_q + {8'b0, num_entries_q[i_q]};
cx_ac_ptr_q[i_q] <= next_ptr_q;
end
endcase
end
if ((j_q + 8'd1) == num_entries_q[i_q])
begin
j_q <= 8'b0;
i_q <= i_q + 4'd1;
code_q <= (code_q + 16'd1) << 1;
end
else
begin
code_q <= code_q + 16'd1;
j_q <= j_q + 8'd1;
end
end
// Increment through empty bit widths
else if (cfg_valid_i && !cfg_accept_o)
begin
i_q <= i_q + 4'd1;
code_q <= code_q << 1;
end
assign cfg_accept_o = has_entries_q[i_q] || (idx_q < 12'd16) || (idx_q == 12'hFFF);
//-----------------------------------------------------------------
// Code table write pointer
//-----------------------------------------------------------------
wire alloc_entry_w = cfg_valid_i && cfg_accept_o && (idx_q >= 12'd16 && idx_q != 12'hFFF);
always @ (posedge clk_i )
if (rst_i)
next_ptr_q <= 10'b0;
else if (alloc_entry_w)
next_ptr_q <= next_ptr_q + 10'd1;
//-----------------------------------------------------------------
// Lookup: Match shortest bit sequence
//-----------------------------------------------------------------
reg [3:0] y_dc_width_r;
always @ *
begin
y_dc_width_r = 4'b0;
if ({15'b0, lookup_input_i[15]} < y_dc_max_code_q[0])
y_dc_width_r = 4'd0;
else if ({14'b0, lookup_input_i[15:14]} < y_dc_max_code_q[1])
y_dc_width_r = 4'd1;
else if ({13'b0, lookup_input_i[15:13]} < y_dc_max_code_q[2])
y_dc_width_r = 4'd2;
else if ({12'b0, lookup_input_i[15:12]} < y_dc_max_code_q[3])
y_dc_width_r = 4'd3;
else if ({11'b0, lookup_input_i[15:11]} < y_dc_max_code_q[4])
y_dc_width_r = 4'd4;
else if ({10'b0, lookup_input_i[15:10]} < y_dc_max_code_q[5])
y_dc_width_r = 4'd5;
else if ({9'b0, lookup_input_i[15:9]} < y_dc_max_code_q[6])
y_dc_width_r = 4'd6;
else if ({8'b0, lookup_input_i[15:8]} < y_dc_max_code_q[7])
y_dc_width_r = 4'd7;
else if ({7'b0, lookup_input_i[15:7]} < y_dc_max_code_q[8])
y_dc_width_r = 4'd8;
else if ({6'b0, lookup_input_i[15:6]} < y_dc_max_code_q[9])
y_dc_width_r = 4'd9;
else if ({5'b0, lookup_input_i[15:5]} < y_dc_max_code_q[10])
y_dc_width_r = 4'd10;
else if ({4'b0, lookup_input_i[15:4]} < y_dc_max_code_q[11])
y_dc_width_r = 4'd11;
else if ({3'b0, lookup_input_i[15:3]} < y_dc_max_code_q[12])
y_dc_width_r = 4'd12;
else if ({2'b0, lookup_input_i[15:2]} < y_dc_max_code_q[13])
y_dc_width_r = 4'd13;
else if ({1'b0, lookup_input_i[15:1]} < y_dc_max_code_q[14])
y_dc_width_r = 4'd14;
else
y_dc_width_r = 4'd15;
end
reg [3:0] y_ac_width_r;
always @ *
begin
y_ac_width_r = 4'b0;
if ({15'b0, lookup_input_i[15]} < y_ac_max_code_q[0])
y_ac_width_r = 4'd0;
else if ({14'b0, lookup_input_i[15:14]} < y_ac_max_code_q[1])
y_ac_width_r = 4'd1;
else if ({13'b0, lookup_input_i[15:13]} < y_ac_max_code_q[2])
y_ac_width_r = 4'd2;
else if ({12'b0, lookup_input_i[15:12]} < y_ac_max_code_q[3])
y_ac_width_r = 4'd3;
else if ({11'b0, lookup_input_i[15:11]} < y_ac_max_code_q[4])
y_ac_width_r = 4'd4;
else if ({10'b0, lookup_input_i[15:10]} < y_ac_max_code_q[5])
y_ac_width_r = 4'd5;
else if ({9'b0, lookup_input_i[15:9]} < y_ac_max_code_q[6])
y_ac_width_r = 4'd6;
else if ({8'b0, lookup_input_i[15:8]} < y_ac_max_code_q[7])
y_ac_width_r = 4'd7;
else if ({7'b0, lookup_input_i[15:7]} < y_ac_max_code_q[8])
y_ac_width_r = 4'd8;
else if ({6'b0, lookup_input_i[15:6]} < y_ac_max_code_q[9])
y_ac_width_r = 4'd9;
else if ({5'b0, lookup_input_i[15:5]} < y_ac_max_code_q[10])
y_ac_width_r = 4'd10;
else if ({4'b0, lookup_input_i[15:4]} < y_ac_max_code_q[11])
y_ac_width_r = 4'd11;
else if ({3'b0, lookup_input_i[15:3]} < y_ac_max_code_q[12])
y_ac_width_r = 4'd12;
else if ({2'b0, lookup_input_i[15:2]} < y_ac_max_code_q[13])
y_ac_width_r = 4'd13;
else if ({1'b0, lookup_input_i[15:1]} < y_ac_max_code_q[14])
y_ac_width_r = 4'd14;
else
y_ac_width_r = 4'd15;
end
reg [3:0] cx_dc_width_r;
always @ *
begin
cx_dc_width_r = 4'b0;
if ({15'b0, lookup_input_i[15]} < cx_dc_max_code_q[0])
cx_dc_width_r = 4'd0;
else if ({14'b0, lookup_input_i[15:14]} < cx_dc_max_code_q[1])
cx_dc_width_r = 4'd1;
else if ({13'b0, lookup_input_i[15:13]} < cx_dc_max_code_q[2])
cx_dc_width_r = 4'd2;
else if ({12'b0, lookup_input_i[15:12]} < cx_dc_max_code_q[3])
cx_dc_width_r = 4'd3;
else if ({11'b0, lookup_input_i[15:11]} < cx_dc_max_code_q[4])
cx_dc_width_r = 4'd4;
else if ({10'b0, lookup_input_i[15:10]} < cx_dc_max_code_q[5])
cx_dc_width_r = 4'd5;
else if ({9'b0, lookup_input_i[15:9]} < cx_dc_max_code_q[6])
cx_dc_width_r = 4'd6;
else if ({8'b0, lookup_input_i[15:8]} < cx_dc_max_code_q[7])
cx_dc_width_r = 4'd7;
else if ({7'b0, lookup_input_i[15:7]} < cx_dc_max_code_q[8])
cx_dc_width_r = 4'd8;
else if ({6'b0, lookup_input_i[15:6]} < cx_dc_max_code_q[9])
cx_dc_width_r = 4'd9;
else if ({5'b0, lookup_input_i[15:5]} < cx_dc_max_code_q[10])
cx_dc_width_r = 4'd10;
else if ({4'b0, lookup_input_i[15:4]} < cx_dc_max_code_q[11])
cx_dc_width_r = 4'd11;
else if ({3'b0, lookup_input_i[15:3]} < cx_dc_max_code_q[12])
cx_dc_width_r = 4'd12;
else if ({2'b0, lookup_input_i[15:2]} < cx_dc_max_code_q[13])
cx_dc_width_r = 4'd13;
else if ({1'b0, lookup_input_i[15:1]} < cx_dc_max_code_q[14])
cx_dc_width_r = 4'd14;
else
cx_dc_width_r = 4'd15;
end
reg [3:0] cx_ac_width_r;
always @ *
begin
cx_ac_width_r = 4'b0;
if ({15'b0, lookup_input_i[15]} < cx_ac_max_code_q[0])
cx_ac_width_r = 4'd0;
else if ({14'b0, lookup_input_i[15:14]} < cx_ac_max_code_q[1])
cx_ac_width_r = 4'd1;
else if ({13'b0, lookup_input_i[15:13]} < cx_ac_max_code_q[2])
cx_ac_width_r = 4'd2;
else if ({12'b0, lookup_input_i[15:12]} < cx_ac_max_code_q[3])
cx_ac_width_r = 4'd3;
else if ({11'b0, lookup_input_i[15:11]} < cx_ac_max_code_q[4])
cx_ac_width_r = 4'd4;
else if ({10'b0, lookup_input_i[15:10]} < cx_ac_max_code_q[5])
cx_ac_width_r = 4'd5;
else if ({9'b0, lookup_input_i[15:9]} < cx_ac_max_code_q[6])
cx_ac_width_r = 4'd6;
else if ({8'b0, lookup_input_i[15:8]} < cx_ac_max_code_q[7])
cx_ac_width_r = 4'd7;
else if ({7'b0, lookup_input_i[15:7]} < cx_ac_max_code_q[8])
cx_ac_width_r = 4'd8;
else if ({6'b0, lookup_input_i[15:6]} < cx_ac_max_code_q[9])
cx_ac_width_r = 4'd9;
else if ({5'b0, lookup_input_i[15:5]} < cx_ac_max_code_q[10])
cx_ac_width_r = 4'd10;
else if ({4'b0, lookup_input_i[15:4]} < cx_ac_max_code_q[11])
cx_ac_width_r = 4'd11;
else if ({3'b0, lookup_input_i[15:3]} < cx_ac_max_code_q[12])
cx_ac_width_r = 4'd12;
else if ({2'b0, lookup_input_i[15:2]} < cx_ac_max_code_q[13])
cx_ac_width_r = 4'd13;
else if ({1'b0, lookup_input_i[15:1]} < cx_ac_max_code_q[14])
cx_ac_width_r = 4'd14;
else
cx_ac_width_r = 4'd15;
end
//-----------------------------------------------------------------
// Lookup: Register lookup width
//-----------------------------------------------------------------
reg [3:0] lookup_width_r;
always @ *
begin
lookup_width_r = 4'b0;
case (lookup_table_i)
2'd0: lookup_width_r = y_dc_width_r;
2'd1: lookup_width_r = y_ac_width_r;
2'd2: lookup_width_r = cx_dc_width_r;
default: lookup_width_r = cx_ac_width_r;
endcase
end
reg [3:0] lookup_width_q;
always @ (posedge clk_i )
if (rst_i)
lookup_width_q <= 4'b0;
else
lookup_width_q <= lookup_width_r;
reg [1:0] lookup_table_q;
always @ (posedge clk_i )
if (rst_i)
lookup_table_q <= 2'b0;
else
lookup_table_q <= lookup_table_i;
//-----------------------------------------------------------------
// Lookup: Create RAM lookup address
//-----------------------------------------------------------------
reg [15:0] lookup_addr_r;
reg [15:0] input_code_r;
always @ *
begin
lookup_addr_r = 16'b0;
input_code_r = 16'b0;
case (lookup_table_q)
2'd0:
begin
input_code_r = lookup_input_i >> (15 - lookup_width_q);
lookup_addr_r = input_code_r - y_dc_min_code_q[lookup_width_q] + {6'b0, y_dc_ptr_q[lookup_width_q]};
end
2'd1:
begin
input_code_r = lookup_input_i >> (15 - lookup_width_q);
lookup_addr_r = input_code_r - y_ac_min_code_q[lookup_width_q] + {6'b0, y_ac_ptr_q[lookup_width_q]};
end
2'd2:
begin
input_code_r = lookup_input_i >> (15 - lookup_width_q);
lookup_addr_r = input_code_r - cx_dc_min_code_q[lookup_width_q] + {6'b0, cx_dc_ptr_q[lookup_width_q]};
end
default:
begin
input_code_r = lookup_input_i >> (15 - lookup_width_q);
lookup_addr_r = input_code_r - cx_ac_min_code_q[lookup_width_q] + {6'b0, cx_ac_ptr_q[lookup_width_q]};
end
endcase
end
//-----------------------------------------------------------------
// RAM for storing Huffman decode values
//-----------------------------------------------------------------
// LUT for decode values
reg [7:0] ram[0:1023];
always @ (posedge clk_i)
begin
if (alloc_entry_w)
ram[next_ptr_q] <= cfg_data_i;
end
reg [7:0] data_value_q;
always @ (posedge clk_i)
begin
data_value_q <= ram[lookup_addr_r[9:0]];
end
reg lookup_valid_q;
always @ (posedge clk_i )
if (rst_i)
lookup_valid_q <= 1'b0;
else
lookup_valid_q <= lookup_req_i;
reg lookup_valid2_q;
always @ (posedge clk_i )
if (rst_i)
lookup_valid2_q <= 1'b0;
else
lookup_valid2_q <= lookup_valid_q;
reg [4:0] lookup_width2_q;
always @ (posedge clk_i )
if (rst_i)
lookup_width2_q <= 5'b0;
else
lookup_width2_q <= {1'b0, lookup_width_q} + 5'd1;
assign lookup_valid_o = lookup_valid2_q;
assign lookup_value_o = data_value_q;
assign lookup_width_o = lookup_width2_q;
end
//---------------------------------------------------------------------
// Support only standard huffman tables (from JPEG spec).
//---------------------------------------------------------------------
else
begin
//-----------------------------------------------------------------
// Y DC Table (standard)
//-----------------------------------------------------------------
wire [7:0] y_dc_value_w;
wire [4:0] y_dc_width_w;
jpeg_dht_std_y_dc
u_fixed_y_dc
(
.lookup_input_i(lookup_input_i)
,.lookup_value_o(y_dc_value_w)
,.lookup_width_o(y_dc_width_w)
);
//-----------------------------------------------------------------
// Y AC Table (standard)
//-----------------------------------------------------------------
wire [7:0] y_ac_value_w;
wire [4:0] y_ac_width_w;
jpeg_dht_std_y_ac
u_fixed_y_ac
(
.lookup_input_i(lookup_input_i)
,.lookup_value_o(y_ac_value_w)
,.lookup_width_o(y_ac_width_w)
);
//-----------------------------------------------------------------
// Cx DC Table (standard)
//-----------------------------------------------------------------
wire [7:0] cx_dc_value_w;
wire [4:0] cx_dc_width_w;
jpeg_dht_std_cx_dc
u_fixed_cx_dc
(
.lookup_input_i(lookup_input_i)
,.lookup_value_o(cx_dc_value_w)
,.lookup_width_o(cx_dc_width_w)
);
//-----------------------------------------------------------------
// Cx AC Table (standard)
//-----------------------------------------------------------------
wire [7:0] cx_ac_value_w;
wire [4:0] cx_ac_width_w;
jpeg_dht_std_cx_ac
u_fixed_cx_ac
(
.lookup_input_i(lookup_input_i)
,.lookup_value_o(cx_ac_value_w)
,.lookup_width_o(cx_ac_width_w)
);
//-----------------------------------------------------------------
// Lookup
//-----------------------------------------------------------------
reg lookup_valid_q;
always @ (posedge clk_i )
if (rst_i)
lookup_valid_q <= 1'b0;
else
lookup_valid_q <= lookup_req_i;
assign lookup_valid_o = lookup_valid_q;
reg [7:0] lookup_value_q;
always @ (posedge clk_i )
if (rst_i)
lookup_value_q <= 8'b0;
else
begin
case (lookup_table_i)
2'd0: lookup_value_q <= y_dc_value_w;
2'd1: lookup_value_q <= y_ac_value_w;
2'd2: lookup_value_q <= cx_dc_value_w;
2'd3: lookup_value_q <= cx_ac_value_w;
endcase
end
assign lookup_value_o = lookup_value_q;
reg [4:0] lookup_width_q;
always @ (posedge clk_i )
if (rst_i)
lookup_width_q <= 5'b0;
else
begin
case (lookup_table_i)
2'd0: lookup_width_q <= y_dc_width_w;
2'd1: lookup_width_q <= y_ac_width_w;
2'd2: lookup_width_q <= cx_dc_width_w;
2'd3: lookup_width_q <= cx_ac_width_w;
endcase
end
assign lookup_width_o = lookup_width_q;
assign cfg_accept_o = 1'b1;
end
endgenerate
endmodule
================================================
FILE: src_v/jpeg_dht_std_cx_ac.v
================================================
//-----------------------------------------------------------------
// Baseline JPEG Decoder
// V0.1
// Ultra-Embedded.com
// Copyright 2020
//
// admin@ultra-embedded.com
//-----------------------------------------------------------------
// License: Apache 2.0
// This IP can be freely used in commercial projects, however you may
// want access to unreleased materials such as verification environments,
// or test vectors, as well as changes to the IP for integration purposes.
// If this is the case, contact the above address.
// I am interested to hear how and where this IP is used, so please get
// in touch!
//-----------------------------------------------------------------
// Copyright 2020 Ultra-Embedded.com
//
// 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.
//-----------------------------------------------------------------
module jpeg_dht_std_cx_ac
(
input [ 15:0] lookup_input_i
,output [ 4:0] lookup_width_o
,output [ 7:0] lookup_value_o
);
//-----------------------------------------------------------------
// Cx AC Table (standard)
//-----------------------------------------------------------------
reg [7:0] cx_ac_value_r;
reg [4:0] cx_ac_width_r;
always @ *
begin
cx_ac_value_r = 8'b0;
cx_ac_width_r = 5'b0;
if (lookup_input_i[15:14] == 2'h0)
begin
cx_ac_value_r = 8'h00;
cx_ac_width_r = 5'd2;
end
else if (lookup_input_i[15:14] == 2'h1)
begin
cx_ac_value_r = 8'h01;
cx_ac_width_r = 5'd2;
end
else if (lookup_input_i[15:13] == 3'h4)
begin
cx_ac_value_r = 8'h02;
cx_ac_width_r = 5'd3;
end
else if (lookup_input_i[15:12] == 4'ha)
begin
cx_ac_value_r = 8'h03;
cx_ac_width_r = 5'd4;
end
else if (lookup_input_i[15:12] == 4'hb)
begin
cx_ac_value_r = 8'h11;
cx_ac_width_r = 5'd4;
end
else if (lookup_input_i[15:11] == 5'h18)
begin
cx_ac_value_r = 8'h04;
cx_ac_width_r = 5'd5;
end
else if (lookup_input_i[15:11] == 5'h19)
begin
cx_ac_value_r = 8'h05;
cx_ac_width_r = 5'd5;
end
else if (lookup_input_i[15:11] == 5'h1a)
begin
cx_ac_value_r = 8'h21;
cx_ac_width_r = 5'd5;
end
else if (lookup_input_i[15:11] == 5'h1b)
begin
cx_ac_value_r = 8'h31;
cx_ac_width_r = 5'd5;
end
else if (lookup_input_i[15:10] == 6'h38)
begin
cx_ac_value_r = 8'h06;
cx_ac_width_r = 5'd6;
end
else if (lookup_input_i[15:10] == 6'h39)
begin
cx_ac_value_r = 8'h12;
cx_ac_width_r = 5'd6;
end
else if (lookup_input_i[15:10] == 6'h3a)
begin
cx_ac_value_r = 8'h41;
cx_ac_width_r = 5'd6;
end
else if (lookup_input_i[15:10] == 6'h3b)
begin
cx_ac_value_r = 8'h51;
cx_ac_width_r = 5'd6;
end
else if (lookup_input_i[15:9] == 7'h78)
begin
cx_ac_value_r = 8'h07;
cx_ac_width_r = 5'd7;
end
else if (lookup_input_i[15:9] == 7'h79)
begin
cx_ac_value_r = 8'h61;
cx_ac_width_r = 5'd7;
end
else if (lookup_input_i[15:9] == 7'h7a)
begin
cx_ac_value_r = 8'h71;
cx_ac_width_r = 5'd7;
end
else if (lookup_input_i[15:8] == 8'hf6)
begin
cx_ac_value_r = 8'h13;
cx_ac_width_r = 5'd8;
end
else if (lookup_input_i[15:8] == 8'hf7)
begin
cx_ac_value_r = 8'h22;
cx_ac_width_r = 5'd8;
end
else if (lookup_input_i[15:8] == 8'hf8)
begin
cx_ac_value_r = 8'h32;
cx_ac_width_r = 5'd8;
end
else if (lookup_input_i[15:8] == 8'hf9)
begin
cx_ac_value_r = 8'h81;
cx_ac_width_r = 5'd8;
end
else if (lookup_input_i[15:7] == 9'h1f4)
begin
cx_ac_value_r = 8'h08;
cx_ac_width_r = 5'd9;
end
else if (lookup_input_i[15:7] == 9'h1f5)
begin
cx_ac_value_r = 8'h14;
cx_ac_width_r = 5'd9;
end
else if (lookup_input_i[15:7] == 9'h1f6)
begin
cx_ac_value_r = 8'h42;
cx_ac_width_r = 5'd9;
end
else if (lookup_input_i[15:7] == 9'h1f7)
begin
cx_ac_value_r = 8'h91;
cx_ac_width_r = 5'd9;
end
else if (lookup_input_i[15:7] == 9'h1f8)
begin
cx_ac_value_r = 8'ha1;
cx_ac_width_r = 5'd9;
end
else if (lookup_input_i[15:7] == 9'h1f9)
begin
cx_ac_value_r = 8'hb1;
cx_ac_width_r = 5'd9;
end
else if (lookup_input_i[15:7] == 9'h1fa)
begin
cx_ac_value_r = 8'hc1;
cx_ac_width_r = 5'd9;
end
else if (lookup_input_i[15:6] == 10'h3f6)
begin
cx_ac_value_r = 8'h09;
cx_ac_width_r = 5'd10;
end
else if (lookup_input_i[15:6] == 10'h3f7)
begin
cx_ac_value_r = 8'h23;
cx_ac_width_r = 5'd10;
end
else if (lookup_input_i[15:6] == 10'h3f8)
begin
cx_ac_value_r = 8'h33;
cx_ac_width_r = 5'd10;
end
else if (lookup_input_i[15:6] == 10'h3f9)
begin
cx_ac_value_r = 8'h52;
cx_ac_width_r = 5'd10;
end
else if (lookup_input_i[15:6] == 10'h3fa)
begin
cx_ac_value_r = 8'hf0;
cx_ac_width_r = 5'd10;
end
else if (lookup_input_i[15:5] == 11'h7f6)
begin
cx_ac_value_r = 8'h15;
cx_ac_width_r = 5'd11;
end
else if (lookup_input_i[15:5] == 11'h7f7)
begin
cx_ac_value_r = 8'h62;
cx_ac_width_r = 5'd11;
end
else if (lookup_input_i[15:5] == 11'h7f8)
begin
cx_ac_value_r = 8'h72;
cx_ac_width_r = 5'd11;
end
else if (lookup_input_i[15:5] == 11'h7f9)
begin
cx_ac_value_r = 8'hd1;
cx_ac_width_r = 5'd11;
end
else if (lookup_input_i[15:4] == 12'hff4)
begin
cx_ac_value_r = 8'h0a;
cx_ac_width_r = 5'd12;
end
else if (lookup_input_i[15:4] == 12'hff5)
begin
cx_ac_value_r = 8'h16;
cx_ac_width_r = 5'd12;
end
else if (lookup_input_i[15:4] == 12'hff6)
begin
cx_ac_value_r = 8'h24;
cx_ac_width_r = 5'd12;
end
else if (lookup_input_i[15:4] == 12'hff7)
begin
cx_ac_value_r = 8'h34;
cx_ac_width_r = 5'd12;
end
else if (lookup_input_i[15:2] == 14'h3fe0)
begin
cx_ac_value_r = 8'he1;
cx_ac_width_r = 5'd14;
end
else if (lookup_input_i[15:1] == 15'h7fc2)
begin
cx_ac_value_r = 8'h25;
cx_ac_width_r = 5'd15;
end
else if (lookup_input_i[15:1] == 15'h7fc3)
begin
cx_ac_value_r = 8'hf1;
cx_ac_width_r = 5'd15;
end
else if (lookup_input_i[15:0] == 16'hff88)
begin
cx_ac_value_r = 8'h17;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff89)
begin
cx_ac_value_r = 8'h18;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff8a)
begin
cx_ac_value_r = 8'h19;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff8b)
begin
cx_ac_value_r = 8'h1a;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff8c)
begin
cx_ac_value_r = 8'h26;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff8d)
begin
cx_ac_value_r = 8'h27;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff8e)
begin
cx_ac_value_r = 8'h28;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff8f)
begin
cx_ac_value_r = 8'h29;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff90)
begin
cx_ac_value_r = 8'h2a;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff91)
begin
cx_ac_value_r = 8'h35;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff92)
begin
cx_ac_value_r = 8'h36;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff93)
begin
cx_ac_value_r = 8'h37;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff94)
begin
cx_ac_value_r = 8'h38;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff95)
begin
cx_ac_value_r = 8'h39;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff96)
begin
cx_ac_value_r = 8'h3a;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff97)
begin
cx_ac_value_r = 8'h43;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff98)
begin
cx_ac_value_r = 8'h44;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff99)
begin
cx_ac_value_r = 8'h45;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff9a)
begin
cx_ac_value_r = 8'h46;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff9b)
begin
cx_ac_value_r = 8'h47;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff9c)
begin
cx_ac_value_r = 8'h48;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff9d)
begin
cx_ac_value_r = 8'h49;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff9e)
begin
cx_ac_value_r = 8'h4a;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff9f)
begin
cx_ac_value_r = 8'h53;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffa0)
begin
cx_ac_value_r = 8'h54;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffa1)
begin
cx_ac_value_r = 8'h55;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffa2)
begin
cx_ac_value_r = 8'h56;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffa3)
begin
cx_ac_value_r = 8'h57;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffa4)
begin
cx_ac_value_r = 8'h58;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffa5)
begin
cx_ac_value_r = 8'h59;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffa6)
begin
cx_ac_value_r = 8'h5a;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffa7)
begin
cx_ac_value_r = 8'h63;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffa8)
begin
cx_ac_value_r = 8'h64;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffa9)
begin
cx_ac_value_r = 8'h65;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffaa)
begin
cx_ac_value_r = 8'h66;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffab)
begin
cx_ac_value_r = 8'h67;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffac)
begin
cx_ac_value_r = 8'h68;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffad)
begin
cx_ac_value_r = 8'h69;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffae)
begin
cx_ac_value_r = 8'h6a;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffaf)
begin
cx_ac_value_r = 8'h73;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffb0)
begin
cx_ac_value_r = 8'h74;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffb1)
begin
cx_ac_value_r = 8'h75;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffb2)
begin
cx_ac_value_r = 8'h76;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffb3)
begin
cx_ac_value_r = 8'h77;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffb4)
begin
cx_ac_value_r = 8'h78;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffb5)
begin
cx_ac_value_r = 8'h79;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffb6)
begin
cx_ac_value_r = 8'h7a;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffb7)
begin
cx_ac_value_r = 8'h82;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffb8)
begin
cx_ac_value_r = 8'h83;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffb9)
begin
cx_ac_value_r = 8'h84;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffba)
begin
cx_ac_value_r = 8'h85;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffbb)
begin
cx_ac_value_r = 8'h86;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffbc)
begin
cx_ac_value_r = 8'h87;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffbd)
begin
cx_ac_value_r = 8'h88;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffbe)
begin
cx_ac_value_r = 8'h89;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffbf)
begin
cx_ac_value_r = 8'h8a;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffc0)
begin
cx_ac_value_r = 8'h92;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffc1)
begin
cx_ac_value_r = 8'h93;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffc2)
begin
cx_ac_value_r = 8'h94;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffc3)
begin
cx_ac_value_r = 8'h95;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffc4)
begin
cx_ac_value_r = 8'h96;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffc5)
begin
cx_ac_value_r = 8'h97;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffc6)
begin
cx_ac_value_r = 8'h98;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffc7)
begin
cx_ac_value_r = 8'h99;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffc8)
begin
cx_ac_value_r = 8'h9a;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffc9)
begin
cx_ac_value_r = 8'ha2;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffca)
begin
cx_ac_value_r = 8'ha3;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffcb)
begin
cx_ac_value_r = 8'ha4;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffcc)
begin
cx_ac_value_r = 8'ha5;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffcd)
begin
cx_ac_value_r = 8'ha6;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffce)
begin
cx_ac_value_r = 8'ha7;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffcf)
begin
cx_ac_value_r = 8'ha8;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffd0)
begin
cx_ac_value_r = 8'ha9;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffd1)
begin
cx_ac_value_r = 8'haa;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffd2)
begin
cx_ac_value_r = 8'hb2;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffd3)
begin
cx_ac_value_r = 8'hb3;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffd4)
begin
cx_ac_value_r = 8'hb4;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffd5)
begin
cx_ac_value_r = 8'hb5;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffd6)
begin
cx_ac_value_r = 8'hb6;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffd7)
begin
cx_ac_value_r = 8'hb7;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffd8)
begin
cx_ac_value_r = 8'hb8;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffd9)
begin
cx_ac_value_r = 8'hb9;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffda)
begin
cx_ac_value_r = 8'hba;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffdb)
begin
cx_ac_value_r = 8'hc2;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffdc)
begin
cx_ac_value_r = 8'hc3;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffdd)
begin
cx_ac_value_r = 8'hc4;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffde)
begin
cx_ac_value_r = 8'hc5;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffdf)
begin
cx_ac_value_r = 8'hc6;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffe0)
begin
cx_ac_value_r = 8'hc7;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffe1)
begin
cx_ac_value_r = 8'hc8;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffe2)
begin
cx_ac_value_r = 8'hc9;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffe3)
begin
cx_ac_value_r = 8'hca;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffe4)
begin
cx_ac_value_r = 8'hd2;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffe5)
begin
cx_ac_value_r = 8'hd3;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffe6)
begin
cx_ac_value_r = 8'hd4;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffe7)
begin
cx_ac_value_r = 8'hd5;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffe8)
begin
cx_ac_value_r = 8'hd6;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffe9)
begin
cx_ac_value_r = 8'hd7;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffea)
begin
cx_ac_value_r = 8'hd8;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffeb)
begin
cx_ac_value_r = 8'hd9;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffec)
begin
cx_ac_value_r = 8'hda;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffed)
begin
cx_ac_value_r = 8'he2;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffee)
begin
cx_ac_value_r = 8'he3;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffef)
begin
cx_ac_value_r = 8'he4;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfff0)
begin
cx_ac_value_r = 8'he5;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfff1)
begin
cx_ac_value_r = 8'he6;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfff2)
begin
cx_ac_value_r = 8'he7;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfff3)
begin
cx_ac_value_r = 8'he8;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfff4)
begin
cx_ac_value_r = 8'he9;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfff5)
begin
cx_ac_value_r = 8'hea;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfff6)
begin
cx_ac_value_r = 8'hf2;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfff7)
begin
cx_ac_value_r = 8'hf3;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfff8)
begin
cx_ac_value_r = 8'hf4;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfff9)
begin
cx_ac_value_r = 8'hf5;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfffa)
begin
cx_ac_value_r = 8'hf6;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfffb)
begin
cx_ac_value_r = 8'hf7;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfffc)
begin
cx_ac_value_r = 8'hf8;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfffd)
begin
cx_ac_value_r = 8'hf9;
cx_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfffe)
begin
cx_ac_value_r = 8'hfa;
cx_ac_width_r = 5'd16;
end
end
assign lookup_width_o = cx_ac_width_r;
assign lookup_value_o = cx_ac_value_r;
endmodule
================================================
FILE: src_v/jpeg_dht_std_cx_dc.v
================================================
//-----------------------------------------------------------------
// Baseline JPEG Decoder
// V0.1
// Ultra-Embedded.com
// Copyright 2020
//
// admin@ultra-embedded.com
//-----------------------------------------------------------------
// License: Apache 2.0
// This IP can be freely used in commercial projects, however you may
// want access to unreleased materials such as verification environments,
// or test vectors, as well as changes to the IP for integration purposes.
// If this is the case, contact the above address.
// I am interested to hear how and where this IP is used, so please get
// in touch!
//-----------------------------------------------------------------
// Copyright 2020 Ultra-Embedded.com
//
// 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.
//-----------------------------------------------------------------
module jpeg_dht_std_cx_dc
(
input [ 15:0] lookup_input_i
,output [ 4:0] lookup_width_o
,output [ 7:0] lookup_value_o
);
//-----------------------------------------------------------------
// Cx DC Table (standard)
//-----------------------------------------------------------------
reg [7:0] cx_dc_value_r;
reg [4:0] cx_dc_width_r;
always @ *
begin
cx_dc_value_r = 8'b0;
cx_dc_width_r = 5'b0;
if (lookup_input_i[15:14] == 2'h0)
begin
cx_dc_value_r = 8'h00;
cx_dc_width_r = 5'd2;
end
else if (lookup_input_i[15:14] == 2'h1)
begin
cx_dc_value_r = 8'h01;
cx_dc_width_r = 5'd2;
end
else if (lookup_input_i[15:14] == 2'h2)
begin
cx_dc_value_r = 8'h02;
cx_dc_width_r = 5'd2;
end
else if (lookup_input_i[15:13] == 3'h6)
begin
cx_dc_value_r = 8'h03;
cx_dc_width_r = 5'd3;
end
else if (lookup_input_i[15:12] == 4'he)
begin
cx_dc_value_r = 8'h04;
cx_dc_width_r = 5'd4;
end
else if (lookup_input_i[15:11] == 5'h1e)
begin
cx_dc_value_r = 8'h05;
cx_dc_width_r = 5'd5;
end
else if (lookup_input_i[15:10] == 6'h3e)
begin
cx_dc_value_r = 8'h06;
cx_dc_width_r = 5'd6;
end
else if (lookup_input_i[15:9] == 7'h7e)
begin
cx_dc_value_r = 8'h07;
cx_dc_width_r = 5'd7;
end
else if (lookup_input_i[15:8] == 8'hfe)
begin
cx_dc_value_r = 8'h08;
cx_dc_width_r = 5'd8;
end
else if (lookup_input_i[15:7] == 9'h1fe)
begin
cx_dc_value_r = 8'h09;
cx_dc_width_r = 5'd9;
end
else if (lookup_input_i[15:6] == 10'h3fe)
begin
cx_dc_value_r = 8'h0a;
cx_dc_width_r = 5'd10;
end
else if (lookup_input_i[15:5] == 11'h7fe)
begin
cx_dc_value_r = 8'h0b;
cx_dc_width_r = 5'd11;
end
end
assign lookup_width_o = cx_dc_width_r;
assign lookup_value_o = cx_dc_value_r;
endmodule
================================================
FILE: src_v/jpeg_dht_std_y_ac.v
================================================
//-----------------------------------------------------------------
// Baseline JPEG Decoder
// V0.1
// Ultra-Embedded.com
// Copyright 2020
//
// admin@ultra-embedded.com
//-----------------------------------------------------------------
// License: Apache 2.0
// This IP can be freely used in commercial projects, however you may
// want access to unreleased materials such as verification environments,
// or test vectors, as well as changes to the IP for integration purposes.
// If this is the case, contact the above address.
// I am interested to hear how and where this IP is used, so please get
// in touch!
//-----------------------------------------------------------------
// Copyright 2020 Ultra-Embedded.com
//
// 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.
//-----------------------------------------------------------------
module jpeg_dht_std_y_ac
(
input [ 15:0] lookup_input_i
,output [ 4:0] lookup_width_o
,output [ 7:0] lookup_value_o
);
//-----------------------------------------------------------------
// Y AC Table (standard)
//-----------------------------------------------------------------
reg [7:0] y_ac_value_r;
reg [4:0] y_ac_width_r;
always @ *
begin
y_ac_value_r = 8'b0;
y_ac_width_r = 5'b0;
if (lookup_input_i[15:14] == 2'h0)
begin
y_ac_value_r = 8'h01;
y_ac_width_r = 5'd2;
end
else if (lookup_input_i[15:14] == 2'h1)
begin
y_ac_value_r = 8'h02;
y_ac_width_r = 5'd2;
end
else if (lookup_input_i[15:13] == 3'h4)
begin
y_ac_value_r = 8'h03;
y_ac_width_r = 5'd3;
end
else if (lookup_input_i[15:12] == 4'ha)
begin
y_ac_value_r = 8'h00;
y_ac_width_r = 5'd4;
end
else if (lookup_input_i[15:12] == 4'hb)
begin
y_ac_value_r = 8'h04;
y_ac_width_r = 5'd4;
end
else if (lookup_input_i[15:12] == 4'hc)
begin
y_ac_value_r = 8'h11;
y_ac_width_r = 5'd4;
end
else if (lookup_input_i[15:11] == 5'h1a)
begin
y_ac_value_r = 8'h05;
y_ac_width_r = 5'd5;
end
else if (lookup_input_i[15:11] == 5'h1b)
begin
y_ac_value_r = 8'h12;
y_ac_width_r = 5'd5;
end
else if (lookup_input_i[15:11] == 5'h1c)
begin
y_ac_value_r = 8'h21;
y_ac_width_r = 5'd5;
end
else if (lookup_input_i[15:10] == 6'h3a)
begin
y_ac_value_r = 8'h31;
y_ac_width_r = 5'd6;
end
else if (lookup_input_i[15:10] == 6'h3b)
begin
y_ac_value_r = 8'h41;
y_ac_width_r = 5'd6;
end
else if (lookup_input_i[15:9] == 7'h78)
begin
y_ac_value_r = 8'h06;
y_ac_width_r = 5'd7;
end
else if (lookup_input_i[15:9] == 7'h79)
begin
y_ac_value_r = 8'h13;
y_ac_width_r = 5'd7;
end
else if (lookup_input_i[15:9] == 7'h7a)
begin
y_ac_value_r = 8'h51;
y_ac_width_r = 5'd7;
end
else if (lookup_input_i[15:9] == 7'h7b)
begin
y_ac_value_r = 8'h61;
y_ac_width_r = 5'd7;
end
else if (lookup_input_i[15:8] == 8'hf8)
begin
y_ac_value_r = 8'h07;
y_ac_width_r = 5'd8;
end
else if (lookup_input_i[15:8] == 8'hf9)
begin
y_ac_value_r = 8'h22;
y_ac_width_r = 5'd8;
end
else if (lookup_input_i[15:8] == 8'hfa)
begin
y_ac_value_r = 8'h71;
y_ac_width_r = 5'd8;
end
else if (lookup_input_i[15:7] == 9'h1f6)
begin
y_ac_value_r = 8'h14;
y_ac_width_r = 5'd9;
end
else if (lookup_input_i[15:7] == 9'h1f7)
begin
y_ac_value_r = 8'h32;
y_ac_width_r = 5'd9;
end
else if (lookup_input_i[15:7] == 9'h1f8)
begin
y_ac_value_r = 8'h81;
y_ac_width_r = 5'd9;
end
else if (lookup_input_i[15:7] == 9'h1f9)
begin
y_ac_value_r = 8'h91;
y_ac_width_r = 5'd9;
end
else if (lookup_input_i[15:7] == 9'h1fa)
begin
y_ac_value_r = 8'ha1;
y_ac_width_r = 5'd9;
end
else if (lookup_input_i[15:6] == 10'h3f6)
begin
y_ac_value_r = 8'h08;
y_ac_width_r = 5'd10;
end
else if (lookup_input_i[15:6] == 10'h3f7)
begin
y_ac_value_r = 8'h23;
y_ac_width_r = 5'd10;
end
else if (lookup_input_i[15:6] == 10'h3f8)
begin
y_ac_value_r = 8'h42;
y_ac_width_r = 5'd10;
end
else if (lookup_input_i[15:6] == 10'h3f9)
begin
y_ac_value_r = 8'hb1;
y_ac_width_r = 5'd10;
end
else if (lookup_input_i[15:6] == 10'h3fa)
begin
y_ac_value_r = 8'hc1;
y_ac_width_r = 5'd10;
end
else if (lookup_input_i[15:5] == 11'h7f6)
begin
y_ac_value_r = 8'h15;
y_ac_width_r = 5'd11;
end
else if (lookup_input_i[15:5] == 11'h7f7)
begin
y_ac_value_r = 8'h52;
y_ac_width_r = 5'd11;
end
else if (lookup_input_i[15:5] == 11'h7f8)
begin
y_ac_value_r = 8'hd1;
y_ac_width_r = 5'd11;
end
else if (lookup_input_i[15:5] == 11'h7f9)
begin
y_ac_value_r = 8'hf0;
y_ac_width_r = 5'd11;
end
else if (lookup_input_i[15:4] == 12'hff4)
begin
y_ac_value_r = 8'h24;
y_ac_width_r = 5'd12;
end
else if (lookup_input_i[15:4] == 12'hff5)
begin
y_ac_value_r = 8'h33;
y_ac_width_r = 5'd12;
end
else if (lookup_input_i[15:4] == 12'hff6)
begin
y_ac_value_r = 8'h62;
y_ac_width_r = 5'd12;
end
else if (lookup_input_i[15:4] == 12'hff7)
begin
y_ac_value_r = 8'h72;
y_ac_width_r = 5'd12;
end
else if (lookup_input_i[15:1] == 15'h7fc0)
begin
y_ac_value_r = 8'h82;
y_ac_width_r = 5'd15;
end
else if (lookup_input_i[15:0] == 16'hff82)
begin
y_ac_value_r = 8'h09;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff83)
begin
y_ac_value_r = 8'h0a;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff84)
begin
y_ac_value_r = 8'h16;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff85)
begin
y_ac_value_r = 8'h17;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff86)
begin
y_ac_value_r = 8'h18;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff87)
begin
y_ac_value_r = 8'h19;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff88)
begin
y_ac_value_r = 8'h1a;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff89)
begin
y_ac_value_r = 8'h25;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff8a)
begin
y_ac_value_r = 8'h26;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff8b)
begin
y_ac_value_r = 8'h27;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff8c)
begin
y_ac_value_r = 8'h28;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff8d)
begin
y_ac_value_r = 8'h29;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff8e)
begin
y_ac_value_r = 8'h2a;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff8f)
begin
y_ac_value_r = 8'h34;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff90)
begin
y_ac_value_r = 8'h35;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff91)
begin
y_ac_value_r = 8'h36;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff92)
begin
y_ac_value_r = 8'h37;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff93)
begin
y_ac_value_r = 8'h38;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff94)
begin
y_ac_value_r = 8'h39;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff95)
begin
y_ac_value_r = 8'h3a;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff96)
begin
y_ac_value_r = 8'h43;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff97)
begin
y_ac_value_r = 8'h44;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff98)
begin
y_ac_value_r = 8'h45;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff99)
begin
y_ac_value_r = 8'h46;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff9a)
begin
y_ac_value_r = 8'h47;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff9b)
begin
y_ac_value_r = 8'h48;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff9c)
begin
y_ac_value_r = 8'h49;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff9d)
begin
y_ac_value_r = 8'h4a;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff9e)
begin
y_ac_value_r = 8'h53;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hff9f)
begin
y_ac_value_r = 8'h54;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffa0)
begin
y_ac_value_r = 8'h55;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffa1)
begin
y_ac_value_r = 8'h56;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffa2)
begin
y_ac_value_r = 8'h57;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffa3)
begin
y_ac_value_r = 8'h58;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffa4)
begin
y_ac_value_r = 8'h59;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffa5)
begin
y_ac_value_r = 8'h5a;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffa6)
begin
y_ac_value_r = 8'h63;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffa7)
begin
y_ac_value_r = 8'h64;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffa8)
begin
y_ac_value_r = 8'h65;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffa9)
begin
y_ac_value_r = 8'h66;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffaa)
begin
y_ac_value_r = 8'h67;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffab)
begin
y_ac_value_r = 8'h68;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffac)
begin
y_ac_value_r = 8'h69;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffad)
begin
y_ac_value_r = 8'h6a;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffae)
begin
y_ac_value_r = 8'h73;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffaf)
begin
y_ac_value_r = 8'h74;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffb0)
begin
y_ac_value_r = 8'h75;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffb1)
begin
y_ac_value_r = 8'h76;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffb2)
begin
y_ac_value_r = 8'h77;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffb3)
begin
y_ac_value_r = 8'h78;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffb4)
begin
y_ac_value_r = 8'h79;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffb5)
begin
y_ac_value_r = 8'h7a;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffb6)
begin
y_ac_value_r = 8'h83;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffb7)
begin
y_ac_value_r = 8'h84;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffb8)
begin
y_ac_value_r = 8'h85;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffb9)
begin
y_ac_value_r = 8'h86;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffba)
begin
y_ac_value_r = 8'h87;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffbb)
begin
y_ac_value_r = 8'h88;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffbc)
begin
y_ac_value_r = 8'h89;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffbd)
begin
y_ac_value_r = 8'h8a;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffbe)
begin
y_ac_value_r = 8'h92;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffbf)
begin
y_ac_value_r = 8'h93;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffc0)
begin
y_ac_value_r = 8'h94;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffc1)
begin
y_ac_value_r = 8'h95;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffc2)
begin
y_ac_value_r = 8'h96;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffc3)
begin
y_ac_value_r = 8'h97;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffc4)
begin
y_ac_value_r = 8'h98;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffc5)
begin
y_ac_value_r = 8'h99;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffc6)
begin
y_ac_value_r = 8'h9a;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffc7)
begin
y_ac_value_r = 8'ha2;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffc8)
begin
y_ac_value_r = 8'ha3;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffc9)
begin
y_ac_value_r = 8'ha4;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffca)
begin
y_ac_value_r = 8'ha5;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffcb)
begin
y_ac_value_r = 8'ha6;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffcc)
begin
y_ac_value_r = 8'ha7;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffcd)
begin
y_ac_value_r = 8'ha8;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffce)
begin
y_ac_value_r = 8'ha9;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffcf)
begin
y_ac_value_r = 8'haa;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffd0)
begin
y_ac_value_r = 8'hb2;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffd1)
begin
y_ac_value_r = 8'hb3;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffd2)
begin
y_ac_value_r = 8'hb4;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffd3)
begin
y_ac_value_r = 8'hb5;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffd4)
begin
y_ac_value_r = 8'hb6;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffd5)
begin
y_ac_value_r = 8'hb7;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffd6)
begin
y_ac_value_r = 8'hb8;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffd7)
begin
y_ac_value_r = 8'hb9;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffd8)
begin
y_ac_value_r = 8'hba;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffd9)
begin
y_ac_value_r = 8'hc2;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffda)
begin
y_ac_value_r = 8'hc3;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffdb)
begin
y_ac_value_r = 8'hc4;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffdc)
begin
y_ac_value_r = 8'hc5;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffdd)
begin
y_ac_value_r = 8'hc6;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffde)
begin
y_ac_value_r = 8'hc7;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffdf)
begin
y_ac_value_r = 8'hc8;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffe0)
begin
y_ac_value_r = 8'hc9;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffe1)
begin
y_ac_value_r = 8'hca;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffe2)
begin
y_ac_value_r = 8'hd2;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffe3)
begin
y_ac_value_r = 8'hd3;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffe4)
begin
y_ac_value_r = 8'hd4;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffe5)
begin
y_ac_value_r = 8'hd5;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffe6)
begin
y_ac_value_r = 8'hd6;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffe7)
begin
y_ac_value_r = 8'hd7;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffe8)
begin
y_ac_value_r = 8'hd8;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffe9)
begin
y_ac_value_r = 8'hd9;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffea)
begin
y_ac_value_r = 8'hda;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffeb)
begin
y_ac_value_r = 8'he1;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffec)
begin
y_ac_value_r = 8'he2;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffed)
begin
y_ac_value_r = 8'he3;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffee)
begin
y_ac_value_r = 8'he4;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hffef)
begin
y_ac_value_r = 8'he5;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfff0)
begin
y_ac_value_r = 8'he6;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfff1)
begin
y_ac_value_r = 8'he7;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfff2)
begin
y_ac_value_r = 8'he8;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfff3)
begin
y_ac_value_r = 8'he9;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfff4)
begin
y_ac_value_r = 8'hea;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfff5)
begin
y_ac_value_r = 8'hf1;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfff6)
begin
y_ac_value_r = 8'hf2;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfff7)
begin
y_ac_value_r = 8'hf3;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfff8)
begin
y_ac_value_r = 8'hf4;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfff9)
begin
y_ac_value_r = 8'hf5;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfffa)
begin
y_ac_value_r = 8'hf6;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfffb)
begin
y_ac_value_r = 8'hf7;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfffc)
begin
y_ac_value_r = 8'hf8;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfffd)
begin
y_ac_value_r = 8'hf9;
y_ac_width_r = 5'd16;
end
else if (lookup_input_i[15:0] == 16'hfffe)
begin
y_ac_value_r = 8'hfa;
y_ac_width_r = 5'd16;
end
end
assign lookup_width_o = y_ac_width_r;
assign lookup_value_o = y_ac_value_r;
endmodule
================================================
FILE: src_v/jpeg_dht_std_y_dc.v
================================================
//-----------------------------------------------------------------
// Baseline JPEG Decoder
// V0.1
// Ultra-Embedded.com
// Copyright 2020
//
// admin@ultra-embedded.com
//-----------------------------------------------------------------
// License: Apache 2.0
// This IP can be freely used in commercial projects, however you may
// want access to unreleased materials such as verification environments,
// or test vectors, as well as changes to the IP for integration purposes.
// If this is the case, contact the above address.
// I am interested to hear how and where this IP is used, so please get
// in touch!
//-----------------------------------------------------------------
// Copyright 2020 Ultra-Embedded.com
//
// 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.
//-----------------------------------------------------------------
module jpeg_dht_std_y_dc
(
input [ 15:0] lookup_input_i
,output [ 4:0] lookup_width_o
,output [ 7:0] lookup_value_o
);
//-----------------------------------------------------------------
// Y DC Table (standard)
//-----------------------------------------------------------------
reg [7:0] y_dc_value_r;
reg [4:0] y_dc_width_r;
always @ *
begin
y_dc_value_r = 8'b0;
y_dc_width_r = 5'b0;
if (lookup_input_i[15:14] == 2'h0)
begin
y_dc_value_r = 8'h00;
y_dc_width_r = 5'd2;
end
else if (lookup_input_i[15:13] == 3'h2)
begin
y_dc_value_r = 8'h01;
y_dc_width_r = 5'd3;
end
else if (lookup_input_i[15:13] == 3'h3)
begin
y_dc_value_r = 8'h02;
y_dc_width_r = 5'd3;
end
else if (lookup_input_i[15:13] == 3'h4)
begin
y_dc_value_r = 8'h03;
y_dc_width_r = 5'd3;
end
else if (lookup_input_i[15:13] == 3'h5)
begin
y_dc_value_r = 8'h04;
y_dc_width_r = 5'd3;
end
else if (lookup_input_i[15:13] == 3'h6)
begin
y_dc_value_r = 8'h05;
y_dc_width_r = 5'd3;
end
else if (lookup_input_i[15:12] == 4'he)
begin
y_dc_value_r = 8'h06;
y_dc_width_r = 5'd4;
end
else if (lookup_input_i[15:11] == 5'h1e)
begin
y_dc_value_r = 8'h07;
y_dc_width_r = 5'd5;
end
else if (lookup_input_i[15:10] == 6'h3e)
begin
y_dc_value_r = 8'h08;
y_dc_width_r = 5'd6;
end
else if (lookup_input_i[15:9] == 7'h7e)
begin
y_dc_value_r = 8'h09;
y_dc_width_r = 5'd7;
end
else if (lookup_input_i[15:8] == 8'hfe)
begin
y_dc_value_r = 8'h0a;
y_dc_width_r = 5'd8;
end
else if (lookup_input_i[15:7] == 9'h1fe)
begin
y_dc_value_r = 8'h0b;
y_dc_width_r = 5'd9;
end
end
assign lookup_width_o = y_dc_width_r;
assign lookup_value_o = y_dc_value_r;
endmodule
================================================
FILE: src_v/jpeg_dqt.v
================================================
//-----------------------------------------------------------------
// Baseline JPEG Decoder
// V0.1
// Ultra-Embedded.com
// Copyright 2020
//
// admin@ultra-embedded.com
//-----------------------------------------------------------------
// License: Apache 2.0
// This IP can be freely used in commercial projects, however you may
// want access to unreleased materials such as verification environments,
// or test vectors, as well as changes to the IP for integration purposes.
// If this is the case, contact the above address.
// I am interested to hear how and where this IP is used, so please get
// in touch!
//-----------------------------------------------------------------
// Copyright 2020 Ultra-Embedded.com
//
// 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.
//-----------------------------------------------------------------
module jpeg_dqt
(
// Inputs
input clk_i
,input rst_i
,input img_start_i
,input img_end_i
,input [ 1:0] img_dqt_table_y_i
,input [ 1:0] img_dqt_table_cb_i
,input [ 1:0] img_dqt_table_cr_i
,input cfg_valid_i
,input [ 7:0] cfg_data_i
,input cfg_last_i
,input inport_valid_i
,input [ 15:0] inport_data_i
,input [ 5:0] inport_idx_i
,input [ 31:0] inport_id_i
,input inport_eob_i
,input outport_accept_i
// Outputs
,output cfg_accept_o
,output inport_blk_space_o
,output outport_valid_o
,output [ 15:0] outport_data_o
,output [ 5:0] outport_idx_o
,output [ 31:0] outport_id_o
,output outport_eob_o
);
//-----------------------------------------------------------------
// DQT tables
//-----------------------------------------------------------------
// 4 * 256
reg [7:0] table_dqt_q[0:255];
//-----------------------------------------------------------------
// Capture Index
//-----------------------------------------------------------------
reg [7:0] idx_q;
always @ (posedge clk_i )
if (rst_i)
idx_q <= 8'hFF;
else if (cfg_valid_i && cfg_last_i && cfg_accept_o)
idx_q <= 8'hFF;
else if (cfg_valid_i && cfg_accept_o)
idx_q <= idx_q + 8'd1;
assign cfg_accept_o = 1'b1;
//-----------------------------------------------------------------
// Write DQT table
//-----------------------------------------------------------------
reg [1:0] cfg_table_q;
always @ (posedge clk_i )
if (rst_i)
cfg_table_q <= 2'b0;
else if (cfg_valid_i && cfg_accept_o && idx_q == 8'hFF)
cfg_table_q <= cfg_data_i[1:0];
wire [7:0] cfg_table_addr_w = {cfg_table_q, idx_q[5:0]};
wire [1:0] table_src_w[3:0];
assign table_src_w[0] = img_dqt_table_y_i;
assign table_src_w[1] = img_dqt_table_cb_i;
assign table_src_w[2] = img_dqt_table_cr_i;
assign table_src_w[3] = 2'b0;
wire [7:0] table_rd_idx_w = {table_src_w[inport_id_i[31:30]], inport_idx_i};
wire dqt_write_w = cfg_valid_i && cfg_accept_o && idx_q != 8'hFF;
wire [7:0] dqt_table_addr_w = dqt_write_w ? cfg_table_addr_w : table_rd_idx_w;
reg [7:0] dqt_entry_q;
always @ (posedge clk_i )
begin
if (dqt_write_w)
table_dqt_q[dqt_table_addr_w] <= cfg_data_i;
dqt_entry_q <= table_dqt_q[dqt_table_addr_w];
end
//-----------------------------------------------------------------
// dezigzag: Reverse zigzag process
//-----------------------------------------------------------------
function [5:0] dezigzag;
input [5:0] idx;
reg [5:0] out_idx;
begin
case (idx)
6'd0: out_idx = 6'd0;
6'd1: out_idx = 6'd1;
6'd2: out_idx = 6'd8;
6'd3: out_idx = 6'd16;
6'd4: out_idx = 6'd9;
6'd5: out_idx = 6'd2;
6'd6: out_idx = 6'd3;
6'd7: out_idx = 6'd10;
6'd8: out_idx = 6'd17;
6'd9: out_idx = 6'd24;
6'd10: out_idx = 6'd32;
6'd11: out_idx = 6'd25;
6'd12: out_idx = 6'd18;
6'd13: out_idx = 6'd11;
6'd14: out_idx = 6'd4;
6'd15: out_idx = 6'd5;
6'd16: out_idx = 6'd12;
6'd17: out_idx = 6'd19;
6'd18: out_idx = 6'd26;
6'd19: out_idx = 6'd33;
6'd20: out_idx = 6'd40;
6'd21: out_idx = 6'd48;
6'd22: out_idx = 6'd41;
6'd23: out_idx = 6'd34;
6'd24: out_idx = 6'd27;
6'd25: out_idx = 6'd20;
6'd26: out_idx = 6'd13;
6'd27: out_idx = 6'd6;
6'd28: out_idx = 6'd7;
6'd29: out_idx = 6'd14;
6'd30: out_idx = 6'd21;
6'd31: out_idx = 6'd28;
6'd32: out_idx = 6'd35;
6'd33: out_idx = 6'd42;
6'd34: out_idx = 6'd49;
6'd35: out_idx = 6'd56;
6'd36: out_idx = 6'd57;
6'd37: out_idx = 6'd50;
6'd38: out_idx = 6'd43;
6'd39: out_idx = 6'd36;
6'd40: out_idx = 6'd29;
6'd41: out_idx = 6'd22;
6'd42: out_idx = 6'd15;
6'd43: out_idx = 6'd23;
6'd44: out_idx = 6'd30;
6'd45: out_idx = 6'd37;
6'd46: out_idx = 6'd44;
6'd47: out_idx = 6'd51;
6'd48: out_idx = 6'd58;
6'd49: out_idx = 6'd59;
6'd50: out_idx = 6'd52;
6'd51: out_idx = 6'd45;
6'd52: out_idx = 6'd38;
6'd53: out_idx = 6'd31;
6'd54: out_idx = 6'd39;
6'd55: out_idx = 6'd46;
6'd56: out_idx = 6'd53;
6'd57: out_idx = 6'd60;
6'd58: out_idx = 6'd61;
6'd59: out_idx = 6'd54;
6'd60: out_idx = 6'd47;
6'd61: out_idx = 6'd55;
6'd62: out_idx = 6'd62;
default: out_idx = 6'd63;
endcase
dezigzag = out_idx;
end
endfunction
//-----------------------------------------------------------------
// Process dequantisation and dezigzag
//-----------------------------------------------------------------
reg inport_valid_q;
reg [15:0] inport_data_q;
reg [5:0] inport_idx_q;
reg [31:0] inport_id_q;
reg inport_eob_q;
always @ (posedge clk_i )
if (rst_i)
inport_valid_q <= 1'b0;
else
inport_valid_q <= inport_valid_i && ~img_start_i;
always @ (posedge clk_i )
if (rst_i)
inport_idx_q <= 6'b0;
else
inport_idx_q <= inport_idx_i;
always @ (posedge clk_i )
if (rst_i)
inport_data_q <= 16'b0;
else
inport_data_q <= inport_data_i;
always @ (posedge clk_i )
if (rst_i)
inport_id_q <= 32'b0;
else if (inport_valid_i)
inport_id_q <= inport_id_i;
always @ (posedge clk_i )
if (rst_i)
inport_eob_q <= 1'b0;
else
inport_eob_q <= inport_eob_i;
//-----------------------------------------------------------------
// Output
//-----------------------------------------------------------------
reg outport_valid_q;
reg signed [15:0] outport_data_q;
reg [5:0] outport_idx_q;
reg [31:0] outport_id_q;
reg outport_eob_q;
always @ (posedge clk_i )
if (rst_i)
outport_valid_q <= 1'b0;
else
outport_valid_q <= inport_valid_q && ~img_start_i;
always @ (posedge clk_i )
if (rst_i)
outport_data_q <= 16'b0;
else
outport_data_q <= inport_data_q * dqt_entry_q;
always @ (posedge clk_i )
if (rst_i)
outport_idx_q <= 6'b0;
else
outport_idx_q <= dezigzag(inport_idx_q);
always @ (posedge clk_i )
if (rst_i)
outport_id_q <= 32'b0;
else
outport_id_q <= inport_id_q;
always @ (posedge clk_i )
if (rst_i)
outport_eob_q <= 1'b0;
else
outport_eob_q <= inport_eob_q;
assign outport_valid_o = outport_valid_q;
assign outport_data_o = outport_data_q;
assign outport_idx_o = outport_idx_q;
assign outport_id_o = outport_id_q;
assign outport_eob_o = outport_eob_q;
// TODO: Perf
assign inport_blk_space_o = outport_accept_i && !(outport_eob_q || inport_eob_q);
`ifdef verilator
function get_valid; /*verilator public*/
begin
get_valid = outport_valid_o;
end
endfunction
function [15:0] get_sample; /*verilator public*/
begin
get_sample = outport_data_o;
end
endfunction
function [5:0] get_sample_idx; /*verilator public*/
begin
get_sample_idx = outport_idx_o;
end
endfunction
`endif
endmodule
================================================
FILE: src_v/jpeg_idct.v
================================================
//-----------------------------------------------------------------
// Baseline JPEG Decoder
// V0.1
// Ultra-Embedded.com
// Copyright 2020
//
// admin@ultra-embedded.com
//-----------------------------------------------------------------
// License: Apache 2.0
// This IP can be freely used in commercial projects, however you may
// want access to unreleased materials such as verification environments,
// or test vectors, as well as changes to the IP for integration purposes.
// If this is the case, contact the above address.
// I am interested to hear how and where this IP is used, so please get
// in touch!
//-----------------------------------------------------------------
// Copyright 2020 Ultra-Embedded.com
//
// 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.
//-----------------------------------------------------------------
module jpeg_idct
(
// Inputs
input clk_i
,input rst_i
,input img_start_i
,input img_end_i
,input inport_valid_i
,input [ 15:0] inport_data_i
,input [ 5:0] inport_idx_i
,input inport_eob_i
,input [ 31:0] inport_id_i
,input outport_accept_i
// Outputs
,output inport_accept_o
,output outport_valid_o
,output [ 31:0] outport_data_o
,output [ 5:0] outport_idx_o
,output [ 31:0] outport_id_o
);
wire input_valid_w;
wire [ 15:0] input_data0_w;
wire [ 15:0] input_data1_w;
wire [ 15:0] input_data2_w;
wire [ 15:0] input_data3_w;
wire [ 2:0] input_idx_w;
wire input_ready_w;
jpeg_idct_ram
u_input
(
.clk_i(clk_i)
,.rst_i(rst_i)
,.img_start_i(img_start_i)
,.img_end_i(img_end_i)
,.inport_valid_i(inport_valid_i)
,.inport_data_i(inport_data_i)
,.inport_idx_i(inport_idx_i)
,.inport_eob_i(inport_eob_i)
,.inport_accept_o(inport_accept_o)
,.outport_valid_o(input_valid_w)
,.outport_data0_o(input_data0_w)
,.outport_data1_o(input_data1_w)
,.outport_data2_o(input_data2_w)
,.outport_data3_o(input_data3_w)
,.outport_idx_o(input_idx_w)
,.outport_ready_i(outport_accept_i)
);
wire idct_x_valid_w;
wire [ 31:0] idct_x_data_w;
wire [ 5:0] idct_x_idx_w;
wire idct_x_accept_w;
jpeg_idct_x
u_idct_x
(
.clk_i(clk_i)
,.rst_i(rst_i)
,.img_start_i(img_start_i)
,.img_end_i(img_end_i)
,.inport_valid_i(input_valid_w)
,.inport_data0_i(input_data0_w)
,.inport_data1_i(input_data1_w)
,.inport_data2_i(input_data2_w)
,.inport_data3_i(input_data3_w)
,.inport_idx_i(input_idx_w)
,.outport_valid_o(idct_x_valid_w)
,.outport_data_o(idct_x_data_w)
,.outport_idx_o(idct_x_idx_w)
);
wire transpose_valid_w;
wire [ 31:0] transpose_data0_w;
wire [ 31:0] transpose_data1_w;
wire [ 31:0] transpose_data2_w;
wire [ 31:0] transpose_data3_w;
wire [ 2:0] transpose_idx_w;
wire transpose_ready_w = 1'b1;
jpeg_idct_transpose
u_transpose
(
.clk_i(clk_i)
,.rst_i(rst_i)
,.img_start_i(img_start_i)
,.img_end_i(img_end_i)
,.inport_valid_i(idct_x_valid_w)
,.inport_data_i(idct_x_data_w)
,.inport_idx_i(idct_x_idx_w)
,.inport_accept_o(idct_x_accept_w)
,.outport_valid_o(transpose_valid_w)
,.outport_data0_o(transpose_data0_w)
,.outport_data1_o(transpose_data1_w)
,.outport_data2_o(transpose_data2_w)
,.outport_data3_o(transpose_data3_w)
,.outport_idx_o(transpose_idx_w)
,.outport_ready_i(transpose_ready_w)
);
jpeg_idct_y
u_idct_y
(
.clk_i(clk_i)
,.rst_i(rst_i)
,.img_start_i(img_start_i)
,.img_end_i(img_end_i)
,.inport_valid_i(transpose_valid_w)
,.inport_data0_i(transpose_data0_w)
,.inport_data1_i(transpose_data1_w)
,.inport_data2_i(transpose_data2_w)
,.inport_data3_i(transpose_data3_w)
,.inport_idx_i(transpose_idx_w)
,.outport_valid_o(outport_valid_o)
,.outport_data_o(outport_data_o)
,.outport_idx_o(outport_idx_o)
);
jpeg_idct_fifo
#(
.WIDTH(32)
,.DEPTH(8)
,.ADDR_W(3)
)
u_id_fifo
(
.clk_i(clk_i)
,.rst_i(rst_i)
,.flush_i(img_start_i)
,.push_i(inport_eob_i)
,.data_in_i(inport_id_i)
,.accept_o()
,.valid_o()
,.data_out_o(outport_id_o)
,.pop_i(outport_valid_o && outport_idx_o == 6'd63)
);
`ifdef verilator
function get_valid; /*verilator public*/
begin
get_valid = outport_valid_o;
end
endfunction
function [5:0] get_sample_idx; /*verilator public*/
begin
get_sample_idx = outport_idx_o;
end
endfunction
function [31:0] get_sample; /*verilator public*/
begin
get_sample = outport_data_o;
end
endfunction
`endif
endmodule
================================================
FILE: src_v/jpeg_idct_fifo.v
================================================
//-----------------------------------------------------------------
// Baseline JPEG Decoder
// V0.1
// Ultra-Embedded.com
// Copyright 2020
//
// admin@ultra-embedded.com
//-----------------------------------------------------------------
// License: Apache 2.0
// This IP can be freely used in commercial projects, however you may
// want access to unreleased materials such as verification environments,
// or test vectors, as well as changes to the IP for integration purposes.
// If this is the case, contact the above address.
// I am interested to hear how and where this IP is used, so please get
// in touch!
//-----------------------------------------------------------------
// Copyright 2020 Ultra-Embedded.com
//
// 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.
//-----------------------------------------------------------------
module jpeg_idct_fifo
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
#(
parameter WIDTH = 8
,parameter DEPTH = 4
,parameter ADDR_W = 2
)
//-----------------------------------------------------------------
// Ports
//-----------------------------------------------------------------
(
// Inputs
input clk_i
,input rst_i
,input [WIDTH-1:0] data_in_i
,input push_i
,input pop_i
,input flush_i
// Outputs
,output [WIDTH-1:0] data_out_o
,output accept_o
,output valid_o
);
//-----------------------------------------------------------------
// Local Params
//-----------------------------------------------------------------
localparam COUNT_W = ADDR_W + 1;
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
reg [WIDTH-1:0] ram_q[DEPTH-1:0];
reg [ADDR_W-1:0] rd_ptr_q;
reg [ADDR_W-1:0] wr_ptr_q;
reg [COUNT_W-1:0] count_q;
//-----------------------------------------------------------------
// Sequential
//-----------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
if (rst_i)
begin
count_q <= {(COUNT_W) {1'b0}};
rd_ptr_q <= {(ADDR_W) {1'b0}};
wr_ptr_q <= {(ADDR_W) {1'b0}};
end
else if (flush_i)
begin
count_q <= {(COUNT_W) {1'b0}};
rd_ptr_q <= {(ADDR_W) {1'b0}};
wr_ptr_q <= {(ADDR_W) {1'b0}};
end
else
begin
// Push
if (push_i & accept_o)
begin
ram_q[wr_ptr_q] <= data_in_i;
wr_ptr_q <= wr_ptr_q + 1;
end
// Pop
if (pop_i & valid_o)
rd_ptr_q <= rd_ptr_q + 1;
// Count up
if ((push_i & accept_o) & ~(pop_i & valid_o))
count_q <= count_q + 1;
// Count down
else if (~(push_i & accept_o) & (pop_i & valid_o))
count_q <= count_q - 1;
end
//-------------------------------------------------------------------
// Combinatorial
//-------------------------------------------------------------------
/* verilator lint_off WIDTH */
assign valid_o = (count_q != 0);
assign accept_o = (count_q != DEPTH);
/* verilator lint_on WIDTH */
assign data_out_o = ram_q[rd_ptr_q];
endmodule
================================================
FILE: src_v/jpeg_idct_ram.v
================================================
//-----------------------------------------------------------------
// Baseline JPEG Decoder
// V0.1
// Ultra-Embedded.com
// Copyright 2020
//
// admin@ultra-embedded.com
//-----------------------------------------------------------------
// License: Apache 2.0
// This IP can be freely used in commercial projects, however you may
// want access to unreleased materials such as verification environments,
// or test vectors, as well as changes to the IP for integration purposes.
// If this is the case, contact the above address.
// I am interested to hear how and where this IP is used, so please get
// in touch!
//-----------------------------------------------------------------
// Copyright 2020 Ultra-Embedded.com
//
// 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.
//-----------------------------------------------------------------
module jpeg_idct_ram
(
// Inputs
input clk_i
,input rst_i
,input img_start_i
,input img_end_i
,input inport_valid_i
,input [ 15:0] inport_data_i
,input [ 5:0] inport_idx_i
,input inport_eob_i
,input outport_ready_i
// Outputs
,output inport_accept_o
,output outport_valid_o
,output [ 15:0] outport_data0_o
,output [ 15:0] outport_data1_o
,output [ 15:0] outport_data2_o
,output [ 15:0] outport_data3_o
,output [ 2:0] outport_idx_o
);
reg [1:0] block_wr_q;
reg [1:0] block_rd_q;
reg [5:0] rd_idx_q;
reg [3:0] rd_addr_q;
wire [5:0] wr_ptr_w = {block_wr_q, inport_idx_i[5:3], inport_idx_i[0]};
wire [15:0] outport_data0_w;
wire [15:0] outport_data1_w;
wire [15:0] outport_data2_w;
wire [15:0] outport_data3_w;
wire wr0_w = inport_valid_i && inport_accept_o && (inport_idx_i[2:0] == 3'd0 || inport_idx_i[2:0] == 3'd1);
wire wr1_w = inport_valid_i && inport_accept_o && (inport_idx_i[2:0] == 3'd2 || inport_idx_i[2:0] == 3'd3);
wire wr2_w = inport_valid_i && inport_accept_o && (inport_idx_i[2:0] == 3'd4 || inport_idx_i[2:0] == 3'd5);
wire wr3_w = inport_valid_i && inport_accept_o && (inport_idx_i[2:0] == 3'd6 || inport_idx_i[2:0] == 3'd7);
jpeg_idct_ram_dp
u_ram0
(
.clk0_i(clk_i)
,.rst0_i(rst_i)
,.clk1_i(clk_i)
,.rst1_i(rst_i)
,.addr0_i(wr_ptr_w)
,.data0_i(inport_data_i)
,.wr0_i(wr0_w)
,.data0_o()
,.addr1_i({block_rd_q, rd_addr_q})
,.data1_i(16'b0)
,.wr1_i(1'b0)
,.data1_o(outport_data0_w)
);
jpeg_idct_ram_dp
u_ram1
(
.clk0_i(clk_i)
,.rst0_i(rst_i)
,.clk1_i(clk_i)
,.rst1_i(rst_i)
,.addr0_i(wr_ptr_w)
,.data0_i(inport_data_i)
,.wr0_i(wr1_w)
,.data0_o()
,.addr1_i({block_rd_q, rd_addr_q})
,.data1_i(16'b0)
,.wr1_i(1'b0)
,.data1_o(outport_data1_w)
);
jpeg_idct_ram_dp
u_ram2
(
.clk0_i(clk_i)
,.rst0_i(rst_i)
,.clk1_i(clk_i)
,.rst1_i(rst_i)
,.addr0_i(wr_ptr_w)
,.data0_i(inport_data_i)
,.wr0_i(wr2_w)
,.data0_o()
,.addr1_i({block_rd_q, rd_addr_q})
,.data1_i(16'b0)
,.wr1_i(1'b0)
,.data1_o(outport_data2_w)
);
jpeg_idct_ram_dp
u_ram3
(
.clk0_i(clk_i)
,.rst0_i(rst_i)
,.clk1_i(clk_i)
,.rst1_i(rst_i)
,.addr0_i(wr_ptr_w)
,.data0_i(inport_data_i)
,.wr0_i(wr3_w)
,.data0_o()
,.addr1_i({block_rd_q, rd_addr_q})
,.data1_i(16'b0)
,.wr1_i(1'b0)
,.data1_o(outport_data3_w)
);
//-----------------------------------------------------------------
// Data Qualifiers
//-----------------------------------------------------------------
reg [63:0] data_valid0_r;
reg [63:0] data_valid0_q;
always @ *
begin
data_valid0_r = data_valid0_q;
// End of block read out - reset data valid state
if (outport_valid_o && rd_idx_q[5:0] == 6'd63)
begin
case (block_rd_q)
2'd0: data_valid0_r[15:0] = 16'b0;
2'd1: data_valid0_r[31:16] = 16'b0;
2'd2: data_valid0_r[47:32] = 16'b0;
default: data_valid0_r[63:48] = 16'b0;
endcase
end
if (wr0_w)
data_valid0_r[wr_ptr_w] = 1'b1;
end
always @ (posedge clk_i )
if (rst_i)
data_valid0_q <= 64'b0;
else if (img_start_i)
data_valid0_q <= 64'b0;
else
data_valid0_q <= data_valid0_r;
reg [63:0] data_valid1_r;
reg [63:0] data_valid1_q;
always @ *
begin
data_valid1_r = data_valid1_q;
// End of block read out - reset data valid state
if (outport_valid_o && rd_idx_q[5:0] == 6'd63)
begin
case (block_rd_q)
2'd0: data_valid1_r[15:0] = 16'b0;
2'd1: data_valid1_r[31:16] = 16'b0;
2'd2: data_valid1_r[47:32] = 16'b0;
default: data_valid1_r[63:48] = 16'b0;
endcase
end
if (wr1_w)
data_valid1_r[wr_ptr_w] = 1'b1;
end
always @ (posedge clk_i )
if (rst_i)
data_valid1_q <= 64'b0;
else if (img_start_i)
data_valid1_q <= 64'b0;
else
data_valid1_q <= data_valid1_r;
reg [63:0] data_valid2_r;
reg [63:0] data_valid2_q;
always @ *
begin
data_valid2_r = data_valid2_q;
// End of block read out - reset data valid state
if (outport_valid_o && rd_idx_q[5:0] == 6'd63)
begin
case (block_rd_q)
2'd0: data_valid2_r[15:0] = 16'b0;
2'd1: data_valid2_r[31:16] = 16'b0;
2'd2: data_valid2_r[47:32] = 16'b0;
default: data_valid2_r[63:48] = 16'b0;
endcase
end
if (wr2_w)
data_valid2_r[wr_ptr_w] = 1'b1;
end
always @ (posedge clk_i )
if (rst_i)
data_valid2_q <= 64'b0;
else if (img_start_i)
data_valid2_q <= 64'b0;
else
data_valid2_q <= data_valid2_r;
reg [63:0] data_valid3_r;
reg [63:0] data_valid3_q;
always @ *
begin
data_valid3_r = data_valid3_q;
// End of block read out - reset data valid state
if (outport_valid_o && rd_idx_q[5:0] == 6'd63)
begin
case (block_rd_q)
2'd0: data_valid3_r[15:0] = 16'b0;
2'd1: data_valid3_r[31:16] = 16'b0;
2'd2: data_valid3_r[47:32] = 16'b0;
default: data_valid3_r[63:48] = 16'b0;
endcase
end
if (wr3_w)
data_valid3_r[wr_ptr_w] = 1'b1;
end
always @ (posedge clk_i )
if (rst_i)
data_valid3_q <= 64'b0;
else if (img_start_i)
data_valid3_q <= 64'b0;
else
data_valid3_q <= data_valid3_r;
//-----------------------------------------------------------------
// Input Buffer
//-----------------------------------------------------------------
reg [3:0] block_ready_q;
always @ (posedge clk_i )
if (rst_i)
begin
block_ready_q <= 4'b0;
block_wr_q <= 2'b0;
block_rd_q <= 2'b0;
end
else if (img_start_i)
begin
block_ready_q <= 4'b0;
block_wr_q <= 2'b0;
block_rd_q <= 2'b0;
end
else
begin
if (inport_eob_i && inport_accept_o)
begin
block_ready_q[block_wr_q] <= 1'b1;
block_wr_q <= block_wr_q + 2'd1;
end
if (outport_valid_o && rd_idx_q[5:0] == 6'd63)
begin
block_ready_q[block_rd_q] <= 1'b0;
block_rd_q <= block_rd_q + 2'd1;
end
end
assign inport_accept_o = ~block_ready_q[block_wr_q];
//-----------------------------------------------------------------
// FSM
//-----------------------------------------------------------------
localparam STATE_W = 2;
localparam STATE_IDLE = 2'd0;
localparam STATE_SETUP = 2'd1;
localparam STATE_ACTIVE = 2'd2;
reg [STATE_W-1:0] state_q;
reg [STATE_W-1:0] next_state_r;
always @ *
begin
next_state_r = state_q;
case (state_q)
STATE_IDLE:
begin
if (block_ready_q[block_rd_q] && outport_ready_i)
next_state_r = STATE_SETUP;
end
STATE_SETUP:
begin
next_state_r = STATE_ACTIVE;
end
STATE_ACTIVE:
begin
if (outport_valid_o && rd_idx_q == 6'd63)
next_state_r = STATE_IDLE;
end
default: ;
endcase
if (img_start_i)
next_state_r = STATE_IDLE;
end
always @ (posedge clk_i )
if (rst_i)
state_q <= STATE_IDLE;
else
state_q <= next_state_r;
always @ (posedge clk_i )
if (rst_i)
rd_idx_q <= 6'b0;
else if (img_start_i)
rd_idx_q <= 6'b0;
else if (state_q == STATE_ACTIVE)
rd_idx_q <= rd_idx_q + 6'd1;
always @ (posedge clk_i )
if (rst_i)
rd_addr_q <= 4'b0;
else if (state_q == STATE_IDLE)
rd_addr_q <= 4'b0;
else if (state_q == STATE_SETUP)
rd_addr_q <= 4'd1;
else if (state_q == STATE_ACTIVE)
begin
case (rd_idx_q[2:0])
3'd0: rd_addr_q <= rd_addr_q - 1;
3'd1: rd_addr_q <= rd_addr_q + 1;
3'd2: ;
3'd3: rd_addr_q <= rd_addr_q - 1;
3'd4: rd_addr_q <= rd_addr_q + 1;
3'd5: rd_addr_q <= rd_addr_q - 1;
3'd6: rd_addr_q <= rd_addr_q + 2;
3'd7: rd_addr_q <= rd_addr_q + 1;
endcase
end
reg data_val0_q;
reg data_val1_q;
reg data_val2_q;
reg data_val3_q;
always @ (posedge clk_i )
if (rst_i)
begin
data_val0_q <= 1'b0;
data_val1_q <= 1'b0;
data_val2_q <= 1'b0;
data_val3_q <= 1'b0;
end
else
begin
data_val0_q <= data_valid0_q[{block_rd_q, rd_addr_q}];
data_val1_q <= data_valid1_q[{block_rd_q, rd_addr_q}];
data_val2_q <= data_valid2_q[{block_rd_q, rd_addr_q}];
data_val3_q <= data_valid3_q[{block_rd_q, rd_addr_q}];
end
assign outport_valid_o = (state_q == STATE_ACTIVE);
assign outport_idx_o = rd_idx_q[2:0];
assign outport_data0_o = {16{data_val0_q}} & outport_data0_w;
assign outport_data1_o = {16{data_val1_q}} & outport_data1_w;
assign outport_data2_o = {16{data_val2_q}} & outport_data2_w;
assign outport_data3_o = {16{data_val3_q}} & outport_data3_w;
endmodule
================================================
FILE: src_v/jpeg_idct_ram_dp.v
================================================
//-----------------------------------------------------------------
// Baseline JPEG Decoder
// V0.1
// Ultra-Embedded.com
// Copyright 2020
//
// admin@ultra-embedded.com
//-----------------------------------------------------------------
// License: Apache 2.0
// This IP can be freely used in commercial projects, however you may
// want access to unreleased materials such as verification environments,
// or test vectors, as well as changes to the IP for integration purposes.
// If this is the case, contact the above address.
// I am interested to hear how and where this IP is used, so please get
// in touch!
//-----------------------------------------------------------------
// Copyright 2020 Ultra-Embedded.com
//
// 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.
//-----------------------------------------------------------------
module jpeg_idct_ram_dp
(
// Inputs
input clk0_i
,input rst0_i
,input [ 5:0] addr0_i
,input [ 15:0] data0_i
,input wr0_i
,input clk1_i
,input rst1_i
,input [ 5:0] addr1_i
,input [ 15:0] data1_i
,input wr1_i
// Outputs
,output [ 15:0] data0_o
,output [ 15:0] data1_o
);
//-----------------------------------------------------------------
// Dual Port RAM
// Mode: Read First
//-----------------------------------------------------------------
/* verilator lint_off MULTIDRIVEN */
reg [15:0] ram [63:0] /*verilator public*/;
/* verilator lint_on MULTIDRIVEN */
reg [15:0] ram_read0_q;
reg [15:0] ram_read1_q;
// Synchronous write
always @ (posedge clk0_i)
begin
if (wr0_i)
ram[addr0_i][15:0] <= data0_i[15:0];
ram_read0_q <= ram[addr0_i];
end
always @ (posedge clk1_i)
begin
if (wr1_i)
ram[addr1_i][15:0] <= data1_i[15:0];
ram_read1_q <= ram[addr1_i];
end
assign data0_o = ram_read0_q;
assign data1_o = ram_read1_q;
endmodule
================================================
FILE: src_v/jpeg_idct_transpose.v
================================================
//-----------------------------------------------------------------
// Baseline JPEG Decoder
// V0.1
// Ultra-Embedded.com
// Copyright 2020
//
// admin@ultra-embedded.com
//-----------------------------------------------------------------
// License: Apache 2.0
// This IP can be freely used in commercial projects, however you may
// want access to unreleased materials such as verification environments,
// or test vectors, as well as changes to the IP for integration purposes.
// If this is the case, contact the above address.
// I am interested to hear how and where this IP is used, so please get
// in touch!
//-----------------------------------------------------------------
// Copyright 2020 Ultra-Embedded.com
//
// 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.
//-----------------------------------------------------------------
module jpeg_idct_transpose
(
// Inputs
input clk_i
,input rst_i
,input img_start_i
,input img_end_i
,input inport_valid_i
,input [ 31:0] inport_data_i
,input [ 5:0] inport_idx_i
,input outport_ready_i
// Outputs
,output inport_accept_o
,output outport_valid_o
,output [ 31:0] outport_data0_o
,output [ 31:0] outport_data1_o
,output [ 31:0] outport_data2_o
,output [ 31:0] outport_data3_o
,output [ 2:0] outport_idx_o
);
reg block_wr_q;
reg block_rd_q;
reg [5:0] rd_idx_q;
reg [3:0] rd_addr_q;
wire [4:0] wr_ptr_w = {block_wr_q, inport_idx_i[3:0]};
wire [31:0] outport_data0_w;
wire [31:0] outport_data1_w;
wire [31:0] outport_data2_w;
wire [31:0] outport_data3_w;
wire wr0_w = inport_valid_i && inport_accept_o && (inport_idx_i[5:4] == 2'd0);
wire wr1_w = inport_valid_i && inport_accept_o && (inport_idx_i[5:4] == 2'd1);
wire wr2_w = inport_valid_i && inport_accept_o && (inport_idx_i[5:4] == 2'd2);
wire wr3_w = inport_valid_i && inport_accept_o && (inport_idx_i[5:4] == 2'd3);
jpeg_idct_transpose_ram
u_ram0
(
.clk0_i(clk_i)
,.rst0_i(rst_i)
,.clk1_i(clk_i)
,.rst1_i(rst_i)
,.addr0_i(wr_ptr_w)
,.data0_i(inport_data_i)
,.wr0_i(wr0_w)
,.data0_o()
,.addr1_i({block_rd_q, rd_addr_q})
,.data1_i(32'b0)
,.wr1_i(1'b0)
,.data1_o(outport_data0_w)
);
jpeg_idct_transpose_ram
u_ram1
(
.clk0_i(clk_i)
,.rst0_i(rst_i)
,.clk1_i(clk_i)
,.rst1_i(rst_i)
,.addr0_i(wr_ptr_w)
,.data0_i(inport_data_i)
,.wr0_i(wr1_w)
,.data0_o()
,.addr1_i({block_rd_q, rd_addr_q})
,.data1_i(32'b0)
,.wr1_i(1'b0)
,.data1_o(outport_data1_w)
);
jpeg_idct_transpose_ram
u_ram2
(
.clk0_i(clk_i)
,.rst0_i(rst_i)
,.clk1_i(clk_i)
,.rst1_i(rst_i)
,.addr0_i(wr_ptr_w)
,.data0_i(inport_data_i)
,.wr0_i(wr2_w)
,.data0_o()
,.addr1_i({block_rd_q, rd_addr_q})
,.data1_i(32'b0)
,.wr1_i(1'b0)
,.data1_o(outport_data2_w)
);
jpeg_idct_transpose_ram
u_ram3
(
.clk0_i(clk_i)
,.rst0_i(rst_i)
,.clk1_i(clk_i)
,.rst1_i(rst_i)
,.addr0_i(wr_ptr_w)
,.data0_i(inport_data_i)
,.wr0_i(wr3_w)
,.data0_o()
,.addr1_i({block_rd_q, rd_addr_q})
,.data1_i(32'b0)
,.wr1_i(1'b0)
,.data1_o(outport_data3_w)
);
//-----------------------------------------------------------------
// Input Buffer
//-----------------------------------------------------------------
reg [1:0] block_ready_q;
always @ (posedge clk_i )
if (rst_i)
begin
block_ready_q <= 2'b0;
block_wr_q <= 1'b0;
block_rd_q <= 1'b0;
end
else if (img_start_i)
begin
block_ready_q <= 2'b0;
block_wr_q <= 1'b0;
block_rd_q <= 1'b0;
end
else
begin
if (inport_valid_i && inport_idx_i == 6'd63 && inport_accept_o)
begin
block_ready_q[block_wr_q] <= 1'b1;
block_wr_q <= ~block_wr_q;
end
if (outport_valid_o && rd_idx_q[5:0] == 6'd63)
begin
block_ready_q[block_rd_q] <= 1'b0;
block_rd_q <= ~block_rd_q;
end
end
assign inport_accept_o = ~block_ready_q[block_wr_q];
//-----------------------------------------------------------------
// FSM
//-----------------------------------------------------------------
localparam STATE_W = 2;
localparam STATE_IDLE = 2'd0;
localparam STATE_SETUP = 2'd1;
localparam STATE_ACTIVE = 2'd2;
reg [STATE_W-1:0] state_q;
reg [STATE_W-1:0] next_state_r;
always @ *
begin
next_state_r = state_q;
case (state_q)
STATE_IDLE:
begin
if (block_ready_q[block_rd_q] && outport_ready_i)
next_state_r = STATE_SETUP;
end
STATE_SETUP:
begin
next_state_r = STATE_ACTIVE;
end
STATE_ACTIVE:
begin
if (outport_valid_o && rd_idx_q == 6'd63)
next_state_r = STATE_IDLE;
end
default: ;
endcase
if (img_start_i)
next_state_r = STATE_IDLE;
end
always @ (posedge clk_i )
if (rst_i)
state_q <= STATE_IDLE;
else
state_q <= next_state_r;
always @ (posedge clk_i )
if (rst_i)
rd_idx_q <= 6'b0;
else if (img_start_i)
rd_idx_q <= 6'b0;
else if (state_q == STATE_ACTIVE)
rd_idx_q <= rd_idx_q + 6'd1;
always @ (posedge clk_i )
if (rst_i)
rd_addr_q <= 4'b0;
else if (state_q == STATE_IDLE)
rd_addr_q <= 4'b0;
else if (state_q == STATE_SETUP)
rd_addr_q <= 4'd8;
else if (state_q == STATE_ACTIVE)
begin
case (rd_idx_q[2:0])
3'd0: rd_addr_q <= rd_addr_q - 4'd8;
3'd1: rd_addr_q <= rd_addr_q + 4'd8;
3'd2: ;
3'd3: rd_addr_q <= rd_addr_q - 4'd8;
3'd4: rd_addr_q <= rd_addr_q + 4'd8;
3'd5: rd_addr_q <= rd_addr_q - 4'd8;
3'd6: rd_addr_q <= rd_addr_q + 4'd1;
3'd7: rd_addr_q <= rd_addr_q + 4'd8;
endcase
end
assign outport_valid_o = (state_q == STATE_ACTIVE);
assign outport_idx_o = rd_idx_q[2:0];
assign outport_data0_o = outport_data0_w;
assign outport_data1_o = outport_data1_w;
assign outport_data2_o = outport_data2_w;
assign outport_data3_o = outport_data3_w;
endmodule
================================================
FILE: src_v/jpeg_idct_transpose_ram.v
================================================
//-----------------------------------------------------------------
// Baseline JPEG Decoder
// V0.1
// Ultra-Embedded.com
// Copyright 2020
//
// admin@ultra-embedded.com
//-----------------------------------------------------------------
// License: Apache 2.0
// This IP can be freely used in commercial projects, however you may
// want access to unreleased materials such as verification environments,
// or test vectors, as well as changes to the IP for integration purposes.
// If this is the case, contact the above address.
// I am interested to hear how and where this IP is used, so please get
// in touch!
//-----------------------------------------------------------------
// Copyright 2020 Ultra-Embedded.com
//
// 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.
//-----------------------------------------------------------------
module jpeg_idct_transpose_ram
(
// Inputs
input clk0_i
,input rst0_i
,input [ 4:0] addr0_i
,input [ 31:0] data0_i
,input wr0_i
,input clk1_i
,input rst1_i
,input [ 4:0] addr1_i
,input [ 31:0] data1_i
,input wr1_i
// Outputs
,output [ 31:0] data0_o
,output [ 31:0] data1_o
);
//-----------------------------------------------------------------
// Dual Port RAM
// Mode: Read First
//-----------------------------------------------------------------
/* verilator lint_off MULTIDRIVEN */
reg [31:0] ram [31:0] /*verilator public*/;
/* verilator lint_on MULTIDRIVEN */
reg [31:0] ram_read0_q;
reg [31:0] ram_read1_q;
// Synchronous write
always @ (posedge clk0_i)
begin
if (wr0_i)
ram[addr0_i][31:0] <= data0_i[31:0];
ram_read0_q <= ram[addr0_i];
end
always @ (posedge clk1_i)
begin
if (wr1_i)
ram[addr1_i][31:0] <= data1_i[31:0];
ram_read1_q <= ram[addr1_i];
end
assign data0_o = ram_read0_q;
assign data1_o = ram_read1_q;
endmodule
================================================
FILE: src_v/jpeg_idct_x.v
================================================
//-----------------------------------------------------------------
// Baseline JPEG Decoder
// V0.1
// Ultra-Embedded.com
// Copyright 2020
//
// admin@ultra-embedded.com
//-----------------------------------------------------------------
// License: Apache 2.0
// This IP can be freely used in commercial projects, however you may
// want access to unreleased materials such as verification environments,
// or test vectors, as well as changes to the IP for integration purposes.
// If this is the case, contact the above address.
// I am interested to hear how and where this IP is used, so please get
// in touch!
//-----------------------------------------------------------------
// Copyright 2020 Ultra-Embedded.com
//
// 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.
//-----------------------------------------------------------------
module jpeg_idct_x
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
#(
parameter OUT_SHIFT = 11
,parameter INPUT_WIDTH = 16
)
//-----------------------------------------------------------------
// Ports
//-----------------------------------------------------------------
(
// Inputs
input clk_i
,input rst_i
,input img_start_i
,input img_end_i
,input inport_valid_i
,input [ 15:0] inport_data0_i
,input [ 15:0] inport_data1_i
,input [ 15:0] inport_data2_i
,input [ 15:0] inport_data3_i
,input [ 2:0] inport_idx_i
// Outputs
,output outport_valid_o
,output [ 31:0] outport_data_o
,output [ 5:0] outport_idx_o
);
localparam [15:0] C1_16 = 4017; // cos( pi/16) x4096
localparam [15:0] C2_16 = 3784; // cos(2pi/16) x4096
localparam [15:0] C3_16 = 3406; // cos(3pi/16) x4096
localparam [15:0] C4_16 = 2896; // cos(4pi/16) x4096
localparam [15:0] C5_16 = 2276; // cos(5pi/16) x4096
localparam [15:0] C6_16 = 1567; // cos(6pi/16) x4096
localparam [15:0] C7_16 = 799; // cos(7pi/16) x4096
wire signed [31:0] block_in_0_1 = {{16{inport_data0_i[15]}}, inport_data0_i};
wire signed [31:0] block_in_2_3 = {{16{inport_data1_i[15]}}, inport_data1_i};
wire signed [31:0] block_in_4_5 = {{16{inport_data2_i[15]}}, inport_data2_i};
wire signed [31:0] block_in_6_7 = {{16{inport_data3_i[15]}}, inport_data3_i};
//-----------------------------------------------------------------
// IDCT
//-----------------------------------------------------------------
reg signed [31:0] i0;
reg signed [31:0] mul0_a;
reg signed [31:0] mul0_b;
reg signed [31:0] mul1_a;
reg signed [31:0] mul1_b;
reg signed [31:0] mul2_a;
reg signed [31:0] mul2_b;
reg signed [31:0] mul3_a;
reg signed [31:0] mul3_b;
reg signed [31:0] mul4_a;
reg signed [31:0] mul4_b;
always @ (posedge clk_i )
if (rst_i)
begin
i0 <= 32'b0;
mul0_a <= 32'b0;
mul0_b <= 32'b0;
mul1_a <= 32'b0;
mul1_b <= 32'b0;
mul2_a <= 32'b0;
mul2_b <= 32'b0;
mul3_a <= 32'b0;
mul3_b <= 32'b0;
mul4_a <= 32'b0;
mul4_b <= 32'b0;
end
else
begin
/* verilator lint_off WIDTH */
case (inport_idx_i)
3'd0:
begin
i0 <= block_in_0_1 + block_in_4_5;
mul0_a <= block_in_2_3;
mul0_b <= C2_16;
mul1_a <= block_in_6_7;
mul1_b <= C6_16;
end
3'd1:
begin
mul0_a <= block_in_0_1;
mul0_b <= C1_16;
mul1_a <= block_in_6_7;
mul1_b <= C7_16;
mul2_a <= block_in_4_5;
mul2_b <= C5_16;
mul3_a <= block_in_2_3;
mul3_b <= C3_16;
mul4_a <= i0;
mul4_b <= C4_16;
end
3'd2:
begin
i0 <= block_in_0_1 - block_in_4_5;
end
3'd3:
begin
mul0_a <= block_in_0_1;
mul0_b <= C7_16;
mul1_a <= block_in_6_7;
mul1_b <= C1_16;
mul2_a <= block_in_4_5;
mul2_b <= C3_16;
mul3_a <= block_in_2_3;
mul3_b <= C5_16;
end
3'd4:
begin
mul0_a <= block_in_0_1;
mul0_b <= C7_16;
mul1_a <= block_in_6_7;
mul1_b <= C1_16;
mul2_a <= block_in_4_5;
mul2_b <= C3_16;
mul3_a <= block_in_2_3;
mul3_b <= C5_16;
end
3'd5:
begin
mul0_a <= block_in_2_3;
mul0_b <= C6_16;
mul1_a <= block_in_6_7;
mul1_b <= C2_16;
mul4_a <= i0;
mul4_b <= C4_16;
end
default:
;
endcase
/* verilator lint_on WIDTH */
end
reg signed [31:0] mul0_q;
reg signed [31:0] mul1_q;
reg signed [31:0] mul2_q;
reg signed [31:0] mul3_q;
reg signed [31:0] mul4_q;
always @ (posedge clk_i )
if (rst_i)
begin
mul0_q <= 32'b0;
mul1_q <= 32'b0;
mul2_q <= 32'b0;
mul3_q <= 32'b0;
mul4_q <= 32'b0;
end
else
begin
mul0_q <= mul0_a * mul0_b;
mul1_q <= mul1_a * mul1_b;
mul2_q <= mul2_a * mul2_b;
mul3_q <= mul3_a * mul3_b;
mul4_q <= mul4_a * mul4_b;
end
reg signed [31:0] mul0;
reg signed [31:0] mul1;
reg signed [31:0] mul2;
reg signed [31:0] mul3;
reg signed [31:0] mul4;
always @ (posedge clk_i )
if (rst_i)
begin
mul0 <= 32'b0;
mul1 <= 32'b0;
mul2 <= 32'b0;
mul3 <= 32'b0;
mul4 <= 32'b0;
end
else
begin
mul0 <= mul0_q;
mul1 <= mul1_q;
mul2 <= mul2_q;
mul3 <= mul3_q;
mul4 <= mul4_q;
end
reg out_stg0_valid_q;
reg [2:0] out_stg0_idx_q;
always @ (posedge clk_i )
if (rst_i)
begin
out_stg0_valid_q <= 1'b0;
out_stg0_idx_q <= 3'b0;
end
else
begin
out_stg0_valid_q <= inport_valid_i;
out_stg0_idx_q <= inport_idx_i;
end
reg out_stg1_valid_q;
reg [2:0] out_stg1_idx_q;
always @ (posedge clk_i )
if (rst_i)
begin
out_stg1_valid_q <= 1'b0;
out_stg1_idx_q <= 3'b0;
end
else
begin
out_stg1_valid_q <= out_stg0_valid_q;
out_stg1_idx_q <= out_stg0_idx_q;
end
reg out_stg2_valid_q;
reg [2:0] out_stg2_idx_q;
always @ (posedge clk_i )
if (rst_i)
begin
out_stg2_valid_q <= 1'b0;
out_stg2_idx_q <= 3'b0;
end
else
begin
out_stg2_valid_q <= out_stg1_valid_q;
out_stg2_idx_q <= out_stg1_idx_q;
end
reg signed [31:0] o_s5;
reg signed [31:0] o_s6;
reg signed [31:0] o_s7;
reg signed [31:0] o_t0;
reg signed [31:0] o_t1;
reg signed [31:0] o_t2;
reg signed [31:0] o_t3;
reg signed [31:0] o_t4;
reg signed [31:0] o_t5;
reg signed [31:0] o_t6;
reg signed [31:0] o_t7;
reg signed [31:0] o_t6_5;
reg signed [31:0] o_t5_6;
always @ (posedge clk_i )
if (rst_i)
begin
o_s5 <= 32'b0;
o_s6 <= 32'b0;
o_s7 <= 32'b0;
o_t0 <= 32'b0;
o_t1 <= 32'b0;
o_t2 <= 32'b0;
o_t3 <= 32'b0;
o_t4 <= 32'b0;
o_t5 <= 32'b0;
o_t6 <= 32'b0;
o_t7 <= 32'b0;
o_t6_5 <= 32'b0;
o_t5_6 <= 32'b0;
end
else
begin
case (out_stg2_idx_q)
3'd0:
begin
o_t3 <= mul0 + mul1; // s3
end
3'd1:
begin
o_s7 <= mul0 + mul1;
o_s6 <= mul2 + mul3;
o_t0 <= mul4; // s0
end
3'd2:
begin
o_t0 <= o_t0 + o_t3; // t0
o_t3 <= o_t0 - o_t3; // t3
o_t7 <= o_s6 + o_s7;
end
3'd3:
begin
o_t4 <= (mul0 - mul1) + (mul2 - mul3);
end
3'd4:
begin
o_t0 <= mul0 - mul1; // s4
o_s5 <= mul2 - mul3;
end
3'd5:
begin
o_t3 <= mul0 - mul1; // s2
o_t4 <= mul4; // s1
o_t5 <= o_t0 - o_s5;
o_t6 <= o_s7 -
gitextract_xejh9o8w/
├── LICENSE
├── README.md
├── c_model/
│ ├── README.md
│ ├── jpeg_bit_buffer.h
│ ├── jpeg_dht.h
│ ├── jpeg_dqt.h
│ ├── jpeg_idct.h
│ ├── jpeg_mcu_block.h
│ ├── main.cpp
│ └── makefile
└── src_v/
├── jpeg_bitbuffer.v
├── jpeg_core.v
├── jpeg_dht.v
├── jpeg_dht_std_cx_ac.v
├── jpeg_dht_std_cx_dc.v
├── jpeg_dht_std_y_ac.v
├── jpeg_dht_std_y_dc.v
├── jpeg_dqt.v
├── jpeg_idct.v
├── jpeg_idct_fifo.v
├── jpeg_idct_ram.v
├── jpeg_idct_ram_dp.v
├── jpeg_idct_transpose.v
├── jpeg_idct_transpose_ram.v
├── jpeg_idct_x.v
├── jpeg_idct_y.v
├── jpeg_input.v
├── jpeg_mcu_id.v
├── jpeg_mcu_proc.v
├── jpeg_output.v
├── jpeg_output_cx_ram.v
├── jpeg_output_fifo.v
└── jpeg_output_y_ram.v
SYMBOL INDEX (13 symbols across 6 files) FILE: c_model/jpeg_bit_buffer.h function class (line 23) | class jpeg_bit_buffer function push (line 53) | bool push(uint8_t b) function read_word (line 79) | uint32_t read_word(void) function advance (line 96) | void advance(int bits) function eof (line 102) | bool eof(void) FILE: c_model/jpeg_dht.h function class (line 24) | class jpeg_dht FILE: c_model/jpeg_dqt.h function class (line 29) | class jpeg_dqt FILE: c_model/jpeg_idct.h function class (line 13) | class jpeg_idct FILE: c_model/jpeg_mcu_block.h function class (line 18) | class jpeg_mcu_block FILE: c_model/main.cpp type eJpgMode (line 23) | enum eJpgMode function ConvertYUV2RGB (line 48) | static void ConvertYUV2RGB(int block_num, int *y, int *cb, int *cr) function DecodeImage (line 112) | static bool DecodeImage(void) function main (line 265) | int main(int argc, char* argv[])
Condensed preview — 33 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (294K chars).
[
{
"path": "LICENSE",
"chars": 11357,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "README.md",
"chars": 3306,
"preview": "# High throughput JPEG decoder\n\nGithub: [https://github.com/ultraembedded/core_jpeg](https://github.com/ultraembedded/co"
},
{
"path": "c_model/README.md",
"chars": 580,
"preview": "## JPEG Decoder C Model\n\nThis a simple C model of a JPEG decoder that can decode baseline JPEG images.\nThe purpose of th"
},
{
"path": "c_model/jpeg_bit_buffer.h",
"chars": 2331,
"preview": "#ifndef JPEG_BIT_BUFFER_H\n#define JPEG_BIT_BUFFER_H\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include"
},
{
"path": "c_model/jpeg_dht.h",
"chars": 4106,
"preview": "#ifndef JPEG_DHT_H\n#define JPEG_DHT_H\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <string.h>\n#i"
},
{
"path": "c_model/jpeg_dqt.h",
"chars": 2824,
"preview": "#ifndef JPEG_DQT_H\n#define JPEG_DQT_H\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <string.h>\n#i"
},
{
"path": "c_model/jpeg_idct.h",
"chars": 3828,
"preview": "#ifndef JPEG_IDCT_H\n#define JPEG_IDCT_H\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <string.h>\n"
},
{
"path": "c_model/jpeg_mcu_block.h",
"chars": 3801,
"preview": "#ifndef JPEG_MCU_BLOCK_H\n#define JPEG_MCU_BLOCK_H\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <"
},
{
"path": "c_model/main.cpp",
"chars": 19685,
"preview": "#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <string.h>\n#include <unistd.h>\n#include <assert.h>\n\n"
},
{
"path": "c_model/makefile",
"chars": 1742,
"preview": "###############################################################################\n# Makefile\n#############################"
},
{
"path": "src_v/jpeg_bitbuffer.v",
"chars": 4661,
"preview": "//-----------------------------------------------------------------\n// Baseline JPEG Decoder\n// "
},
{
"path": "src_v/jpeg_core.v",
"chars": 9309,
"preview": "//-----------------------------------------------------------------\n// Baseline JPEG Decoder\n// "
},
{
"path": "src_v/jpeg_dht.v",
"chars": 29210,
"preview": "//-----------------------------------------------------------------\n// Baseline JPEG Decoder\n// "
},
{
"path": "src_v/jpeg_dht_std_cx_ac.v",
"chars": 22789,
"preview": "//-----------------------------------------------------------------\n// Baseline JPEG Decoder\n// "
},
{
"path": "src_v/jpeg_dht_std_cx_dc.v",
"chars": 3507,
"preview": "//-----------------------------------------------------------------\n// Baseline JPEG Decoder\n// "
},
{
"path": "src_v/jpeg_dht_std_y_ac.v",
"chars": 22468,
"preview": "//-----------------------------------------------------------------\n// Baseline JPEG Decoder\n// "
},
{
"path": "src_v/jpeg_dht_std_y_dc.v",
"chars": 3467,
"preview": "//-----------------------------------------------------------------\n// Baseline JPEG Decoder\n// "
},
{
"path": "src_v/jpeg_dqt.v",
"chars": 8418,
"preview": "//-----------------------------------------------------------------\n// Baseline JPEG Decoder\n// "
},
{
"path": "src_v/jpeg_idct.v",
"chars": 5326,
"preview": "//-----------------------------------------------------------------\n// Baseline JPEG Decoder\n// "
},
{
"path": "src_v/jpeg_idct_fifo.v",
"chars": 3918,
"preview": "//-----------------------------------------------------------------\n// Baseline JPEG Decoder\n// "
},
{
"path": "src_v/jpeg_idct_ram.v",
"chars": 10263,
"preview": "//-----------------------------------------------------------------\n// Baseline JPEG Decoder\n// "
},
{
"path": "src_v/jpeg_idct_ram_dp.v",
"chars": 2588,
"preview": "//-----------------------------------------------------------------\n// Baseline JPEG Decoder\n// "
},
{
"path": "src_v/jpeg_idct_transpose.v",
"chars": 6683,
"preview": "//-----------------------------------------------------------------\n// Baseline JPEG Decoder\n// "
},
{
"path": "src_v/jpeg_idct_transpose_ram.v",
"chars": 2595,
"preview": "//-----------------------------------------------------------------\n// Baseline JPEG Decoder\n// "
},
{
"path": "src_v/jpeg_idct_x.v",
"chars": 10141,
"preview": "//-----------------------------------------------------------------\n// Baseline JPEG Decoder\n// "
},
{
"path": "src_v/jpeg_idct_y.v",
"chars": 12024,
"preview": "//-----------------------------------------------------------------\n// Baseline JPEG Decoder\n// "
},
{
"path": "src_v/jpeg_input.v",
"chars": 17968,
"preview": "//-----------------------------------------------------------------\n// Baseline JPEG Decoder\n// "
},
{
"path": "src_v/jpeg_mcu_id.v",
"chars": 5638,
"preview": "//-----------------------------------------------------------------\n// Baseline JPEG Decoder\n// "
},
{
"path": "src_v/jpeg_mcu_proc.v",
"chars": 12600,
"preview": "//-----------------------------------------------------------------\n// Baseline JPEG Decoder\n// "
},
{
"path": "src_v/jpeg_output.v",
"chars": 9914,
"preview": "//-----------------------------------------------------------------\n// Baseline JPEG Decoder\n// "
},
{
"path": "src_v/jpeg_output_cx_ram.v",
"chars": 15242,
"preview": "//-----------------------------------------------------------------\n// Baseline JPEG Decoder\n// "
},
{
"path": "src_v/jpeg_output_fifo.v",
"chars": 3920,
"preview": "//-----------------------------------------------------------------\n// Baseline JPEG Decoder\n// "
},
{
"path": "src_v/jpeg_output_y_ram.v",
"chars": 5943,
"preview": "//-----------------------------------------------------------------\n// Baseline JPEG Decoder\n// "
}
]
About this extraction
This page contains the full source code of the ultraembedded/core_jpeg GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 33 files (275.5 KB), approximately 85.9k tokens, and a symbol index with 13 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.