module data_mem(
input clk,
input [31:0] addr,
input [31:0] wdata,
input wr_en,
input rd_en,
output [31:0] rdata
);
reg [7:0] Mem [255:0];
assign rdata = rd_en ? Mem[addr]:32'bxxxxxxxx;
always # (posedge clk) begin
if (wr_en)
Mem[addr] <= wdata;
end
endmodule
Want to assign 4 bytes Mem[3:0] to wdata for write when wr_en flag is 1.
more accurately Mem[addr+3: addr]. how can i do this?
Three options:
Use concatenations: {Mem[addr+3],Mem[addr+2],Mem[addr+1],Mem[addr]} <= wdata;
Explicit range selection:
begin
Mem[addr+3] <= wdata[31:24];
// other assigments
Mem[addr] <= wdata[7:0];
end
Or you can Indexing vectors and arrays with +: which allows for(i=0;i<4;i=i+1) Mem[addr+i] <= wdata[i*8 +: 8]
Related
I am trying to delay a 32-bit signal using shift register. My logic is a single flip flop delay a signal by 1 clk so I use shift register as it is combination of flip flop can someone guide me what is wrong with this code.
module delay_n_cycles (
input wire [31:0] data_in,
input wire clk,
output reg [31:0] data_out,
parameter N = 5
);
reg [31:0] shift_reg;
always #(posedge clk) begin
shift_reg <= {shift_reg[30:0], data_in};
if (N == 0) begin
data_out <= shift_reg[31];
end else begin
data_out <= shift_reg[N-1];
end
end
endmodule
First of all, your code is syntactically wrong. parameter cannot be declared in a way you provided.
Your shift register is only 32 bit wide. Usually, to delay multi-bit data this way, you need to keep N copies of data in the register, shift them at one end and read at the other. I guess the following should help:
module delay_n_cycles #(parameter N = 5)(
input wire [31:0] data_in,
input wire clk,
output reg [31:0] data_out
);
reg [N-1:0][31:0] shift_reg;
always #(posedge clk) begin
shift_reg <= (shift_reg << 32) | data_in;
data_out <= shift_reg[N-1];
end
endmodule
This code will work with system verilog because it used packed multi-dimensional arrays.
You need to shift the reg by 32 (width of the data) in packed version.
Here is an example of a testbench:
module tb();
bit clk;
int clkCount;
initial
forever begin
#5 clk = ~clk;
clkCount++;
end
logic [31:0] data_in, data_out;
initial begin
$monitor("%0t (%0d) [%h]: %0d --> %0d", $time, clkCount, ds.shift_reg[4], data_in, ds.data_out);
for(int i = 0; i < 20; i++) begin
#10 data_in = i;
end
$finish;
end
delay_n_cycles ds(data_in, clk, data_out);
endmodule
I am trying to assign ADDR to pcOut but ADDR is showing up as xxxxxxxx in GTKWave.
Here is my code:
module processor (
input CLK,
// Memory
input [31:0] DATAOUT, // Memory data out
output [31:0] DATAIN, // Memory data in
output [31:0] ADDR, // Memory address
output WE // Memory write enable
);
wire [3:0] aluSel;
wire [4:0] regSel1, regSel2, regDataSel;
wire regLoad, aluEnable, pcLoad, pcNext;
wire [31:0] regDataIn, regDataOut1, regDataOut2, aluOut, pcOut, pcIn, aluA, aluB;
assign ADDR = pcOut;
controlUnit controlUnit (
.CLK(CLK), // Clock
// Outputs
.memDataOut(DATAOUT),
.regDataOut1(regDataOut1),
.regDataOut2(regDataOut2),
.aluOut(aluOut),
.pcOut(pcOut),
// Load and enable
.pcLoad(pcLoad),
.regLoad(regLoad),
.aluEnable(aluEnable),
.pcNext(pcNext),
// Selects
.aluSel(aluSel),
.regSel1(regSel1),
.regSel2(regSel2),
.regDataSel(regDataSel),
// Inputs
.pcIn(pcIn),
.regDataIn(regDataIn),
.aluA(aluA),
.aluB(aluB),
.memDataIn(DATAIN),
.memAddr(ADDR)
);
datapath datapath (
.pcNext(pcNext),
// Load and enable
.pcLoad(pcLoad),
.regLoad(regLoad),
.aluEnable(aluEnable),
// Selects
.aluSel(aluSel),
.regSel1(regSel1),
.regSel2(regSel2),
.regDataSel(regDataSel),
// Inputs
.regDataIn(regDataIn),
.pcIn(pcIn),
.aluA(aluA),
.aluB(aluB),
// Outputs
.regDataOut1(regDataOut1),
.regDataOut2(regDataOut2),
.aluOut(aluOut),
.pcOut(pcOut)
);
endmodule
Can anyone help?
Thanks in advance.
Edit:
pcOut is outputting the correct value but ADDR is not being set that same value.
Edit 2:
Here is the code for the controlUnit module:
module controlUnit (
input CLK,
input [31:0] memDataOut, regDataOut1, regDataOut2, aluOut, pcOut,
output reg [0:0] pcLoad, regLoad, aluEnable, pcNext,
output reg [3:0] aluSel,
output reg [4:0] regSel1, regSel2, regDataSel,
output reg [31:0] pcIn, regDataIn, aluA, aluB, memDataIn, memAddr
);
reg cycle = 0;
wire [10:0] opcode;
wire [4:0] rs1, rs2, rd;
decoder decoder (
.cycle(cycle),
.instruction(memDataOut),
.rs1(rs1),
.rs2(rs2),
.rd(rd),
.opcode(opcode)
);
always #(posedge CLK) begin
case (cycle)
1'b0: begin
regLoad <= 0;
aluEnable <= 0;
pcNext <= 0;
end
1'b1: begin
pcNext <= 1;
case (opcode)
11'b00000110011: begin // Add
regSel1 <= rs1;
regSel2 <= rs2;
regDataSel <= rd;
aluSel <= 0;
aluEnable <= 1;
regDataIn <= aluOut;
regLoad <= 1;
end
11'b10000110011: begin // Sub
end
endcase
end
endcase
cycle <= !cycle;
end
endmodule
Your controlUnit doesn't seem to have any logic attached to memAddr, but memAddr is still an output of controlUnit. At the top level, you port map ADDR to .memAddr, and you also assign ADDR = pcOut. You're trying to drive ADDR in two different locations.
parameter N1 = 5;
parameter N2 = 5;
wire [(N1+N2-1):0] seckey [8:1];
shiftreg #(.depth(N1+N2-1)) sr1( .clk(clk), .reset(reset), .data_in(muxout[1]), .data_out(seckey[0]));
//--------------------------------------------------------------------------//
module shiftreg(
input clk,
input reset,
input data_in,
output data_out
);
parameter depth = 9;
wire [depth:0] connect_wire;
wire [depth:0] data_out;
//wire [depth:0] data_out;
assign connect_wire[0] = data_in;
assign data_out[depth:0] = connect_wire[depth:0];
genvar i;
generate
for(i=1; i<=depth; i=i+1) begin: loop1
ff dff(.d(connect_wire[i-1]), .clk(clk), .reset(reset), .q(connect_wire[i]));
end
endgenerate
endmodule
//--------------------------------------------------------------------//
module ff(
input d,
input clk,
input reset,
output reg q
);
always # (posedge clk or posedge reset)
begin
if (reset) begin
q <= 1'b0;
end
else begin
q <= d;
end
end
endmodule
//------------------------------------------------------------------------//
Value of N1 and N2 is 5.
I am getting the error "Size mismatch in connection of port (data_out). Formal port size is 10-bit while actual signal size is 1-bit"
I have set the size of the data_out port to be 10 bits but its still showing the signal size to be 1 bit.
To set the size of data_out, you need to set the size where you declare the parameter. Try the header below
module shiftreg(clk, reset, data_in, data_out);
parameter depth = 9;
input clk;
input reset;
input data_in;
input [depth:0] data_out;
Also:
assign data_out[depth:0] = connect_wire[depth:0];
can be replaced with
assign data_out = connect_wire;
I am trying to make serializer from 32bits to 8 bits. Because I am just starting verilog I am facing problem. I would like to get 32 bits (on every 4th clock cycles) and then to send 8 bits on every clock cycle. How can I take just part of my dataIn, I wrote code below but assignment expression is not working. Sorry if question is basic. Thank you in advance on answer.
module ser32to8(clk, dataIn, dataOut);
input clk;
input [32:0] dataIn;
output [7:0] dataOut;
always #(posedge clk)
begin
dataOut <= dataIn << 8;
end
endmodule
The reason why the assignment failed (besides your code not doing any serialization) is because you didn't declare dataOut as a reg, and so you cannot assign to it inside an always block.
Here's how you do it correctly. (Since you didn't say in which order you wanted to serialize, I chose to go for lowest byte first, highest byte last. To reverse the order, exchange >> by << and tmp[7:0] by tmp[31:24].)
module ser32to8(
input clk,
input [31:0] dataIn,
output [7:0] dataOut
);
// count: 0, 1, 2, 3, 0, ... (wraps automatically)
reg [1:0] count;
always #(posedge clk) begin
count <= count + 2'd1;
end
reg [31:0] tmp;
always #(posedge clk) begin
if (count == 2'd0)
tmp <= dataIn;
else
tmp <= (tmp >> 8);
end
assign dataOut = tmp[7:0];
endmodule
How can you just take part of your dataIn data? By using the [] notation. dataIn[7:0] takes the 8 least significant bits, dataIn[15:8] takes the next 8 bits, and so on up to dataIn[31:24] which would take the 8 most significant bits.
To apply this to your problem, you can do like this (take into account that this is not an optimal solution, as outputs are not registered and hence, glitches may occur)
module ser32to8(
input wire clk,
input wire [31:0] dataIn,
output reg [7:0] dataOut
);
reg [1:0] cnt = 2'b00;
always #(posedge clk)
cnt <= cnt + 1;
always #* begin
case (cnt)
2'd0: dataOut = dataIn[7:0];
2'd1: dataOut = dataIn[15:8];
2'd2: dataOut = dataIn[23:16];
2'd3: dataOut = dataIn[31:24];
default: dataOut = 8'h00;
endcase
end
endmodule
You must declare dataOut as a reg, since you are using it in always block.Also, you are trying to assign 32 bit datain to 8 bit dataout , it is not logically correct.
The idea behind the question is not so clear but my guess would be that you want to wait for 4 clock cycles before you send the data, if that is the case below snippet could help, A counter to wait before 4 clock cycles will do the trick
module top (input clk,rst,
input [31:0] dataIn,
output [7:0] dataOut
);
reg [31:0] tmp;
reg [31:0] inter;
integer count;
always #(posedge clk)
begin
if (rst) begin
count <= 0;
tmp <= '0;
end
else
begin
if (count < 3) begin
tmp <= dataIn << 4;
count <= count +1; end
else if (count == 3)
begin
inter <= tmp;
count <= 0;
end
else
begin
tmp <= dataIn;
end
end
end
assign dataOut = inter[7:0];
endmodule
But there are some limitations tested with tb http://www.edaplayground.com/x/4Cg
Note: Please ignore the previous code it won't work(I was not clear so
tried it differently)
EDIT:
If I understand your question correctly a simple way to do it is
a)
module top ( input rst,clk,
input [31:0] dataIn,
output [7:0] dataOut);
reg [1:0] cnt;
always #(posedge clk) begin
if (rst) cnt <= 'b0;
else cnt <= cnt + 1;
end
assign dataOut = (cnt == 0) ? dataIn [7:0] :
(cnt == 1) ? dataIn [15:8] :
(cnt == 2) ? dataIn [23:16] :
(cnt == 3) ? dataIn [31:24] :
'0;
endmodule
Incase if you don't want to write it seperately for loop will come in handy to make it more simple
b)
module top ( input rst,clk,
input [31:0] dataIn,
output reg [7:0] dataOut);
reg [1:0] cnt;
integer i;
always #(posedge clk) begin
if (rst) cnt <= 'b0;
else cnt <= cnt + 1;
end
always # * begin
for ( i =0;i < cnt ; i=i+1) begin
dataOut <= dataIn[(i*8)+:8]; end
end
endmodule
I have tried both with test cases and found to be working, tc's present #
a) http://www.edaplayground.com/x/VCF
b) http://www.edaplayground.com/x/4Cg
You may want to give it a try
You can follow the figure below to design your circuit. Hope it can be useful with you. If you need the code, feel free to contact me.
SER 112 bits with 8 outputs in parallel
I'm trying to calculate times in which input x with 8 bits is repeated on every posedge clk.
I'm thinking about creating 256b counter to each value of these 8 bit to compare x with it, but I get error when I'm trying to compare each value of these counter with each input x on rising edge.
module counter_initial(x);
input[7:0] x;
//output [7:0] y;
//reg [7:0] y;
//reg [7:0] freq_tst,gap_tst;
reg [7:0] freq_num;
endmodule
module counter_256(clk,x,out);
input [7:0] x;
input clk;
// input [7:0] in;
output [7:0] out;
reg [7:0] out;
//reg [7:0] freq_tst,gap_tst;
reg [7:0] k=0;
// reg [] t=0;
genvar i;
generate
for (i=0;i<256;i=i+1)
begin
counter_initial m(i);
//t=m(i);
end
endgenerate
always #(posedge clk)
begin
if(k<256) begin
if (x==m[i])
//counter_initial[k]==x
begin
freq_num=freq_num+1;
end
//else
//begin gap_tst=gap_tst+1; end
k=k+1;
end
end
endmodule
You don't need an additional module to count. You can use a memory array. Example:
input [WIDTH-1:0] x;
reg [7:0] mem [WIDTH-1:0];
integer i;
always #(posedge clk) begin
if (reset) begin
for (i = 0; i < 2**WIDTH; i = i+1) begin
mem[i] <= 8'b0;
end
end
else if (mem[x] < 8'd255) begin // cap counting and prevent overflow
mem[x] <= mem[x] + 1'b1;
end
end
If you want to use separate modules then pass the clock to it. Example:
module counter (output reg [7:0] count, input increment, clk, reset);
always #(posedge clk) begin
if (reset) begin
count <= 8'b0;
end
else if (count < 8'd255) begin // cap counting and prevent overflow
count <= count + increment;
end
end
endmodule
module my_device ( /* ..., */ input [7:0] x, input clk, reset );
/* ... */
genvar i;
generate
for (i=0; i<256; i=i+1) begin
counter icount( .count(/* ... */), .increment(x==i), .* );
end
endgenerate
/* ... */
endmdoule
Reminder 8'd255 + 1 is 8'd0 because the MSB of 8'd256 is out of range. I capped the counters so the will not overflow and roll back to zero.