How to write consecutive case statements? - syntax-error

I got an assignment to make a 4-bit booth multiplier with unsigned inputs in Verilog.
I've only used verilog a few times before this, so I'm not too familiar in writing case statements in it.
module booth(ina,inb,out);
input [3:0] ina, inb;
output[7:0] out;
reg[2:0] p1,p2;
reg[5:0] temp1, temp2;
assign p1={inb[2],inb[1],0};
assign p2={inb[3],inb[2],inb[1]};
always #(*)
begin
out = 8'b00000000;
case(p1)
3'b000: temp1=0;
3'b010: temp1=ina;
3'b100:temp1=-2 * ina;
3'b110:temp1= -ina;
endcase
end
begin
case(p2)
3'b000,3'b111: temp2=0;
3'b001,3'b010: temp2=ina;
3'b011:temp2=2 * ina;
3'b100:temp2=-2 * ina;
3'b101,3'b110:temp2= -ina;
endcase
temp2 = temp2<<2;
end
assign out=temp1+temp2;
endmodule
How am I supposed to write two case statements in a row?
I get a syntax error:
syntax error near text: "begin"; expecting "endmodule". Check for and fix any syntax errors that appear immediately before or at the specified keyword.

There are several compile errors.
Your error message probably refers to the 2 consecutive begin/end blocks after your always statement. One way to fix this is to add a 2nd always statement. It is a good idea to separate the temp1 and temp2 logic this way.
I also get an error for p1 because you make a continuous assignment to it with an assign statement. You should declare the signal as a wire, not a reg. Change:
reg [2:0] p1,p2;
to:
wire [2:0] p1,p2;
Another problem is that you make multiple assignments to the out signal. I think you probably want to remove it from the always block.
Lastly, you need to use a sized constant for 0 in the p1 statement. Change:
assign p1={inb[2],inb[1],0};
to:
assign p1={inb[2],inb[1],1'b0};
This code compiles cleanly for me:
module booth (ina, inb, out);
input [3:0] ina, inb;
output [7:0] out;
wire [2:0] p1,p2;
reg [5:0] temp1, temp2;
assign p1 = {inb[2], inb[1], 1'b0};
assign p2 = {inb[3], inb[2], inb[1]};
always #(*) begin
case (p1)
3'b000: temp1 = 0;
3'b010: temp1 = ina;
3'b100: temp1 = -2 * ina;
3'b110: temp1 = -ina;
endcase
end
always #(*) begin
case(p2)
3'b000,3'b111: temp2 = 0;
3'b001,3'b010: temp2 = ina;
3'b011: temp2 = 2 * ina;
3'b100: temp2 = -2 * ina;
3'b101,3'b110: temp2 = -ina;
endcase
temp2 = temp2<<2;
end
assign out = temp1+temp2;
endmodule

Related

Error: this expression has type unit but an expression was expected of type int

I am trying to do this simple while loop but it's not working. It is giving me the following error:
this expression has type unit but an expression was expected of type
int
let function () =
let current = ref 0 in
let square = ref !current in
while(((square := !current * !current) mod 1000000) != 269696) do
current := !current +1
done;
!square
;;
First of all, function is a keyword in OCaml, you cannot use it to name your functions.
Also, the condition in the while loop is buggy:
this square := !current * !current is an assignment, which type is unit. It is a type error to use it as an argument of mod which takes two integers as input.
You should probably do the assignment inside the loop and only test !square mod 1000000 <> 269696 in the loop's condition.
Notice that i used the <> structural inequality, instead of the physical one != which by luck does the same thing for integers, but you should not use it unless you know that.

Conditional processing in proc sql(SAS) using a macro variable

I need to select the name of states that do not start with M if the the macro variable M=N but return only the names of states that start with M if macro variable is equal to any other variable using conditional processing.
for example:
%let M=N;
proc sql;
select states,profit,
case
when .....
else
end
from geography_dim
quit;
For the sake of argument, suppose you change the name of the macro variable M to something more ridiculously expressive, such as YN_OPTION_SELECT_M_STATES
%let YN_OPTION_SELECT_M_STATES = N;
proc sql;
select states,profit,
case
when .....
else
end
from geography_dim
/* add this */
where
("&YN_OPTION_SELECT_M_STATES" eq 'N' & STATE not like 'M%')
or
("&YN_OPTION_SELECT_M_STATES" ne 'N' & STATE like 'M%')
;
quit;
Revert to macro variable M if you must, however the code will be somewhat opaque.
It is not SQL but very simple in datastep. If you want check the staring with M macro values in that case "N" you can do like:
/*test data*/
data geography_dim ;
states="Aaaaa";profit=10;output;
states="Naaaa";profit=10;output;
run;
/*set macro variable*/
%let M=N;
/*check if you want*/
%put "&M";
/*your case in datastep*/
data test;
set geography_dim;
if substr(states,1,1) eq "&M" then profit=profit*10;
else profit=0;
run;
/* results
states profit
Aaaaa 0
Naaaa 100
*/

Crossing clock domain for rarly changing data

I need to connect a configuration module (running at slower clock) to a worker which runs at higher speed. Standard answer seems to be a FIFO but I thought I come up with a simpler solution which consumes less resources - with drawback of having much higher latency. Benefit for me is that I don't need to regenerate FIFO IP for each possible size of data. In RTL simulation it seems to work (I run into troubles using post-synthesis one unrelated to question).
Am I missing something or is the following code correct:
module fifo_int#( // This is bad name. I haven't come up with better yet
parameter type DATA = logic [31:0]
)(
input logic rst,
input logic clk_in,
input DATA din,
input logic clk_out,
output DATA dout
);
DATA dreg;
enum logic [1:0] {
IN,
STABLE,
WAIT_OUT
} in_state;
enum logic [1:0] {
WAIT_IN,
WRITE,
INV
} out_state;
logic in_output[3], out_output[3];
initial begin
in_state <= IN;
out_state <= WAIT_IN;
for (int i = 0; i < 3; i++) begin
in_output[i] <= 0;
out_output[i] <= 0;
end
end
always #(posedge clk_in)
begin
case (in_state)
IN: begin
dreg <= din;
in_state <= STABLE;
end
STABLE: begin
in_state <= WAIT_OUT;
in_output[0] <= ~in_output[0];
end
WAIT_OUT: begin
in_state <= (in_output[0] == out_output[2]) ? IN : WAIT_OUT;
end
endcase
out_output[1] <= out_output[0];
out_output[2] <= out_output[1];
end
always #(posedge clk_out)
begin
case (out_state)
WAIT_IN: begin
out_state <= (in_output[2] == out_output[0]) ? WAIT_IN : WRITE;
end
WRITE: begin
dout <= dreg;
out_state <= INV;
end
INV: begin
out_output[0] <= ~out_output[0];
out_state <= WAIT_IN;
end
endcase
in_output[1] <= in_output[0];
in_output[2] <= in_output[1];
end
endmodule
If your clocks are asynchronous, you're going to need synchronization.
For synchronous clocks, since your slow side is the one producing the data, you don't need any buffering. Data is anyway held stable for multiple (fast) clock cycles, so you don't really need any logic between the domains.

Input value If macro variable exists else some other value

The need is to perform valuation of a macro variable outside datastep and depending on the existence of the variable, perform insertion:
data my_dataSet;
set ...
....
if %SYMEXIST(Variable_from_prior_code) = 1 then do;
dataset_variable = &Variable_from_prior_code.;
end;
else do;
dataset_variable = &Some_default_value_from_prior_code;
end;
However, this fails at compiler when trying to run it as the " Apparent symbolic reference &Variable_from_prior_code." has not been resolved. Ie. the compiler checks the contents of the if statement even as the condition is not met.
I came up with silly work-around: to approach this from opposite directon, but feels more stupid than bag of badgers:
if %SYMEXIST(Variable_from_prior_code) = 0 then do;
dataset_variable = &Some_default_value_from_prior_code
%let Variable_from_prior_code=0; /*Dummy value*/
end;
else do;
dataset_variable = &Variable_from_prior_code.;
end;
Any way to restrict the compiler from evaluating content, which it shouldn't due to condition?
Or alternatively, more elegant work-around, which do not require creation of the variable?
I'd say, avoid macro logic unless necessary! Here's a pure data step approach:
%symdel Variable_from_prior_code; /* make sure variable does not exist */
%let Some_default_value=test; /* populate macro variable */
data my_dataSet;
if SYMEXIST('Variable_from_prior_code') = 1 then do; /* use data step function */
/* note variable name is quoted, else would reference a data step variable value */
dataset_variable = symget('Variable_from_prior_code');
end;
else do;
/* had to shorten this name to less than max allowed 32 chars */
dataset_variable = symget('Some_default_value');
end;
run;
As Tom mentions, you are currently mixing up macro and data step logic. Macro is used to write data step code (so is essentially a program generator), and that resultant data step code is executed long after the macro statements are compiled / resolved / executed.

opening a cursor after some code

I have some Stored Procedure in DB2. Some lines of code (INSERT, UPDATE etc). After some operations I have IF condition that opening/not opening CURSOR. For some reason the CURSOR is not opened even if IF condition is TRUE. All the code before the CURSOR works fine. If I'll remove it, so the CURSOR will works fine. If I'll put the CURSOR in separate SP, it works fine (calling for another SP from this SP). But together for some reason it not works. I can't understand why. I need this code for the IF condition.
That's how it looks (only 1 row with INSERT left outside the CURSOR):
DECLARE C1 CURSOR WITH HOLD FOR
SELECT s.KEY, s.CODE, s.PRODUCT, s.AMOUNT
FROM DB2ADMIN.SALES s, DB2ADMIN.PRODUCTS p
WHERE s.DATE_KEY = CDC AND s.PRODUCT_KEY = p.PRODUCT_KEY;
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET EOF = 1;
INSERT INTO DB2ADMIN.IA_BASE_SALES_TMP (SOME_FIELD) VALUES (SOME_VALUE);
IF true THEN
OPEN C1;
WHILE EOF = 0 DO
FETCH FROM C1 INTO SP_KEY, SP_CODE, SP_KEY, SP_PRODUCT, SP_AMOUNT;
MERGE INTO DB2ADMIN.IA_BASE_SALES_TMP t
USING (
SELECT POS, p.KEY, s.TELLER, s.TYPE, s.AMOUNT, s.CDC
FROM DB2ADMIN.COMMISSIONS s, DB2ADMIN.PRODUCTS p
WHERE TELLER = SP_TELLER AND TYPE = SP_TYPE
) e ON t.TELLER_KEY = e.TELLER_ID
WHEN matched
THEN UPDATE SET t.KEY = e.KEY, t.UPD = 0;
END WHILE;
CLOSE C1;
END IF;
Thanks to Jean.
Replacing the cursor with FOR loop and everything works OK.