JPEG解码:反DCT变换(三)
2:矩阵的转秩
在矩阵的相乘结束之后,要对矩阵转秩,转秩的效果就是行列转换。在此要用到2个ram,一个要做数据输入,另个用与数据输出。
ram
1 `timescale 1ps / 1ps
2 module idct_ram (
3 clk,
4 rst_n,
5 wr_rd,
6 datain,
7 wr_addr,
8 rd_addr,
9 dataout
10 );
11
12 input clk;
13 input rst_n;
14 input wr_rd;
15 input [13:0]datain;
16
17 input [5:0]wr_addr;
18 input [5:0]rd_addr;
19
20 output [13:0]dataout;
21
22 reg[13:0]ram[0:63];
23 always@(posedge clk or negedge rst_n)
24 begin
25 if(!rst_n)
26 begin
27 ram[0]<=14'd0;
28 ram[1]<=14'd0;
29 ram[2]<=14'd0;
30 ram[3]<=14'd0;
31 ram[4]<=14'd0;
32 ram[5]<=14'd0;
33 ram[6]<=14'd0;
34 ram[7]<=14'd0;
35 ram[8]<=14'd0;
36 ram[9]<=14'd0;
37 ram[10]<=14'd0;
38 ram[11]<=14'd0;
39 ram[12]<=14'd0;
40 ram[13]<=14'd0;
41 ram[14]<=14'd0;
42 ram[15]<=14'd0;
43 ram[16]<=14'd0;
44 ram[17]<=14'd0;
45 ram[18]<=14'd0;
46 ram[19]<=14'd0;
47 ram[20]<=14'd0;
48 ram[21]<=14'd0;
49 ram[22]<=14'd0;
50 ram[23]<=14'd0;
51 ram[24]<=14'd0;
52 ram[25]<=14'd0;
53 ram[26]<=14'd0;
54 ram[27]<=14'd0;
55 ram[28]<=14'd0;
56 ram[29]<=14'd0;
57 ram[30]<=14'd0;
58 ram[31]<=14'd0;
59 ram[32]<=14'd0;
60 ram[33]<=14'd0;
61 ram[34]<=14'd0;
62 ram[35]<=14'd0;
63 ram[36]<=14'd0;
64 ram[37]<=14'd0;
65 ram[38]<=14'd0;
66 ram[39]<=14'd0;
67 ram[40]<=14'd0;
68 ram[41]<=14'd0;
69 ram[42]<=14'd0;
70 ram[43]<=14'd0;
71 ram[44]<=14'd0;
72 ram[45]<=14'd0;
73 ram[46]<=14'd0;
74 ram[47]<=14'd0;
75 ram[48]<=14'd0;
76 ram[49]<=14'd0;
77 ram[50]<=14'd0;
78 ram[51]<=14'd0;
79 ram[52]<=14'd0;
80 ram[53]<=14'd0;
81 ram[54]<=14'd0;
82 ram[55]<=14'd0;
83 ram[56]<=14'd0;
84 ram[57]<=14'd0;
85 ram[58]<=14'd0;
86 ram[59]<=14'd0;
87 ram[60]<=14'd0;
88 ram[61]<=14'd0;
89 ram[62]<=14'd0;
90 ram[63]<=14'd0;
91 end
92 else if(wr_rd==1'b1)
93 begin
94 ram[wr_addr]<=datain;
95 end
96
97 else
98 begin
99 end
100 end
101
102 assign dataout=(!wr_rd) ? ram[rd_addr] : 14'b0;
103 endmodule
104
105
106
107
108
109
110
111
112
113
ram的代码比较简单。
顶层代码:
top
1 `timescale 1ps / 1ps
2 module idct_ram_control(
3 clk,
4 rst_n,
5 datain,
6 datain_en,
7 dataout,
8 dataout_en
9 );
10
11
12 input clk;
13 input rst_n;
14 input [13:0]datain;
15 input datain_en;
16 output [13:0]dataout;
17 output dataout_en;
18 //-----------------------------------------
19 reg [5:0]count_in;
20 always @(posedge clk or negedge rst_n)
21 if (!rst_n)
22 count_in<=6'd0;
23 else
24 if (datain_en==1'b1)
25 count_in<=count_in+1'b1;
26
27 reg dataout_en;
28 reg [5:0]count_out;
29 reg out_en;
30 always @(posedge clk or negedge rst_n)
31 if(!rst_n)
32 out_en<=1'b0;
33 else
34 begin
35 if (count_in==6'b111111 & count_out==6'b111111)
36 out_en<=1'b1;
37 else
38 begin
39 if (count_in==6'b111111 & datain_en==1'b1)
40 out_en<=1'b1;
41 if (count_out==6'b111111)
42 out_en<=1'b0;
43 end
44 end
45 always @(posedge clk or negedge rst_n)
46 if (!rst_n)
47 dataout_en<=1'b0;
48 else
49 dataout_en<=out_en;
50
51
52 always @(posedge clk or negedge rst_n)
53 if (!rst_n)
54 count_out<=1'b0;
55 else if (out_en==1'b1)
56 count_out<=count_out+1'b1;
57
58
59 reg [6:0]wr_count;
60 always@(posedge clk or negedge rst_n)
61 begin
62 if(!rst_n)
63 begin
64 wr_count<=1'b0000000;
65 end
66 else if((datain_en==1'b1))
67 begin
68 wr_count<=wr_count+1;
69 end
70 else
71 begin
72 wr_count<=wr_count;
73 end
74 end
75
76 reg [6:0]rd_count;
77 always@(posedge clk or negedge rst_n)
78 begin
79 if(!rst_n)
80 begin
81 rd_count[5:3]<=3'b000;
82 end
83 else if((dataout_en==1'b1))
84 begin
85 rd_count[5:3]<=rd_count[5:3]+1;
86 end
87 else
88 begin
89 rd_count[5:3]<=rd_count[5:3];
90 end
91 end
92
93 always@(posedge clk or negedge rst_n)
94 begin
95 if(!rst_n)
96 begin
97 rd_count[2:0]<=3'b000;
98 end
99 else if((dataout_en==1'b1)&&(rd_count[5:3]==3'b111))
100 begin
101 rd_count[2:0]<=rd_count[2:0]+1;
102 end
103 else
104 begin
105 rd_count[2:0]<=rd_count[2:0];
106 end
107 end
108
109 always@(posedge clk or negedge rst_n)
110 begin
111 if(!rst_n)
112 begin
113 rd_count[6]<=1'b0;
114 end
115 else if((dataout_en==1'b1)&&(rd_count[5:0]==6'b111111))
116 begin
117 rd_count[6]<=~rd_count[6];
118 end
119 else
120 begin
121 rd_count[6]<=rd_count[6];
122 end
123 end
124 wire [13:0]dout1,dout2;
125 idct_ram ram1(
126 .clk(clk),
127 .rst_n(rst_n),
128 .wr_rd((wr_count[6]==1'b0)),
129 .datain(datain),
130 .wr_addr(wr_count[5:0]),
131 .rd_addr(rd_count[5:0]),
132 .dataout(dout1)
133 );
134
135 idct_ram ram2 (
136 .clk(clk),
137 .rst_n(rst_n),
138 .wr_rd((wr_count[6]==1'b1)),
139 .datain(datain),
140 .wr_addr(wr_count[5:0]),
141 .rd_addr(rd_count[5:0]),
142 .dataout(dout2)
143 );
144
145 assign dataout=wr_count[6]?dout1:dout2;
146
147 endmodule
148
149
150
151
对于转秩的方法有多种:
1,写入一个数据,找到转秩之后的地址然后把数据存进去,在读的时候顺序读出就可以了。
2,写入的时候是顺序写入,读出的时候不是顺序读出,而是读出转秩之后的对于地址的数据。
这里采用第二种方法,在写入的时候是顺序写入,写地址(wr_count[5:0])依次递加。在读出的时候是读地址是每次累加8个,即rd_count[5:3]依次累加,当rd_count[5:3]累加到最大值的时候,rd_count[2:0]才累加一次。
在modelsim中仿真结果如下:
写入的数据位1-64,64个数据,在读出的时候是一次从列开始读出的,最后一行,1,9,17...........................